diff --git a/content/guides/calls.mdx b/content/guides/calls.mdx index 0165bde..88ece6c 100644 --- a/content/guides/calls.mdx +++ b/content/guides/calls.mdx @@ -364,6 +364,8 @@ resultSchema: { ## Idempotency +A shared-platform-line task supports one phone number. Batch tasks require an eligible dedicated purchased number selected as the account default outbound number. The configured task allowance applies across API, MCP, and Dashboard: by default, each account has one shared-platform-line slot and ten purchased-number slots, including planning. To use the purchased-number allowance, complete identity verification (KYC), [buy a dedicated number](https://dashboard.heycall-e.com/account/numbers/buy), and select the activated number as the account default outbound number. A purchased number keeps its purchased-line allowance when selected as the account default. Waiting for user input or confirmation releases planning capacity. + Pass an idempotency key when a workflow step might retry. The key maps to the `Idempotency-Key` HTTP header and prevents duplicate call creation for the same external operation. Use a stable workflow key, not a random UUID generated at each retry. @@ -398,3 +400,5 @@ completed = client.calls.wait_for_result( events = client.calls.list_events(call["id"], limit=50) ``` + +Persisted creation failures replay their original HTTP status and error. A duplicate still being created returns `409 idempotency_conflict` with `details.reason_code=creation_in_progress`. diff --git a/content/guides/changelog.mdx b/content/guides/changelog.mdx index 731e290..6486b81 100644 --- a/content/guides/changelog.mdx +++ b/content/guides/changelog.mdx @@ -5,6 +5,12 @@ description: Track CALL-E Developer API and SDK product updates. Product updates for the CALL-E Developer API and server SDKs. +## September 8, 2026 + +### Account task admission and creation retries + +Task capacity is shared across API, MCP, and Dashboard for each account and line class: shared platform lines default to 1 concurrent task, while eligible dedicated purchased numbers default to 10. Selecting a purchased number as the account default outbound number keeps its purchased-line allowance. Account concurrency and token-budget denials have distinct 429 codes; unavailable controls return distinct 503 codes. Shared-line concurrency errors include identity verification (KYC), dedicated-number purchase guidance, and a purchase-page link. The effective limit and upgrade information are available in error details. Calls API idempotent retries preserve the original creation error. Call creation follows configured account controls without a separate fixed daily creation cap. + ## July 29, 2026 ### Terminal webhook delivery diff --git a/content/guides/errors.mdx b/content/guides/errors.mdx index 44a7f15..45cd219 100644 --- a/content/guides/errors.mdx +++ b/content/guides/errors.mdx @@ -25,6 +25,10 @@ SDK methods raise typed SDK errors while preserving the stable API error code an - `unauthorized` - `forbidden` - `rate_limit_exceeded` +- `account_concurrency_exceeded` +- `account_concurrency_unavailable` +- `llm_token_budget_exceeded` +- `llm_token_budget_unavailable` - `insufficient_balance` - `unsupported_region` - `unsupported_language` @@ -56,6 +60,16 @@ See [Authentication](/authentication) for API key setup, server-only usage, and `rate_limit_exceeded` means the caller should retry after backoff. +`account_concurrency_exceeded` (HTTP 429) means the account has reached its configured task allowance for the selected line class. Shared platform lines default to one active task, and eligible dedicated purchased numbers default to ten. The same account shares each allowance across API keys, MCP, and Dashboard. Wait for a task to finish before starting a new attempt. + +On a default shared line, the error message explains how to increase concurrency: complete identity verification (KYC), [purchase a dedicated phone number](https://dashboard.heycall-e.com/account/numbers/buy), and select the activated number as the default outbound number. KYC alone does not increase the shared-line allowance. The default purchased-number allowance is 10 tasks; account-specific configuration may differ. + +`details.line_type` and `details.max_active_tasks` identify the denied allowance. Shared-line responses also include `details.upgrade.max_active_tasks`, `details.upgrade.kyc_required`, and `details.upgrade.purchase_url`. Use these values when presenting the upgrade action. Local/test API responses link to the TEST Dashboard. Purchased-number exhaustion asks the user to wait and does not include another purchase action. + +`llm_token_budget_exceeded` (HTTP 429) means the account's current token allowance is exhausted. Wait for the configured usage window to reset or contact your account administrator. + +`account_concurrency_unavailable` and `llm_token_budget_unavailable` (HTTP 503) mean the corresponding control could not be checked. Planning does not start when admission cannot be verified. + `insufficient_balance` means the project cannot start more calls until billing is resolved. `unsupported_region` or `unsupported_language` means CALL-E could not resolve a supported calling configuration for the request. @@ -70,7 +84,9 @@ See [Authentication](/authentication) for API key setup, server-only usage, and `recipient_result_schema_invalid` means the per-recipient `recipient_result_schema` is not a valid supported JSON Schema object. -`idempotency_conflict` means the same idempotency key was reused with a different request body. Reuse keys only for the same external workflow operation. +`idempotency_conflict` (HTTP 409) means the key was reused with different input or the original creation is still in progress. For the latter, `details.reason_code` is `creation_in_progress`; retry with the same key and input. + +For Calls API requests, a persisted creation failure replays the same HTTP status and error body. Once the underlying limit or service issue is resolved, use a new key for a new attempt. If creation succeeded but the call later failed, the original call remains the result of an exact replay. `not_found` means a call, Goal, or Goal Run does not exist or is not visible to the current API key. Owner mismatch and hidden Goals use the same code. diff --git a/openapi/calle.openapi.yaml b/openapi/calle.openapi.yaml index 269e273..922cfd7 100644 --- a/openapi/calle.openapi.yaml +++ b/openapi/calle.openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: CALL-E Developer API - version: 0.6.0 + version: 0.7.0 description: Developer API contract used by the CALL-E TypeScript and Python SDKs. servers: - url: https://api.heycall-e.com @@ -15,7 +15,7 @@ paths: tags: - calls summary: Create Call - description: Create an asynchronous call. Use `result_schema` and `recipient_result_schema` to ask CALL-E to extract structured JSON results from terminal call evidence. + description: Create an asynchronous call. Use `result_schema` and `recipient_result_schema` to ask CALL-E to extract structured JSON results from terminal call evidence. Shared platform outbound lines support one phone number per task. Batch calls require an eligible purchased number selected as the account default outbound number; otherwise creation returns `422 call_not_ready`. Account concurrency and LLM token usage are controlled by the effective account configuration. Task concurrency defaults to 1 on shared platform lines and 10 on eligible dedicated purchased numbers; selecting a purchased number as the account default does not make it a shared platform line. parameters: - $ref: "#/components/parameters/IdempotencyKey" requestBody: @@ -26,18 +26,14 @@ paths: $ref: "#/components/schemas/CreateCallRequest" examples: batchLunch: - summary: Check Friday lunch availability for two recipients. + summary: Check Friday lunch availability for two recipients using an eligible purchased outbound number. value: task: Call each recipient and ask whether they can attend Friday lunch in San Francisco. recipients: - phones: - "" - region: US - locale: en-US - phones: - "" - region: US - locale: en-US result_schema: type: object required: @@ -176,9 +172,30 @@ paths: "422": $ref: "#/components/responses/ErrorResponse" "429": - $ref: "#/components/responses/ErrorResponse" + description: An account concurrency limit (`account_concurrency_exceeded`), or LLM token budget (`llm_token_budget_exceeded`) was reached. Account admission is checked before planning. Concurrency errors identify the effective line type and limit. Shared-line errors include KYC and dedicated-number purchase guidance in the message and `details.upgrade`; purchased-line errors ask the user to wait for capacity without another purchase suggestion. Configured limits override the default 1 / 10 values. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + example: + error: + code: account_concurrency_exceeded + message: Your default shared line (such as us/all) is at its account concurrency limit of 1. This limit is shared across API, MCP, and Dashboard. Wait for an active task to finish, then retry. For up to 10 concurrent tasks, complete identity verification (KYC), purchase a dedicated phone number, and select the activated number as your default outbound number. [Verify identity and buy a number](https://dashboard.heycall-e.com/account/numbers/buy). + details: + line_type: platform_default + max_active_tasks: 1 + upgrade: + max_active_tasks: 10 + kyc_required: true + purchase_url: https://dashboard.heycall-e.com/account/numbers/buy "500": $ref: "#/components/responses/ErrorResponse" + "503": + description: The provider or an account control is unavailable (`provider_unavailable`, `account_concurrency_unavailable`, or `llm_token_budget_unavailable`). + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" /v1/calls/{call_id}: get: operationId: getCall @@ -328,6 +345,8 @@ paths: `after` value; clients must not parse or construct cursor values. `title` and `description` help operators recognize each published workflow, but integrations should still store the intended `goal_id` at publish time and must not execute the first list item blindly. + Candidates whose published RunSpec is not execution-ready are omitted without preventing + later executable Goals from appearing in the page. parameters: - $ref: "#/components/parameters/GoalListLimit" - $ref: "#/components/parameters/GoalListAfter" @@ -399,8 +418,6 @@ paths: $ref: "#/components/responses/ErrorResponse" "403": $ref: "#/components/responses/ErrorResponse" - "409": - $ref: "#/components/responses/ErrorResponse" "429": $ref: "#/components/responses/ErrorResponse" "500": @@ -520,6 +537,7 @@ paths: id: rgrp_delivery_ord_8472 goal_id: goal_delivery_confirmation run_id: run_delivery_ord_8472 + call_id: null status: queued run_spec: id: rspec_delivery_v4 @@ -597,6 +615,7 @@ paths: id: rgrp_delivery_ord_8472 goal_id: goal_delivery_confirmation run_id: run_delivery_ord_8472 + call_id: calling_call_delivery_ord_8472 status: completed run_spec: id: rspec_delivery_v4 @@ -614,6 +633,7 @@ paths: id: rgrp_delivery_ord_8472 goal_id: goal_delivery_confirmation run_id: run_delivery_ord_8472 + call_id: null status: failed run_spec: id: rspec_delivery_v4 @@ -739,7 +759,7 @@ components: IdempotencyKey: name: Idempotency-Key in: header - description: Stable caller-provided key used to make create-call retries safe. Reusing the same key with the same request returns the original call instead of creating a duplicate. + description: Stable caller-provided key used to make create-call retries safe. Reusing the same key with the same request returns the original call instead of creating a duplicate. A persisted creation failure replays its original HTTP status and error body; use a new key for a new attempt after resolving the error. While creation is still in progress, a duplicate returns `409 idempotency_conflict` with `details.reason_code=creation_in_progress`. A different request using the same key returns `409 idempotency_conflict`. required: false schema: type: string @@ -998,6 +1018,7 @@ components: - id - goal_id - run_id + - call_id - run_spec - status - result @@ -1021,6 +1042,17 @@ components: type: string description: Internal execution member exposed for correlation; do not use it in the Goal Run polling path. minLength: 1 + call_id: + type: + - string + - "null" + description: |- + Calling call identifier selected for this Goal Run when that trusted fact is available, + or `null` before a call identifier is persisted or when no identifier is available. This + is different from the Goal Run `id` and nested `run_id`; it does not expose other provider + diagnostics and must not be treated as an independent answered-call boolean. + minLength: 1 + maxLength: 255 run_spec: description: Read-only identity and version of the exact RunSpec pinned by this Run. $ref: "#/components/schemas/GoalRunSpecSnapshot" @@ -1124,7 +1156,7 @@ components: type: - array - "null" - description: Optional explicit recipients for this call task. Omit it when the task text already contains the phone targets CALL-E should use. + description: Optional explicit recipients for this call task. Omit it when the task text already contains the phone targets CALL-E should use. The default outbound line permits one phone number in total across all recipients. Multiple targets require an eligible purchased outbound number; this also applies to targets inferred from task text. minItems: 1 items: $ref: "#/components/schemas/CallTaskRecipientRequest" @@ -1596,6 +1628,10 @@ components: - unauthorized - forbidden - rate_limit_exceeded + - account_concurrency_exceeded + - account_concurrency_unavailable + - llm_token_budget_exceeded + - llm_token_budget_unavailable - insufficient_balance - unsupported_region - unsupported_language