vapi: add Customer Phone Number prop to create-call (outbound calls were impossible)#21084
Conversation
The create-call action sent only assistantId, squadId, phoneNumberId,
name and customerId to POST /call. The Vapi API requires a destination
via customer: { number } (or customerId), but Vapi has no customer CRUD,
so every outbound phone call failed with:
400: Couldn't Get Customer. Need Either `customerId` Or `customer`.
- create-call: optional Customer Phone Number prop (E.164) sent as
customer: { number }, plus an early ConfigurationError mirroring the
API requirement
- vapi.app.mjs: phone number options labeled as "name (number)" so
auto-named numbers are distinguishable
- version bumps
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
|
Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds optional ChangesVapi Component Enhancements
Sequence Diagram(s)sequenceDiagram
participant CreateCallRun as CreateCall.run
participant Validator as run validation
participant PayloadBuilder as startConversation payload
participant VapiAPI as Vapi API
CreateCallRun->>Validator: ensure customerId or customerNumber
Validator-->>CreateCallRun: validated
CreateCallRun->>PayloadBuilder: construct payload (customerId, customer?: { number })
PayloadBuilder->>VapiAPI: POST /startConversation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@components/vapi/actions/create-call/create-call.mjs`:
- Around line 49-54: The description for the customerNumber prop uses bolded
**Customer ID**, which could be mistaken for a tool name; update the text in the
customerNumber property (the label "Customer Phone Number" / property key
customerNumber) to reference the other prop plainly (e.g., "Customer ID" without
bolding or by using the exact prop name customerId) and reword the sentence to
say "The API requires either this or the customerId property for outbound phone
calls" so it's unambiguous to agents.
In `@components/vapi/vapi.app.mjs`:
- Around line 54-61: phoneNumberId.async options() currently fetches only a
single page (limit: LIMIT) and ignores prevContext/page, causing truncated
dropdowns; update this function to use the existing async *paginate() helper (or
replicate its logic) so it consumes prevContext and params.page and iteratively
requests GET /phone-number using the response pagination metadata
(meta.current_page / meta.last_page or currentPage) to load additional pages,
accumulating or yielding mapped option objects (preserving the label/value
mapping) until all pages are fetched, and return the combined context for next
calls; ensure prevContext/page are passed through and that paginate()'s
cursor/state is returned so load-more works.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 42d122ef-2432-4144-8a41-e0eb2befcda7
📒 Files selected for processing (4)
components/vapi/actions/create-call/create-call.mjscomponents/vapi/actions/list-phone-number-id-options/list-phone-number-id-options.mjscomponents/vapi/package.jsoncomponents/vapi/vapi.app.mjs
| return phoneNumbers.map(({ | ||
| id: value, name: label, | ||
| id: value, name, number, | ||
| }) => ({ | ||
| label, | ||
| label: (name && number) | ||
| ? `${name} (${number})` | ||
| : (name ?? number ?? value), | ||
| value, | ||
| })); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if other propDefinitions in this app use pagination
# Search for propDefinitions that use the paginate helper
rg -n -A10 'async options\(' components/vapi/vapi.app.mjs | rg -C3 'paginate'Repository: PipedreamHQ/pipedream
Length of output: 47
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="components/vapi/vapi.app.mjs"
echo "=== phoneNumberId propDefinition area (approx lines 1-120) ==="
nl -ba "$FILE" | sed -n '1,140p'
echo
echo "=== Look for prevContext/page usage in vapi.app.mjs ==="
rg -n --hidden --no-ignore-vcs -S "prevContext|\\bpage\\b" "$FILE" || true
echo
echo "=== Find paginate helper definition / usage in vapi.app.mjs ==="
rg -n "paginate" "$FILE" || true
echo
echo "=== Find phone-number API calls & pagination-related params ==="
rg -n -S "phone[-_ ]?number|phoneNumber|/phone-number" "$FILE" || true
rg -n -S "limit|offset|starting_after|startingAfter|cursor|page|has_more|next_" "$FILE" || trueRepository: PipedreamHQ/pipedream
Length of output: 189
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="components/vapi/vapi.app.mjs"
echo "=== phoneNumberId propDefinition area (start of file through ~140) ==="
cat -n "$FILE" | sed -n '1,140p'
echo
echo "=== Look for prevContext/page usage in vapi.app.mjs ==="
rg -n --hidden --no-ignore-vcs -S "prevContext|\\bpage\\b" "$FILE" || true
echo
echo "=== Find paginate helper definition / usage in vapi.app.mjs ==="
rg -n "paginate" "$FILE" || true
echo
echo "=== Find phone-number API calls & pagination-related params ==="
rg -n -S "phone[-_ ]?number|phoneNumber|/phone-number" "$FILE" || true
rg -n -S "limit|offset|starting_after|startingAfter|cursor|page|has_more|next_" "$FILE" || trueRepository: PipedreamHQ/pipedream
Length of output: 5033
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="components/vapi/vapi.app.mjs"
echo "=== paginate() implementation (approx lines 120-220) ==="
cat -n "$FILE" | sed -n '120,220p'
echo
echo "=== Find uses of paginate() within vapi components ==="
rg -n "this\\.paginate\\(|\\.paginate\\(" components/vapi -S || true
echo
echo "=== Find any async options() in vapi components that use prevContext/page ==="
rg -n --glob='components/vapi/**/*.{mjs,js,ts}' "async options\\(\\)|prevContext|\\bpage\\b" -S || true
echo
echo "=== Find other uses of listPhoneNumbers in vapi components ==="
rg -n --glob='components/vapi/**/*.{mjs,js,ts}' "listPhoneNumbers\\(" -S || trueRepository: PipedreamHQ/pipedream
Length of output: 1890
🌐 Web query:
Vapi API GET /phone-number pagination params current_page last_page page limit
💡 Result:
Vapi API GET /phone-number pagination params (list phone numbers) 1) Query parameters - limit: maximum number of items to return (defaults to 100) [1] 2) Pagination fields returned in response.metadata - currentPage: current page number (from PaginationMeta) [2][3] 3) Your requested params - current_page: not used as a request query param name; the request uses limit, and the response metadata uses currentPage [1][2] - last_page: not documented as a request query parameter or returned pagination field for phone numbers; only currentPage (plus itemsPerPage and totalItems) is shown in PaginationMeta [2] - page: not shown as a query parameter for the phone-number list endpoint in the official docs; the endpoint documents limit (and filtering fields), not page-based params [1] If you want, paste an example of the response JSON you’re getting for list phone numbers and I can map exactly which pagination fields are present in your case.
Citations:
- 1: https://docs.vapi.ai/api-reference/phone-numbers/list
- 2: https://rubydoc.info/gems/vapi_server_sdk/0.4.0/Vapi/PaginationMeta
- 3: https://rubydoc.info/gems/vapi_server_sdk/0.4.0/Vapi/PhoneNumberPaginatedResponse
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search repo for vapi phone-number usage ==="
rg -n --glob='components/**/*.{mjs,js,ts}' -S "path: \"/phone-number\"|/phone-number" components/vapi components -S || true
echo
echo "=== Search for current_page/last_page/meta usage in vapi app/components ==="
rg -n --glob='components/vapi/**/*.{mjs,js,ts}' -S "current_page|last_page|meta: \\{|next|has_more" || true
echo
echo "=== Search for phoneNumberId propDefinition usage ==="
rg -n --glob='components/vapi/**/*.{mjs,js,ts}' -S "phoneNumberId" || trueRepository: PipedreamHQ/pipedream
Length of output: 2467
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n --glob='components/vapi/**/*.{mjs,js,ts}' "phoneNumberId\\.options" components/vapi || true
echo "=== Inspect components/vapi/actions/list-phone-number-id-options/list-phone-number-id-options.mjs ==="
FILE="components/vapi/actions/list-phone-number-id-options/list-phone-number-id-options.mjs"
cat -n "$FILE" | sed -n '1,200p'Repository: PipedreamHQ/pipedream
Length of output: 1149
Add load-more pagination support to phoneNumberId options()
components/vapi/vapi.app.mjs’s phoneNumberId.async options() fetches only limit: LIMIT and doesn’t accept/use prevContext or page. The app already has an async *paginate() helper (using params.page and meta.current_page/last_page), but it isn’t used here; meanwhile GET /phone-number returns pagination metadata (e.g., currentPage), so this dropdown may silently truncate results. Wire prevContext/page into phoneNumberId.options() (likely via paginate()), or explicitly justify why pagination can’t be requested for this endpoint. See the documentation
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@components/vapi/vapi.app.mjs` around lines 54 - 61, phoneNumberId.async
options() currently fetches only a single page (limit: LIMIT) and ignores
prevContext/page, causing truncated dropdowns; update this function to use the
existing async *paginate() helper (or replicate its logic) so it consumes
prevContext and params.page and iteratively requests GET /phone-number using the
response pagination metadata (meta.current_page / meta.last_page or currentPage)
to load additional pages, accumulating or yielding mapped option objects
(preserving the label/value mapping) until all pages are fetched, and return the
combined context for next calls; ensure prevContext/page are passed through and
that paginate()'s cursor/state is returned so load-more works.
There was a problem hiding this comment.
Skipping this one - three reasons:
GET /phone-numberreturns a plain array, not the{ data, meta: { current_page, last_page } }shape the existingpaginate()helper consumes, so it can't be reused for this endpoint (Vapi usescreatedAtLtcursor pagination on these list endpoints).- The single-page fetch is pre-existing behavior shared identically by the
assistantIdandsquadIdpropDefinitions, which this PR doesn't touch - the diff only changes the label mapping. LIMITis already 1000, the documented per-request maximum, so truncation only occurs for accounts with 1000+ phone numbers.
Happy to address pagination across all three propDefinitions in a separate PR if maintainers want it.
There was a problem hiding this comment.
@VibhanshuPandey, all three points are well-reasoned — thanks for the detailed explanation. The mismatch between the plain-array response shape and the paginate() helper's expected { data, meta: { current_page, last_page } } structure is the key blocker, and since LIMIT is already at the API's documented maximum of 1000, the practical impact is minimal. Deferring a proper cursor-based pagination refactor across all three propDefinitions to a follow-up PR makes sense.
Would you like me to open a GitHub issue to track that follow-up work (pagination for phoneNumberId, assistantId, and squadId propDefinitions using createdAtLt cursor pagination)?
🐇 ( ˘ᵕ˘) noted and filed away
✏️ Learnings added
Learnt from: VibhanshuPandey
Repo: PipedreamHQ/pipedream PR: 21084
File: components/vapi/vapi.app.mjs:54-61
Timestamp: 2026-06-06T09:48:46.537Z
Learning: In `components/vapi/vapi.app.mjs`, the Vapi `GET /phone-number`, `GET /assistant`, and `GET /squad` list endpoints all return plain arrays, NOT the `{ data, meta: { current_page, last_page } }` shape that the existing `async *paginate()` helper in the same file consumes. Vapi uses `createdAtLt` cursor pagination on these list endpoints. Therefore, the existing `paginate()` helper CANNOT be used for `phoneNumberId`, `assistantId`, or `squadId` propDefinition `async options()`. The `LIMIT` constant is 1000, the documented per-request maximum for these endpoints, so truncation only affects accounts with more than 1000 records. Do not flag the absence of `prevContext`/`page` pagination in these three propDefinitions as a blocker until a proper cursor-based pagination implementation is available.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/*/*.app.mjs : Prop definitions in app files must include both `label` and `description`. If a definition includes `async options()` that calls a paginated API endpoint, it must support `prevContext` or `page`.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/**/*.mjs : Prop descriptions must describe the expected format for non-obvious values (dates, IDs, JSON structures, enum strings), include concrete examples for JSON objects or constructed values, explain where to get IDs if the user might only have a name or URL, avoid UI language like "select from the dropdown", and point to discovery tools when valid values must be looked up
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/**/*.mjs : Every prop definition with `async options()` that calls a paginated API endpoint must support `prevContext` or `page` (starts at 0) for "load more" functionality
Learnt from: s0s0physm
Repo: PipedreamHQ/pipedream PR: 0
File: :0-0
Timestamp: 2026-04-29T23:16:37.561Z
Learning: In the Stripe list actions (e.g., `components/stripe/actions/list-customers/list-customers.mjs`, `list-invoices`, `list-payouts`, `list-balance-history`, `list-refunds`, `list-payment-intents`), pagination metadata (`has_more`, `next_starting_after`) is exposed via an opt-in boolean prop `returnPaginationInfo` (default `false`). When `false`, actions return `Array<T>` exactly as before (no breaking change). When `true`, actions fetch `limit + 1` items, trim to `limit`, derive `has_more`, and return `{ data, has_more, next_starting_after }`. This opt-in design makes the version bump `0.1.4` → `0.2.0` (MINOR, not MAJOR) correct per Pipedream semver guidelines. Do not flag this as a breaking change or suggest a major version bump.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20911
File: components/freshchat/actions/list-agent-id-options/list-agent-id-options.mjs:16-22
Timestamp: 2026-05-18T18:55:29.937Z
Learning: In PipedreamHQ/pipedream, for list-options utility action components under `components/<app>/actions/list-*-options/`, the `page` integer prop does NOT require a `max` constraint. Only a `min: 0` and `default: 0` are needed. Do not flag the absence of a `max` value on page pagination props in these components.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-source-guidelines.md:0-0
Timestamp: 2026-04-13T20:20:15.870Z
Learning: Applies to **/*source*.{js,ts} : Paginate through all new items when the API supports pagination — do not stop after the first page
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 14137
File: components/tricentis_qtest/tricentis_qtest.app.mjs:39-54
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The Tricentis qTest API endpoint used for fetching requirements does not support pagination, so pagination is unnecessary in the `options` method for `requirementId`.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 14137
File: components/tricentis_qtest/tricentis_qtest.app.mjs:39-54
Timestamp: 2024-09-29T22:37:26.269Z
Learning: The Tricentis qTest API endpoint used for fetching requirements does not support pagination, so pagination is unnecessary in the `options` method for `requirementId`.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20865
File: components/envoy/actions/list-employee-id-options/list-employee-id-options.mjs:17-23
Timestamp: 2026-05-14T19:04:45.522Z
Learning: In PipedreamHQ/pipedream, for lightweight "list prop options" utility action components (actions under `components/<app>/actions/list-*-options/` whose sole purpose is to retrieve and return available options for a prop field), it is NOT necessary to pass the `$` context into `propDefinitions.options.call(this.<app>)` calls or the underlying API methods they invoke (e.g., `listEmployeesOps()`). The `$` context requirement is waived for these read-only utility actions since they are simple option-retrieval helpers.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20678
File: components/moodle/actions/search-users/search-users.mjs:16-40
Timestamp: 2026-04-28T18:14:58.414Z
Learning: For Pipedream component files under components/**/*.mjs: the "[See the documentation](...)" link is required only in the top-level component `description` field. For any individual prop `description` fields, write the description specifically for AI agent consumption—include concrete inline examples. Prop `description` fields do not need to end with a documentation link.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20832
File: components/getty_images/common/constants.mjs:1-74
Timestamp: 2026-05-11T22:13:55.006Z
Learning: In Pipedream component files under `components/**/*.mjs`, follow this naming convention: use `UPPER_SNAKE_CASE` for module-level constants (e.g., option arrays like `IMAGE_TYPE_OPTIONS`, `ORIENTATION_OPTIONS`). For all other identifiers, use `camelCase`—specifically local variables inside functions/methods, prop names, and method names. `UPPER_SNAKE_CASE` at module scope for constants is an accepted convention in this codebase and should not be flagged.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20853
File: components/surecart/actions/create-checkout/create-checkout.mjs:7-7
Timestamp: 2026-05-13T17:22:52.552Z
Learning: When reviewing a connector “fix/republish” PR in PipedreamHQ/pipedream, a breaking input-contract change in the republished connector/component should NOT automatically trigger a major version bump if the previous connector/component version was never successfully published (e.g., the publish pipeline failed with a UserError). In that case, a patch bump is acceptable (e.g., 0.0.1 → 0.0.2) because no users could have relied on the unpublished interface. Before flagging an incorrect bump level, verify the prior version’s unpublished status using the PR description and/or linked issue(s).
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20884
File: components/jira_data_center/actions/list-filter-id-options/list-filter-id-options.mjs:1-1
Timestamp: 2026-05-15T16:31:34.394Z
Learning: When reviewing Pipedream component files, do not require the imported app module identifier (the local import variable) to be snake_case. Both snake_case and camelCase local import variable names are acceptable (e.g., `import jiraDataCenter from "../../jira_data_center.app.mjs"` is fine even if the app filename uses `jira_data_center`). However, ensure the key(s) used in the component’s `props` object match exactly what the referenced app module exports; mismatches between the app’s exported prop name(s) and the component `props` keys should be flagged. The local import variable name itself is flexible as long as `props` keys align with the app exports.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20884
File: components/youtube_data_api/actions/list-language-options/list-language-options.mjs:1-1
Timestamp: 2026-05-15T19:23:37.145Z
Learning: For Pipedream component files under `components/**/*.mjs`, follow `pipedream-component-guidelines.md`: require camelCase for all prop names, method names, and local variables (including import identifiers used as local variables). Do not flag camelCase import identifiers (e.g., `import youtubeDataApi from "..."` with `props: { youtubeDataApi }`) for being “snake_case to match the app key.” The only exception is API request parameter names: keep their casing as required by the upstream API spec.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20908
File: components/clockwork_recruiting/actions/list-tag-ids-options/list-tag-ids-options.mjs:1-1
Timestamp: 2026-05-18T18:42:14.701Z
Learning: In Pipedream component files, the general camelCase naming rule should NOT be applied to (1) API request parameter names and (2) the snake_case app import identifier (the local variable name used for the app import) and its corresponding prop key. When reviewing `components/**/*.mjs`, do not flag `snake_case` for those exempt app identifiers/prop keys (e.g., `clockwork_recruiting`), but continue to require camelCase for all other local variables, prop names (other than the exempt app prop key), and method names.
There was a problem hiding this comment.
@coderabbitai Yes, please open the issue to track the pagination follow-up.
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
gh issue create \
--repo PipedreamHQ/pipedream \
--title "vapi: add cursor-based pagination to phoneNumberId, assistantId, and squadId propDefinitions" \
--body "## Summary
The \`phoneNumberId\`, \`assistantId\`, and \`squadId\` propDefinitions in \`components/vapi/vapi.app.mjs\` currently fetch only a single page of results using \`limit: LIMIT\` (1000 records — the documented per-request maximum). Truncation is therefore only an issue for accounts with more than 1000 records per resource type, but the \`async options()\` functions should ideally support load-more pagination.
## Background
Raised during review of `#21084` (comment: https://github.com/PipedreamHQ/pipedream/pull/21084#discussion_r3367045633).
The existing \`async *paginate()\` helper in \`vapi.app.mjs\` consumes a \`{ data, meta: { current_page, last_page } }\` response shape, but the Vapi \`GET /phone-number\`, \`GET /assistant\`, and \`GET /squad\` list endpoints return **plain arrays**, not that shape. Vapi uses \`createdAtLt\` cursor pagination on these endpoints.
## Work needed
- Implement cursor-based (\`createdAtLt\`) pagination for the three propDefinitions:
- \`phoneNumberId\` — \`GET /phone-number\`
- \`assistantId\` — \`GET /assistant\`
- \`squadId\` — \`GET /squad\`
- Either add a new \`paginateCursor()\` helper to the app file, or replicate the cursor logic inline in each \`async options()\`.
- Wire up \`prevContext\` to pass the cursor between load-more calls.
- Bump the app package version accordingly.
## References
- PR where this was deferred: `#21084`
- Vapi phone-number list docs: https://docs.vapi.ai/api-reference/phone-numbers/list
/cc `@VibhanshuPandey`" \
--assignee VibhanshuPandeyLength of output: 2047
🏁 Script executed:
#!/bin/bash
gh issue create \
--repo PipedreamHQ/pipedream \
--title "vapi: add cursor-based pagination to phoneNumberId, assistantId, and squadId propDefinitions" \
--body "## Summary
The \`phoneNumberId\`, \`assistantId\`, and \`squadId\` propDefinitions in \`components/vapi/vapi.app.mjs\` currently fetch only a single page of results using \`limit: LIMIT\` (1000 records — the documented per-request maximum). Truncation is therefore only an issue for accounts with more than 1000 records per resource type, but the \`async options()\` functions should ideally support load-more pagination.
## Background
Raised during review of `#21084` (comment: https://github.com/PipedreamHQ/pipedream/pull/21084#discussion_r3367045633).
The existing \`async *paginate()\` helper in \`vapi.app.mjs\` consumes a \`{ data, meta: { current_page, last_page } }\` response shape, but the Vapi \`GET /phone-number\`, \`GET /assistant\`, and \`GET /squad\` list endpoints return **plain arrays**, not that shape. Vapi uses \`createdAtLt\` cursor pagination on these endpoints.
## Work needed
- Implement cursor-based (\`createdAtLt\`) pagination for the three propDefinitions:
- \`phoneNumberId\` — \`GET /phone-number\`
- \`assistantId\` — \`GET /assistant\`
- \`squadId\` — \`GET /squad\`
- Either add a new \`paginateCursor()\` helper to the app file, or replicate the cursor logic inline in each \`async options()\`.
- Wire up \`prevContext\` to pass the cursor between load-more calls.
- Bump the app package version accordingly.
## References
- PR where this was deferred: `#21084`
- Vapi phone-number list docs: https://docs.vapi.ai/api-reference/phone-numbers/list
/cc `@VibhanshuPandey`"Length of output: 1795
@VibhanshuPandey, the follow-up issue has been created: #21086
It tracks implementing createdAtLt cursor-based pagination across all three propDefinitions (phoneNumberId, assistantId, squadId) in components/vapi/vapi.app.mjs.
🐇 ᓚᘏᗢ filed and ready for the next sprint
🧠 Learnings used
Learnt from: VibhanshuPandey
Repo: PipedreamHQ/pipedream PR: 21084
File: components/vapi/vapi.app.mjs:54-61
Timestamp: 2026-06-06T09:48:46.537Z
Learning: In `components/vapi/vapi.app.mjs`, the Vapi `GET /phone-number`, `GET /assistant`, and `GET /squad` list endpoints all return plain arrays, NOT the `{ data, meta: { current_page, last_page } }` shape that the existing `async *paginate()` helper in the same file consumes. Vapi uses `createdAtLt` cursor pagination on these list endpoints. Therefore, the existing `paginate()` helper CANNOT be used for `phoneNumberId`, `assistantId`, or `squadId` propDefinition `async options()`. The `LIMIT` constant is 1000, the documented per-request maximum for these endpoints, so truncation only affects accounts with more than 1000 records. Do not flag the absence of `prevContext`/`page` pagination in these three propDefinitions as a blocker until a proper cursor-based pagination implementation is available.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/*/*.app.mjs : Prop definitions in app files must include both `label` and `description`. If a definition includes `async options()` that calls a paginated API endpoint, it must support `prevContext` or `page`.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/**/*.mjs : Prop descriptions must describe the expected format for non-obvious values (dates, IDs, JSON structures, enum strings), include concrete examples for JSON objects or constructed values, explain where to get IDs if the user might only have a name or URL, avoid UI language like "select from the dropdown", and point to discovery tools when valid values must be looked up
Learnt from: s0s0physm
Repo: PipedreamHQ/pipedream PR: 0
File: :0-0
Timestamp: 2026-04-29T23:16:37.561Z
Learning: In the Stripe list actions (e.g., `components/stripe/actions/list-customers/list-customers.mjs`, `list-invoices`, `list-payouts`, `list-balance-history`, `list-refunds`, `list-payment-intents`), pagination metadata (`has_more`, `next_starting_after`) is exposed via an opt-in boolean prop `returnPaginationInfo` (default `false`). When `false`, actions return `Array<T>` exactly as before (no breaking change). When `true`, actions fetch `limit + 1` items, trim to `limit`, derive `has_more`, and return `{ data, has_more, next_starting_after }`. This opt-in design makes the version bump `0.1.4` → `0.2.0` (MINOR, not MAJOR) correct per Pipedream semver guidelines. Do not flag this as a breaking change or suggest a major version bump.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-component-guidelines.md:0-0
Timestamp: 2026-04-29T00:52:39.465Z
Learning: Applies to components/**/*.mjs : Every prop definition with `async options()` that calls a paginated API endpoint must support `prevContext` or `page` (starts at 0) for "load more" functionality
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20911
File: components/freshchat/actions/list-agent-id-options/list-agent-id-options.mjs:16-22
Timestamp: 2026-05-18T18:55:29.937Z
Learning: In PipedreamHQ/pipedream, for list-options utility action components under `components/<app>/actions/list-*-options/`, the `page` integer prop does NOT require a `max` constraint. Only a `min: 0` and `default: 0` are needed. Do not flag the absence of a `max` value on page pagination props in these components.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20990
File: components/ashby/actions/get-file-url/get-file-url.mjs:19-19
Timestamp: 2026-05-27T08:44:16.428Z
Learning: In the PipedreamHQ/pipedream Ashby integration (and likely other connectors), when a prop value is a pass-through from another API response (e.g., `fileHandle` in `components/ashby/actions/get-file-url/get-file-url.mjs`), do NOT require or suggest adding a concrete inline example for that prop's description. Since the format is opaque and controlled entirely by the upstream API, hardcoding an example risks becoming stale. Instead, the description should cross-reference the source action (e.g., **Get Candidate**) where the value can be obtained. Do not flag the absence of a concrete example for pass-through / API-derived identifiers.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20783
File: components/monday/actions/common/common-create-item.mjs:18-18
Timestamp: 2026-05-04T22:10:40.584Z
Learning: In Pipedream component files (components/**/*.mjs) for the monday.com integration: when a prop uses `propDefinition` that provides async options (e.g., the `columns`/`column` prop in `components/monday/actions/common/common-create-item.mjs`), concrete inline format examples in the `description` field are not required because the agent/user selects from the returned option list rather than constructing values manually. Do not flag the absence of inline examples for such props.
Learnt from: CR
Repo: PipedreamHQ/pipedream PR: 0
File: .github/pipedream-source-guidelines.md:0-0
Timestamp: 2026-04-13T20:20:15.870Z
Learning: Applies to **/*source*.{js,ts} : Paginate through all new items when the API supports pagination — do not stop after the first page
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20865
File: components/envoy/actions/list-employee-id-options/list-employee-id-options.mjs:17-23
Timestamp: 2026-05-14T19:04:45.522Z
Learning: In PipedreamHQ/pipedream, for lightweight "list prop options" utility action components (actions under `components/<app>/actions/list-*-options/` whose sole purpose is to retrieve and return available options for a prop field), it is NOT necessary to pass the `$` context into `propDefinitions.options.call(this.<app>)` calls or the underlying API methods they invoke (e.g., `listEmployeesOps()`). The `$` context requirement is waived for these read-only utility actions since they are simple option-retrieval helpers.
Learnt from: ashwins01
Repo: PipedreamHQ/pipedream PR: 21031
File: components/hubspot/sources/new-engagement/new-engagement.mjs:33-39
Timestamp: 2026-06-02T13:28:47.253Z
Learning: In the PipedreamHQ/pipedream repo, for HubSpot "New Engagement" source (`components/hubspot/sources/new-engagement/new-engagement.mjs`), the component description intentionally lists multiple per-activity HubSpot documentation links (Calls, Emails, Meetings, Notes, Postal Mail, Tasks) instead of a single consolidated "See the documentation" link. This is by design because each engagement type has its own separate v3 API endpoint and docs page. When reviewing this specific source, do not flag the multiple inline links as a violation of the single-docs-link convention unless the final link is also missing the required `[See the documentation](...)` closing link.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20678
File: components/moodle/actions/search-users/search-users.mjs:16-40
Timestamp: 2026-04-28T18:14:58.414Z
Learning: For Pipedream component files under components/**/*.mjs: the "[See the documentation](...)" link is required only in the top-level component `description` field. For any individual prop `description` fields, write the description specifically for AI agent consumption—include concrete inline examples. Prop `description` fields do not need to end with a documentation link.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20832
File: components/getty_images/common/constants.mjs:1-74
Timestamp: 2026-05-11T22:13:55.006Z
Learning: In Pipedream component files under `components/**/*.mjs`, follow this naming convention: use `UPPER_SNAKE_CASE` for module-level constants (e.g., option arrays like `IMAGE_TYPE_OPTIONS`, `ORIENTATION_OPTIONS`). For all other identifiers, use `camelCase`—specifically local variables inside functions/methods, prop names, and method names. `UPPER_SNAKE_CASE` at module scope for constants is an accepted convention in this codebase and should not be flagged.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20853
File: components/surecart/actions/create-checkout/create-checkout.mjs:7-7
Timestamp: 2026-05-13T17:22:52.552Z
Learning: When reviewing a connector “fix/republish” PR in PipedreamHQ/pipedream, a breaking input-contract change in the republished connector/component should NOT automatically trigger a major version bump if the previous connector/component version was never successfully published (e.g., the publish pipeline failed with a UserError). In that case, a patch bump is acceptable (e.g., 0.0.1 → 0.0.2) because no users could have relied on the unpublished interface. Before flagging an incorrect bump level, verify the prior version’s unpublished status using the PR description and/or linked issue(s).
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20884
File: components/jira_data_center/actions/list-filter-id-options/list-filter-id-options.mjs:1-1
Timestamp: 2026-05-15T16:31:34.394Z
Learning: When reviewing Pipedream component files, do not require the imported app module identifier (the local import variable) to be snake_case. Both snake_case and camelCase local import variable names are acceptable (e.g., `import jiraDataCenter from "../../jira_data_center.app.mjs"` is fine even if the app filename uses `jira_data_center`). However, ensure the key(s) used in the component’s `props` object match exactly what the referenced app module exports; mismatches between the app’s exported prop name(s) and the component `props` keys should be flagged. The local import variable name itself is flexible as long as `props` keys align with the app exports.
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 20884
File: components/youtube_data_api/actions/list-language-options/list-language-options.mjs:1-1
Timestamp: 2026-05-15T19:23:37.145Z
Learning: For Pipedream component files under `components/**/*.mjs`, follow `pipedream-component-guidelines.md`: require camelCase for all prop names, method names, and local variables (including import identifiers used as local variables). Do not flag camelCase import identifiers (e.g., `import youtubeDataApi from "..."` with `props: { youtubeDataApi }`) for being “snake_case to match the app key.” The only exception is API request parameter names: keep their casing as required by the upstream API spec.
Learnt from: michelle0927
Repo: PipedreamHQ/pipedream PR: 20908
File: components/clockwork_recruiting/actions/list-tag-ids-options/list-tag-ids-options.mjs:1-1
Timestamp: 2026-05-18T18:42:14.701Z
Learning: In Pipedream component files, the general camelCase naming rule should NOT be applied to (1) API request parameter names and (2) the snake_case app import identifier (the local variable name used for the app import) and its corresponding prop key. When reviewing `components/**/*.mjs`, do not flag `snake_case` for those exempt app identifiers/prop keys (e.g., `clockwork_recruiting`), but continue to require camelCase for all other local variables, prop names (other than the exempt app prop key), and method names.
The create-call PR modifies vapi.app.mjs, so every component importing the app must have its version bumped per the "Ensure component commits modify component versions" CI check. Bumps list-assistant-id-options, list-squad-id-options, update-assistant-settings, upload-file, and the new-conversation source.
|
Pushed
Could a maintainer re-approve the CI run so the version check can go green? Ready for re-review. Thanks! |
WHY
vapi-create-callcurrently sends onlyassistantId,squadId,phoneNumberId,nameandcustomerIdtoPOST /call. The Vapi API requires a call destination viacustomer: { number }(orcustomerId), but Vapi exposes no customer CRUD endpoints — socustomerIdis effectively unusable and there is no way to specify who to call. Every outbound phone call made with this action fails with:(Reproduced today against api.vapi.ai with a valid assistant + phone number and all existing props set.)
Changes
+14155551234) passed to the API ascustomer: { number }. Added an earlyConfigurationErrormirroring the API requirement so users get a clear message instead of the raw 400. Kept optional so any existing configs usingcustomerIdare untouched.name (number)with fallbacks. Vapi auto-names provisioned numbers (e.g. "Twilio"), so name-only labels made multiple numbers indistinguishable in the dropdown.create-call0.0.2 → 0.1.0,list-phone-number-id-options0.0.1 → 0.0.2 (its output labels change), package 0.3.0 → 0.4.0.Summary by CodeRabbit
New Features
Improvements
Updates
Chores