Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions content/guides/calls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ Use a stable workflow key, not a random UUID generated at each retry.

Use `waitForResult` or `wait_for_result` for simple server-side polling. Use events when you need a developer-facing trace of the call lifecycle.

Before mapping a failed call to no answer or decline, read
[Accepted call execution outcomes](/errors#accepted-call-execution-outcomes).
Calls API `failure_code` values are not a published enum, and Goal Run error
codes do not define the Calls API contract.

When the terminal `structured_result` is `null`, CALL-E did not produce a schema-valid whole-task result from the available evidence. Recipient-level structured results use the same rule: invalid or unsupported values are returned as `null`. The task-level `task_completed`, `completion_confidence`, and `evidence` fields come from the post-call summary and are available independently of your custom result schema.

Each recipient attempt can include `transcript_turns`, an ordered list of structured transcript turns for that dial attempt. Each turn has `offset_seconds`, `speaker`, and `text`; `speaker` is `bot`, `user`, or `unknown`. The array is empty when no transcript is available.
Expand Down
24 changes: 24 additions & 0 deletions content/guides/errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ SDK methods raise typed SDK errors while preserving the stable API error code an
- `internal_error`
- `not_found`

## Accepted call execution outcomes

The stable `APIError.code` values above describe an HTTP request failure. They
are separate from the outcome of a call task or Goal Run that was accepted and
later reached a terminal state.

| Surface | Stable contract |
| --- | --- |
| Developer API request | `APIError.code` uses the stable values listed above. |
| Calls API call task | Lifecycle `status` is stable. `failure_code` is a nullable string without a published enum; `failure_message` is nullable human-readable context. |
| Goal Runs API | `GoalRunError.code` is a separate enum that includes `no_answer` and `declined`. |

For Calls API resources, treat `failure_code` and `failure_message` as
diagnostic context. Preserve the raw values for support, but do not branch
retry, reporting, or analytics logic on a particular string.

The Goal Run codes `no_answer` and `declined` do not define Calls API
`failure_code` values. The Calls API currently does not guarantee a distinct
no-answer or callee-decline value at the call-task, recipient, or attempt
level. If the documented Calls fields do not establish that distinction, keep
the business outcome unresolved. Do not infer that a recipient declined from
a generic `failed` state or an undocumented failure message, and do not
automatically retry based only on an undocumented failure string.

## Recovery guidance

`unauthorized` means the API key is missing or invalid. Check the `Authorization: Bearer` header.
Expand Down
23 changes: 23 additions & 0 deletions tests/docs-site.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,29 @@ test("connects the Calls guide to HTTP and related references", async ({
await expect(
callsBody.locator('p a[href="/webhooks"]'),
).toBeVisible();

const outcomeGuidance = callsBody.getByRole("link", {
name: "Accepted call execution outcomes",
});
await expect(outcomeGuidance).toHaveAttribute(
"href",
"/errors#accepted-call-execution-outcomes",
);
await outcomeGuidance.click();

await expect(page).toHaveURL(/\/errors#accepted-call-execution-outcomes$/);
await expect(
page.getByRole("heading", { name: "Accepted call execution outcomes" }),
).toBeVisible();
const callsOutcomeWarning = page.locator("main p").filter({
hasText: "do not define Calls API",
});
await expect(callsOutcomeWarning).toContainText(
"keep the business outcome unresolved",
);
await expect(
callsOutcomeWarning.locator("code").filter({ hasText: "failure_code" }),
).toBeVisible();
});

test("documents the published Goal Run flow on a clean route", async ({
Expand Down