{
  "openapi": "3.0.0",
  "info": {
    "description": "SuperDial REST API Reference",
    "version": "1.0.0",
    "title": "SuperDial API"
  },
  "servers": [
    {
      "url": "https://robodialer-service-api-9nc4t1p9.uc.gateway.dev",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "description": "SuperDial employs Bearer Authentication. Fetch a bearer token using your API Key and API Secret, then pass it as `Authorization: Bearer <token>` on subsequent calls."
    },
    {
      "name": "Requests",
      "description": "Endpoints for creating and reading requests (structured data extraction jobs). All non-2xx responses use the uniform `{error, message, [details]}` envelope (see the `ApiError` schema)."
    },
    {
      "name": "Schemas",
      "description": "Discover the schemas provisioned for your account, the input keys each one requires, and the fields each one returns. All non-2xx responses use the uniform `{error, message, [details]}` envelope (see the `ApiError` schema)."
    }
  ],
  "paths": {
    "/v1/auth": {
      "get": {
        "summary": "Authenticate and get token",
        "description": "Returns a short-lived bearer token for use in API calls. The API key and API secret are **two distinct values** issued together: the key identifies your account, the secret authenticates the request.",
        "tags": ["Authentication"],
        "security": [
          {
            "apiKey": [],
            "apiSecret": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "shell",
            "label": "curl",
            "source": "curl https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/auth \\\n  -H 'Robodialer-API-Key: <your-api-key>' \\\n  -H 'Robodialer-API-Secret: <your-api-secret>'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import requests\n\nr = requests.get(\n    'https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/auth',\n    headers={\n        'Robodialer-API-Key': '<your-api-key>',\n        'Robodialer-API-Secret': '<your-api-secret>',\n    },\n)\nr.raise_for_status()\ntoken = r.json()['token']"
          },
          {
            "lang": "javascript",
            "label": "JavaScript",
            "source": "const r = await fetch(\n  'https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/auth',\n  {\n    headers: {\n      'Robodialer-API-Key': '<your-api-key>',\n      'Robodialer-API-Secret': '<your-api-secret>',\n    },\n  },\n);\nconst { token } = await r.json();"
          }
        ],
        "responses": {
          "200": {
            "description": "Token returned successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/AuthTokenResponse" },
                "example": {
                  "token": "eyJhbGciOiJSUzI1NiIs...truncated...signature"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SimpleErrorResponse" },
                "examples": {
                  "missingApiKey": {
                    "summary": "Missing Robodialer-API-Key header",
                    "value": { "error": "MISSING_API_KEY" }
                  },
                  "missingApiSecret": {
                    "summary": "Missing Robodialer-API-Secret header",
                    "value": { "error": "MISSING_API_SECRET" }
                  },
                  "invalidApiKey": {
                    "summary": "API key not recognized",
                    "value": { "error": "INVALID_API_KEY" }
                  },
                  "unauthorized": {
                    "summary": "Secret does not match the API key",
                    "value": { "error": "UNAUTHORIZED" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas": {
      "get": {
        "tags": ["Schemas"],
        "summary": "List schemas",
        "description": "Returns the schemas provisioned for your account. Each row carries a `requestType` (e.g. `claim-status`, `vob`) that identifies the kind of extraction the schema performs. Schemas that are no longer accessible for your account are filtered out.",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "List of schemas the caller's account is provisioned for.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ListSchemasResponse" },
                "example": {
                  "schemas": [
                    {
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "name": "Claim Status (Commercial)",
                      "requestType": "claim-status"
                    },
                    {
                      "schemaId": "qP2bN8rT6mK1xC3vW9aL",
                      "name": "Verification of Benefits",
                      "requestType": "vob"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  },
                  "malformedJwt": {
                    "summary": "Authorization header value isn't a valid JWT",
                    "value": { "code": 401, "message": "Jwt is not in the form of Header.Payload.Signature with two dots and 3 sections" }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Account not found: the API key does not resolve to a provisioned account.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "ACCOUNT_NOT_FOUND",
                  "message": "No account is associated with this API key. Contact support if you believe this is an error."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas/{schemaId}": {
      "get": {
        "tags": ["Schemas"],
        "summary": "Retrieve a schema",
        "description": "Returns the detail resource for one schema: its `name`, its `requestType`, and `resultsFields` — every field the schema can produce in `results` on `GET /v1/requests/{requestId}`. Use it to build an ingest mapping and a destination table before you run a request. Inputs are not included; use `GET /v1/schemas/{schemaId}/required-inputs` for what to send.\n\n`resultsFields` is sorted by `name`. Each `name` matches the `results` key and the top-level `missingFields` entries exactly. `callSteps[].missingFields` is a different list — it falls back to raw question text for a skipped question that carries no alias — so do not join it against this inventory.\n\n**For this schema, the inventory is a superset of any one response.** Most fields on a large schema are gated on another field's answer, so they are absent on any given request. An unanswered field is absent from `results`; it is never `null`. Every column you build from this inventory must be nullable. Map on `name`, treat every field as optional, and ignore keys you do not map. The endpoint does not report which fields are gated.\n\n**A chained request can return keys beyond this schema.** A request can open a follow-up leg: a second call against a different schema, visible as an extra `callSteps` entry. That leg's captured values merge into the same top-level `results` under the leg schema's own field names. `resultsFields` covers one schema and does not list them. Read `callSteps[].schemaId` on a completed request, then call this endpoint again for that id.\n\n**`allowedValues` is not a closed set.** `CANNOT ANSWER - <reason>` passes through verbatim as a string on any type, including `boolean` and `multiple`, so a strict enum or boolean parse fails on it. Detect it by string prefix. It does not appear in `missingFields`: an explicit non-answer counts as answered.\n\n**Version drift.** `resultsFields` describes the schema's current latest version. A request that already ran was pinned to the version that was latest at run time. So an older request's `results` can carry keys this endpoint no longer lists, or omit keys it now lists. Read the endpoint again and diff the field list to find a change.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "schemaId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The schema ID (from `GET /v1/schemas`). Must be non-blank, ≤1500 characters, contain no `/`, and must not start with `_` or `.`."
          }
        ],
        "responses": {
          "200": {
            "description": "Detail for the schema, including every field it can return in `results`.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SchemaDetailResponse" },
                "example": {
                  "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                  "name": "Claim Status (Commercial)",
                  "requestType": "claim-status",
                  "resultsFields": [
                    {
                      "name": "checkNumber",
                      "label": "Check Number",
                      "description": "What is the check number?",
                      "type": "alphanumeric"
                    },
                    {
                      "name": "claimReceived",
                      "label": "Claim Received",
                      "description": "Did the payer receive the claim?",
                      "type": "boolean"
                    },
                    {
                      "name": "claimStatus",
                      "label": "Claim Status",
                      "description": "What is the status of the claim?",
                      "type": "multiple",
                      "allowedValues": ["PAID", "DENIED", "PENDING"]
                    },
                    {
                      "name": "paidAmount",
                      "label": "Paid Amount",
                      "description": "What amount was paid on the claim?",
                      "type": "dollar"
                    },
                    {
                      "name": "paidDate",
                      "label": "Paid Date",
                      "description": "On what date was the claim paid?",
                      "type": "date"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid `schemaId` path parameter (empty, contains `/`, starts with `_` or `.`, or exceeds 1500 characters).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INVALID_REQUEST",
                  "message": "The provided schemaId is invalid."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Schema not found, or account not found.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "schemaNotFound": {
                    "summary": "Schema not found, or has been retired and is no longer available for new requests",
                    "value": {
                      "error": "SCHEMA_NOT_FOUND",
                      "message": "No schema with that ID exists for your account."
                    }
                  },
                  "accountNotFound": {
                    "summary": "The API key resolves to an account that no longer exists. Rare: wrong-API-key cases hit `INVALID_API_KEY` at `/v1/auth` first.",
                    "value": {
                      "error": "ACCOUNT_NOT_FOUND",
                      "message": "No account is associated with this API key. Contact support if you believe this is an error."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error. Also returned when the schema's stored version record is unreadable or carries no fields. An empty inventory is never returned as a `200`.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas/{schemaId}/required-inputs": {
      "get": {
        "tags": ["Schemas"],
        "summary": "Required inputs for a schema",
        "description": "Returns the input keys this schema declares: those required to submit a request against it, and those it accepts but does not require. Field names are returned verbatim. Use them as the keys of the `inputs` object on `POST /v1/requests`. Lists are sorted. Neither list constrains `inputs`: additional keys outside both are accepted and passed to the call as context. This is the baseline: if your account is enabled for per-payer required inputs, some payers require additional fields not listed here, reported as `INVALID_INPUTS` on `POST /v1/requests`.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "schemaId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The schema ID (from `GET /v1/schemas`). Must be non-blank, ≤1500 characters, contain no `/`, and must not start with `_` or `.`."
          }
        ],
        "responses": {
          "200": {
            "description": "Sorted list of required input field names for this schema.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RequiredInputsResponse" },
                "example": {
                  "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                  "requiredInputs": {
                    "fields": [
                      "beginningDateOfService",
                      "billingProviderName",
                      "billingProviderTaxId",
                      "claimChargeAmount",
                      "memberId",
                      "patientDateOfBirth",
                      "patientFirstName",
                      "patientLastName",
                      "payerName",
                      "phoneNumber",
                      "renderingProviderName",
                      "renderingProviderNpi"
                    ]
                  },
                  "optionalInputs": {
                    "fields": [
                      "memberId2"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid `schemaId` path parameter (empty, contains `/`, starts with `_` or `.`, or exceeds 1500 characters).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INVALID_REQUEST",
                  "message": "The provided schemaId is invalid."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Schema not found, or account not found.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "schemaNotFound": {
                    "summary": "Schema not found, or has been retired and is no longer available for new requests",
                    "value": {
                      "error": "SCHEMA_NOT_FOUND",
                      "message": "No schema with that ID exists for your account."
                    }
                  },
                  "accountNotFound": {
                    "summary": "The API key resolves to an account that no longer exists. Rare: wrong-API-key cases hit `INVALID_API_KEY` at `/v1/auth` first.",
                    "value": {
                      "error": "ACCOUNT_NOT_FOUND",
                      "message": "No account is associated with this API key. Contact support if you believe this is an error."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          }
        }
      }
    },
    "/v1/schemas/{schemaId}/required-payer-inputs": {
      "post": {
        "tags": ["Schemas"],
        "summary": "Resolve payer names against a schema's required inputs",
        "description": "Given a schema and a batch of payer names, returns the schema's own required/optional inputs **plus** the per-payer required inputs for each name, so you can assemble the complete input set for a specific payer *before* calling `POST /v1/requests`, instead of discovering a payer-specific field from an `INVALID_INPUTS` rejection. The schema-level `requiredInputs`/`optionalInputs` are identical in shape and meaning to [`GET /v1/schemas/{schemaId}/required-inputs`](/api-reference/schemas/required-inputs-for-a-schema); `payers` adds the per-payer detail.\n\nThe response carries one `payers` entry per `payerNames` entry, in input order, with no de-duplication (positionally aligned 1:1 with the request array). Each entry is either **matched** (`inputPayerName`, `matchedPayerName`, `payerRequiredInputs.fields`) or a per-payer **error** (`inputPayerName`, `errorCode`, `message`). Discriminate on the presence of `errorCode`. A per-payer failure never fails the whole request; whole-request failures use the uniform `{error, message}` envelope.\n\n**Opt-in.** Gated on the `enforcePayerRequiredInputs` account feature. When it is off the endpoint returns 403 `PAYER_REQUIRED_INPUTS_DISABLED`. This is the schema-keyed twin of `POST /v1/scripts/{scriptId}/required-payer-inputs`. See the [Per-Payer Required Inputs guide](/guides/payer-required-inputs).",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "schemaId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The schema ID (from `GET /v1/schemas`). Must be non-blank, ≤1500 characters, contain no `/`, and must not start with `_` or `.`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/RequiredPayerInputsRequest" },
              "example": {
                "payerNames": ["Sample Insurance Co", "Unknown Payer"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schema required/optional inputs plus one `payers` entry per requested name.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RequiredPayerInputsResponse" },
                "example": {
                  "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                  "requiredInputs": {
                    "fields": [
                      "beginningDateOfService",
                      "billingProviderName",
                      "billingProviderTaxId",
                      "claimChargeAmount",
                      "memberId",
                      "patientDateOfBirth",
                      "patientFirstName",
                      "patientLastName",
                      "payerName",
                      "phoneNumber",
                      "renderingProviderName",
                      "renderingProviderNpi"
                    ]
                  },
                  "optionalInputs": {
                    "fields": ["memberId2"]
                  },
                  "payers": [
                    {
                      "inputPayerName": "Sample Insurance Co",
                      "matchedPayerName": "Sample Insurance Company, Inc.",
                      "payerRequiredInputs": {
                        "fields": ["claimNumber"]
                      }
                    },
                    {
                      "inputPayerName": "Unknown Payer",
                      "errorCode": "PAYER_NOT_FOUND",
                      "message": "No canonical payer matched 'Unknown Payer'."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid `schemaId` path parameter, or a malformed request body. Whole-request only: a bad *individual* payer name comes back inline as a `payers[]` error entry, not a 400.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "invalidSchemaId": {
                    "summary": "schemaId is empty, contains `/`, starts with `_` or `.`, or exceeds 1500 characters",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "The provided schemaId is invalid."
                    }
                  },
                  "bodyNotObject": {
                    "summary": "Body is missing or not a JSON object",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "Request body must be a JSON object."
                    }
                  },
                  "payerNamesNotArray": {
                    "summary": "`payerNames` is absent or not an array",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "`payerNames` must be a JSON array of strings."
                    }
                  },
                  "payerNamesEmpty": {
                    "summary": "`payerNames` is an empty array",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "`payerNames` must contain at least one entry."
                    }
                  },
                  "payerNamesTooMany": {
                    "summary": "`payerNames` exceeds the 50-entry cap (no truncation: the whole request is rejected)",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "`payerNames` may not exceed 50 entries."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Per-payer required inputs is not enabled for your account. Opt-in feature: contact your account manager.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "PAYER_REQUIRED_INPUTS_DISABLED",
                  "message": "Payer-required inputs are available as an opt-in feature but are not currently enabled for your account. Reach out to your account manager to request access."
                }
              }
            }
          },
          "404": {
            "description": "Schema not found, or account not found.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "schemaNotFound": {
                    "summary": "Schema not found, or has been retired and is no longer available for new requests",
                    "value": {
                      "error": "SCHEMA_NOT_FOUND",
                      "message": "No schema with that ID exists for your account."
                    }
                  },
                  "accountNotFound": {
                    "summary": "The API key resolves to an account that no longer exists. Rare: wrong-API-key cases hit `INVALID_API_KEY` at `/v1/auth` first.",
                    "value": {
                      "error": "ACCOUNT_NOT_FOUND",
                      "message": "No account is associated with this API key. Contact support if you believe this is an error."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          }
        }
      }
    },
    "/v1/requests": {
      "post": {
        "tags": ["Requests"],
        "summary": "Create a Request",
        "description": "Submit a single request or a batch of requests. For batch, wrap in `{\"requests\": [...]}`. If `internalId` is supplied on a single request, a duplicate POST with the same `internalId` returns the previously reserved `requestId` rather than creating a new one.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  { "$ref": "#/components/schemas/CreateRequestPayload" },
                  { "$ref": "#/components/schemas/CreateRequestBatchPayload" }
                ]
              },
              "examples": {
                "single": {
                  "summary": "Single request",
                  "value": {
                    "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                    "inputs": {
                      "payerName": "Sample Insurance Co",
                      "memberId": "TEST123456789",
                      "phoneNumber": "2125551234",
                      "providerNpi": "1234567890",
                      "dateOfService": "2026-03-15"
                    },
                    "internalId": "claim_internal_456"
                  }
                },
                "batch": {
                  "summary": "Batch: multiple requests in one POST",
                  "value": {
                    "requests": [
                      {
                        "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                        "inputs": {
                          "payerName": "Sample Insurance Co",
                          "memberId": "TEST123456789",
                          "phoneNumber": "2125551234",
                          "providerNpi": "1234567890",
                          "dateOfService": "2026-03-15"
                        },
                        "internalId": "claim_001"
                      },
                      {
                        "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                        "inputs": {
                          "payerName": "Sample Insurance Co",
                          "memberId": "TEST987654321",
                          "phoneNumber": "2125551234",
                          "providerNpi": "1234567890",
                          "dateOfService": "2026-03-12"
                        },
                        "internalId": "claim_002"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request(s) created successfully. The body is `CreateRequestSuccess` for a single-item POST and `CreateRequestBatchResponse` (with every entry a success) for a batch.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/CreateRequestSuccess" },
                    { "$ref": "#/components/schemas/CreateRequestBatchResponse" }
                  ]
                },
                "examples": {
                  "single": {
                    "summary": "Single: request created",
                    "value": {
                      "requestId": "8bF7xK2mP9qR4sT6uV0w",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "internalId": "claim_internal_456"
                    }
                  },
                  "singleWithPayerLookup": {
                    "summary": "Single: request created, plus synchronous payer phone number lookup succeeded (payerName supplied without phoneNumber)",
                    "value": {
                      "requestId": "8bF7xK2mP9qR4sT6uV0w",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "internalId": "claim_internal_456",
                      "payerLookup": {
                        "inputPayerName": "Sample Insurance Co",
                        "inputPhoneNumber": null,
                        "matchedPayerName": "Sample Insurance Company, Inc.",
                        "matchedPayerPhone": "8005551234",
                        "phoneNumberToUse": "8005551234",
                        "phoneNumberSource": "superdial"
                      }
                    }
                  },
                  "singleIdempotentReplay": {
                    "summary": "Single: idempotent replay (same internalId returns the original requestId)",
                    "value": {
                      "requestId": "8bF7xK2mP9qR4sT6uV0w",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "internalId": "claim_internal_456"
                    }
                  },
                  "batch": {
                    "summary": "Batch: every entry created successfully",
                    "value": {
                      "requests": [
                        {
                          "requestId": "8bF7xK2mP9qR4sT6uV0w",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "internalId": "claim_001"
                        },
                        {
                          "requestId": "aC3hN5jD8eL1fM2gK6Yo",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "internalId": "claim_002"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "207": {
            "description": "Partial success (batch only): at least one entry succeeded and at least one failed (validation, lookup, or server error). Each failed entry uses the `ApiError` envelope; succeeded entries use `CreateRequestSuccess`. The batch response itself does not carry a top-level error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateRequestBatchResponse" },
                "examples": {
                  "batchMixed": {
                    "summary": "Batch: one entry created, one failed validation",
                    "value": {
                      "requests": [
                        {
                          "requestId": "8bF7xK2mP9qR4sT6uV0w",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "internalId": "claim_001"
                        },
                        {
                          "error": "INVALID_REQUEST",
                          "message": "schemaId is required"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error. The body is always an `ApiError` envelope, except when every entry of a batch failed validation. In that case the body is a `CreateRequestBatchResponse` and each entry is its own `ApiError`. Codes returned at this status: `INVALID_REQUEST` (payload-shape, missing required fields, scheduling-capacity errors) and `INVALID_INPUTS` (input validation, with `details.missingInputs` and/or `details.invalidInputs`). With per-payer required inputs enabled, `details.missingInputs` can also include inputs a payer requires beyond the schema fields.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiError" },
                    { "$ref": "#/components/schemas/CreateRequestBatchResponse" }
                  ]
                },
                "examples": {
                  "bodyNotJsonObject": {
                    "summary": "Body is missing, empty, or not a JSON object (e.g. a JSON array)",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "The request body must be a JSON object."
                    }
                  },
                  "schemaIdRequired": {
                    "summary": "Single: schemaId missing",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "schemaId is required"
                    }
                  },
                  "inputsNotObject": {
                    "summary": "Single: inputs is not a JSON object",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "inputs must be an object"
                    }
                  },
                  "inputsMissing": {
                    "summary": "Required schema inputs are missing (details lists every missing field)",
                    "value": {
                      "error": "INVALID_INPUTS",
                      "message": "Required inputs are missing or invalid.",
                      "details": {
                        "missingInputs": [
                          "beginningDateOfService",
                          "billingProviderName",
                          "billingProviderTaxId",
                          "claimChargeAmount",
                          "memberId",
                          "patientDateOfBirth",
                          "patientFirstName",
                          "patientLastName",
                          "phoneNumber",
                          "renderingProviderName",
                          "renderingProviderNpi"
                        ]
                      }
                    }
                  },
                  "inputsInvalid": {
                    "summary": "Required inputs missing AND format-invalid (details has both blocks)",
                    "value": {
                      "error": "INVALID_INPUTS",
                      "message": "Required inputs are missing or invalid.",
                      "details": {
                        "missingInputs": [
                          "beginningDateOfService",
                          "billingProviderName",
                          "billingProviderTaxId",
                          "claimChargeAmount",
                          "patientDateOfBirth",
                          "patientFirstName",
                          "patientLastName",
                          "renderingProviderName",
                          "renderingProviderNpi"
                        ],
                        "invalidInputs": {
                          "memberId": "memberId contains invalid characters (curly braces)",
                          "phoneNumber": "phoneNumber is not a valid U.S. phone number"
                        }
                      }
                    }
                  },
                  "inputsFormatInvalid": {
                    "summary": "Format rules applied to supplied values. See the Input Validation guide for every rule",
                    "value": {
                      "error": "INVALID_INPUTS",
                      "message": "Required inputs are missing or invalid.",
                      "details": {
                        "invalidInputs": {
                          "claimChargeAmount": "claimChargeAmount is scientific notation",
                          "dateOfService": "dateOfService is invalid",
                          "phoneNumber": "phoneNumber is not a valid U.S. phone number"
                        }
                      }
                    }
                  },
                  "inputValueNotString": {
                    "summary": "A value is not a string. The type gate runs before any format rule, and covers keys outside the schema too",
                    "value": {
                      "error": "INVALID_INPUTS",
                      "message": "Required inputs are missing or invalid.",
                      "details": {
                        "invalidInputs": {
                          "priorDenialReason": "priorDenialReason must be a string (got dict)"
                        }
                      }
                    }
                  },
                  "memberIdRejected": {
                    "summary": "Member-ID validation (only when enabled for your account): here a BCBS payer with a too-short memberId",
                    "value": {
                      "error": "INVALID_INPUTS",
                      "message": "Required inputs are missing or invalid.",
                      "details": {
                        "invalidInputs": {
                          "memberId": "memberId 'ABC' is too short to be a BCBS member ID (got 3 characters, minimum is 9). BCBS Federal IDs are 9 chars (R + 8 digits); commercial IDs are typically 11+."
                        }
                      }
                    }
                  },
                  "dailyLimitZero": {
                    "summary": "Daily call limit on the account is configured at 0",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "Daily calls limit is set to 0: cannot schedule batches"
                    }
                  },
                  "capacityExceeded": {
                    "summary": "Account is fully booked beyond the 365-day scheduling horizon",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "Could not schedule all rows within 365 days: 5 of 100 rows could not be placed"
                    }
                  },
                  "batchEmpty": {
                    "summary": "Batch: requests array missing or empty",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "The 'requests' array must contain at least one entry."
                    }
                  },
                  "payerNotFound": {
                    "summary": "Payer phone number lookup: `payerName` did not match any known payer (only fires when `phoneNumber` was omitted).",
                    "value": {
                      "error": "PAYER_NOT_FOUND",
                      "message": "Could not match the supplied payerName to any known payer."
                    }
                  },
                  "batchAllFailed": {
                    "summary": "Batch: every entry failed validation (per-entry envelopes; HTTP 400 because no entry succeeded and no entry hit a server error). Note: schema-not-found surfaces here as `INVALID_REQUEST` with the validator's `Schema not found` message because batch entries don't carry status codes. Read `message` to distinguish 4xx causes.",
                    "value": {
                      "requests": [
                        {
                          "error": "INVALID_REQUEST",
                          "message": "Schema not found"
                        },
                        {
                          "error": "INVALID_REQUEST",
                          "message": "schemaId is required"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired. The gateway uses its own envelope (`{code, message}`), distinct from the service's `ApiError`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  },
                  "malformedJwt": {
                    "summary": "Authorization header value isn't a valid JWT",
                    "value": { "code": 401, "message": "Jwt is not in the form of Header.Payload.Signature with two dots and 3 sections" }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Resource not found: schema or account.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "schemaNotFound": {
                    "summary": "schemaId does not exist for this account, or has been retired",
                    "value": {
                      "error": "SCHEMA_NOT_FOUND",
                      "message": "No schema with that ID exists for your account."
                    }
                  },
                  "accountNotFound": {
                    "summary": "The API key resolves to an account that no longer exists. Rare: wrong-API-key cases hit `INVALID_API_KEY` at `/v1/auth` first.",
                    "value": {
                      "error": "ACCOUNT_NOT_FOUND",
                      "message": "No account is associated with this API key. Contact support if you believe this is an error."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error. **Single-item POST:** body is the top-level `INTERNAL_ERROR` envelope. **Batch POST:** body can take **either** of two shapes: top-level `INTERNAL_ERROR` envelope (the common case), or `{\"requests\": [...]}` with per-entry envelopes (rarer: every entry failed and at least one was a server error). Check for the `requests` key to tell the two shapes apart.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiError" },
                    { "$ref": "#/components/schemas/CreateRequestBatchResponse" }
                  ]
                },
                "examples": {
                  "singleInternalError": {
                    "summary": "Single: unexpected server failure",
                    "value": {
                      "error": "INTERNAL_ERROR",
                      "message": "An internal error occurred. Please try again or contact support if the problem persists."
                    }
                  },
                  "payerLookupFailure": {
                    "summary": "Payer phone number lookup: matched a payer but no phone on file, or transient infra failure. Retry with backoff.",
                    "value": {
                      "error": "PAYER_LOOKUP_FAILURE",
                      "message": "Could not retrieve a phone number for the resolved payer. Please retry, or supply phoneNumber explicitly."
                    }
                  },
                  "batchInternalError": {
                    "summary": "Batch: exception raised mid-processing (most common). Top-level `ApiError` envelope, no `requests` key.",
                    "value": {
                      "error": "INTERNAL_ERROR",
                      "message": "An internal error occurred. Please try again or contact support if the problem persists."
                    }
                  },
                  "batchAllServerErrors": {
                    "summary": "Batch: every entry failed and at least one was a server error (rarer; per-entry shape). Server-error entries surface as `INVALID_REQUEST` with the underlying message (the per-entry translator does not propagate `INTERNAL_ERROR`).",
                    "value": {
                      "requests": [
                        {
                          "error": "INVALID_REQUEST",
                          "message": "Failed to enqueue request"
                        },
                        {
                          "error": "INVALID_REQUEST",
                          "message": "schemaId is required"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["Requests"],
        "summary": "List Requests",
        "description": "Retrieve requests filtered by date range or batch ID.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date" },
            "description": "**Optional.** Start of the `dateCreated` window (inclusive), `YYYY-MM-DD`. Interpreted as UTC midnight. When omitted (and `requestBatchId` is also omitted), defaults to today in the server's clock."
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date" },
            "description": "**Optional.** End of the `dateCreated` window (**exclusive**), `YYYY-MM-DD`. Interpreted as UTC midnight. When omitted (and `requestBatchId` is also omitted), defaults to tomorrow in the server's clock."
          },
          {
            "name": "requestBatchId",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "**Optional.** Return every request belonging to this `requestBatchId`. Bypasses the `dateFrom`/`dateTo` defaults. Passing this returns matching requests regardless of when they were created."
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 500 },
            "description": "**Optional.** Turns on pagination. Maximum number of requests to return in one page (1 to 500). Omit to return every matching request in one response. A value outside the range is rejected with `400 INVALID_REQUEST`."
          },
          {
            "name": "pageToken",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "**Optional.** Opaque cursor from a previous response's `nextPageToken`. Resumes the listing where the previous page ended. Keep the other filters unchanged across pages. Passing `pageToken` without `pageSize` applies the default page size of 100. A malformed token is rejected with `400 INVALID_REQUEST`."
          }
        ],
        "responses": {
          "200": {
            "description": "List of requests. The list endpoint omits `transcript` and `recordingDownloadUrl`. Fetch `GET /v1/requests/{requestId}` for those. Every other field on `RequestResponse` (including `state`, `modality`, `data_completeness`, `error`) is included when applicable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/RequestResponse" }
                    },
                    "nextPageToken": {
                      "type": "string",
                      "description": "Present only when more pages remain, which requires `pageSize` (or `pageToken`) on the request. Pass it back as `pageToken` to fetch the next page. Absent on the final page."
                    }
                  }
                },
                "examples": {
                  "list": {
                    "summary": "Four requests showing one of each state (SUCCESS, PARTIAL, FAILURE, PROCESSING)",
                    "value": {
                      "requests": [
                        {
                          "requestId": "8bF7xK2mP9qR4sT6uV0w",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "requestType": "claim-status",
                          "state": "SUCCESS",
                          "inputs": {
                            "payerName": "Sample Insurance Co",
                            "memberId": "TEST123456789",
                            "patientFirstName": "Sample",
                            "patientLastName": "Patient",
                            "patientDateOfBirth": "1990-01-15",
                            "beginningDateOfService": "2026-03-15",
                            "billingProviderName": "Test Clinic LLC",
                            "billingProviderTaxId": "999999999",
                            "renderingProviderName": "Dr Test Provider",
                            "renderingProviderNpi": "1234567890",
                            "claimChargeAmount": "150.00",
                            "phoneNumber": "2125551234"
                          },
                          "results": {
                            "claimStatus": "PAID",
                            "paidAmount": "150.00",
                            "checkNumber": "CHK998877",
                            "paidDate": "2026-04-10"
                          },
                          "missingFields": [],
                          "dateCreated": "2026-04-24T15:30:00.123456+00:00",
                          "completedAt": "2026-04-24T15:32:18.987654+00:00",
                          "dueDate": "2026-04-25T23:00:00+00:00",
                          "internalId": "claim_internal_001",
                          "internalTag": "march-batch",
                          "modality": "phone_only",
                          "data_completeness": null,
                          "error": null,
                          "to": "+12125551234",
                          "callDuration": "00:08:42",
                          "callSummary": "Verified claim status as PAID."
                        },
                        {
                          "requestId": "kT9bR2mP6nE3yV1xD7Aq",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "requestType": "claim-status",
                          "state": "PARTIAL",
                          "inputs": {
                            "payerName": "Sample Insurance Co",
                            "memberId": "TEST555444333",
                            "patientFirstName": "Sample",
                            "patientLastName": "Patient",
                            "patientDateOfBirth": "1990-01-15",
                            "beginningDateOfService": "2026-03-15",
                            "billingProviderName": "Test Clinic LLC",
                            "billingProviderTaxId": "999999999",
                            "renderingProviderName": "Dr Test Provider",
                            "renderingProviderNpi": "1234567890",
                            "claimChargeAmount": "150.00",
                            "phoneNumber": "2125551234"
                          },
                          "results": {
                            "claimStatus": "PAID",
                            "paidAmount": "150.00"
                          },
                          "missingFields": ["checkNumber", "paidDate"],
                          "dateCreated": "2026-04-24T15:33:10.123000+00:00",
                          "completedAt": "2026-04-24T15:36:42.456000+00:00",
                          "dueDate": "2026-04-25T23:00:00+00:00",
                          "internalId": "claim_internal_002",
                          "internalTag": "march-batch",
                          "modality": "digital_plus_phone",
                          "data_completeness": null,
                          "error": null,
                          "to": "+12125551234",
                          "callDuration": "00:06:24",
                          "callSummary": "Confirmed the claim is PAID for $150.00 on the primary call; a follow-up call for the check number and paid date did not complete."
                        },
                        {
                          "requestId": "nQ4rW8sT1vY3zE5xC2bV",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "requestType": "claim-status",
                          "state": "FAILURE",
                          "inputs": {
                            "payerName": "Sample Insurance Co",
                            "memberId": "BADID000",
                            "patientFirstName": "Sample",
                            "patientLastName": "Patient",
                            "patientDateOfBirth": "1990-01-15",
                            "beginningDateOfService": "2026-03-15",
                            "billingProviderName": "Test Clinic LLC",
                            "billingProviderTaxId": "999999999",
                            "renderingProviderName": "Dr Test Provider",
                            "renderingProviderNpi": "1234567890",
                            "claimChargeAmount": "150.00",
                            "phoneNumber": "2125551234"
                          },
                          "results": {},
                          "missingFields": [],
                          "dateCreated": "2026-04-24T15:32:00.000000+00:00",
                          "completedAt": "2026-04-24T15:35:11.222333+00:00",
                          "dueDate": "2026-04-25T23:00:00+00:00",
                          "internalId": "claim_internal_003",
                          "internalTag": "march-batch",
                          "modality": "phone_only",
                          "data_completeness": null,
                          "error": {
                            "errorCategory": "NOT_FOUND",
                            "errorCode": "MEMBER_NOT_FOUND",
                            "errorMessage": "Member could not be located"
                          },
                          "to": "+12125551234",
                          "callDuration": "00:04:11",
                          "callSummary": "Representative could not locate the member; lookup failed."
                        },
                        {
                          "requestId": "aC3hN5jD8eL1fM2gK6Yo",
                          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "requestType": "claim-status",
                          "state": "PROCESSING",
                          "inputs": {
                            "payerName": "Sample Insurance Co",
                            "memberId": "TEST987654321",
                            "patientFirstName": "Sample",
                            "patientLastName": "Patient",
                            "patientDateOfBirth": "1990-01-15",
                            "beginningDateOfService": "2026-03-15",
                            "billingProviderName": "Test Clinic LLC",
                            "billingProviderTaxId": "999999999",
                            "renderingProviderName": "Dr Test Provider",
                            "renderingProviderNpi": "1234567890",
                            "claimChargeAmount": "150.00",
                            "phoneNumber": "2125551234"
                          },
                          "results": {},
                          "missingFields": [],
                          "dateCreated": "2026-04-24T15:31:02.456789+00:00",
                          "completedAt": null,
                          "dueDate": "2026-04-25T23:00:00+00:00",
                          "internalId": "claim_internal_004",
                          "internalTag": "march-batch",
                          "modality": null,
                          "data_completeness": null,
                          "error": null
                        }
                      ]
                    }
                  },
                  "empty": {
                    "summary": "No requests matched the window",
                    "value": { "requests": [] }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  },
                  "malformedJwt": {
                    "summary": "Authorization header value isn't a valid JWT",
                    "value": { "code": 401, "message": "Jwt is not in the form of Header.Payload.Signature with two dots and 3 sections" }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameter.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "invalidDateFrom": {
                    "summary": "`dateFrom` is not a valid `YYYY-MM-DD` date",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "dateFrom must be a YYYY-MM-DD date."
                    }
                  },
                  "invalidDateTo": {
                    "summary": "`dateTo` is not a valid `YYYY-MM-DD` date",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "dateTo must be a YYYY-MM-DD date."
                    }
                  },
                  "invalidPageSize": {
                    "summary": "`pageSize` is not an integer between 1 and 500",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "pageSize must be an integer between 1 and 500."
                    }
                  },
                  "invalidPageToken": {
                    "summary": "`pageToken` is not a cursor we issued",
                    "value": {
                      "error": "INVALID_REQUEST",
                      "message": "pageToken is malformed."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Account not found: the API key does not resolve to a provisioned account.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "ACCOUNT_NOT_FOUND",
                  "message": "No account is associated with this API key. Contact support if you believe this is an error."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error. Retry once; escalate if persistent.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          }
        }
      }
    },
    "/v1/requests/{requestId}": {
      "get": {
        "tags": ["Requests"],
        "summary": "Retrieve a Request",
        "description": "Fetch details for a request by ID.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The request ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Request retrieved successfully. Single-request reads include phone-call enrichment fields (`transcript`, `recordingDownloadUrl`, etc.) when a representative call has completed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RequestResponse" },
                "examples": {
                  "success": {
                    "summary": "Successfully retrieved a request that completed with results: every required field populated.",
                    "value": {
                      "requestId": "8bF7xK2mP9qR4sT6uV0w",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "claim-status",
                      "state": "SUCCESS",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST123456789",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "beginningDateOfService": "2026-03-15",
                        "billingProviderName": "Test Clinic LLC",
                        "billingProviderTaxId": "999999999",
                        "renderingProviderName": "Dr Test Provider",
                        "renderingProviderNpi": "1234567890",
                        "claimChargeAmount": "150.00",
                        "phoneNumber": "2125551234"
                      },
                      "results": {
                        "claimStatus": "PAID",
                        "paidAmount": "150.00",
                        "checkNumber": "CHK998877",
                        "paidDate": "2026-04-10"
                      },
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:30:00.123456+00:00",
                      "completedAt": "2026-04-24T15:32:18.987654+00:00",
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_001",
                      "internalTag": "march-batch",
                      "modality": "phone_only",
                      "data_completeness": null,
                      "error": null,
                      "to": "+12125551234",
                      "transcript": "SuperDial Agent: Hi, I'm calling to check on a claim status for member TEST123456789.\nRepresentative: Let me look that up for you...",
                      "recordingDownloadUrl": "https://storage.googleapis.com/sd-recordings/.../recording.mp3?X-Goog-Signature=...",
                      "callDuration": "00:08:42",
                      "callSummary": "Verified claim status as PAID. Check #CHK998877 issued on 2026-04-10 for $150.00.",
                      "callAuditSummary": "All claim status questions answered. Representative confirmed paid amount and check number."
                    }
                  },
                  "successDigitalOnly": {
                    "summary": "SUCCESS via digital channels only: `data_completeness` is `\"minimum\"` to flag that a phone call could have yielded richer data.",
                    "value": {
                      "requestId": "rD2bV4mK7nE9yX1cP5Lo",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "claim-status",
                      "state": "SUCCESS",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST111222333",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "beginningDateOfService": "2026-03-15",
                        "billingProviderName": "Test Clinic LLC",
                        "billingProviderTaxId": "999999999",
                        "renderingProviderName": "Dr Test Provider",
                        "renderingProviderNpi": "1234567890",
                        "claimChargeAmount": "150.00",
                        "phoneNumber": "2125551234"
                      },
                      "results": {
                        "claimStatus": "PAID",
                        "paidAmount": "150.00",
                        "checkNumber": "CHK112233",
                        "paidDate": "2026-04-12"
                      },
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:35:00.123456+00:00",
                      "completedAt": "2026-04-24T15:35:08.456789+00:00",
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_005",
                      "internalTag": "march-batch",
                      "modality": "digital_only",
                      "data_completeness": "minimum",
                      "error": null
                    }
                  },
                  "failureNoResults": {
                    "summary": "FAILURE (NOT_FOUND): the payer couldn't find the member. `results` is `{}` and `error` names the cause.",
                    "value": {
                      "requestId": "nQ4rW8sT1vY3zE5xC2bV",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "vob",
                      "state": "FAILURE",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST555444333",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "phoneNumber": "2125551234"
                      },
                      "results": {},
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:32:00.000000+00:00",
                      "completedAt": "2026-04-24T15:35:11.222333+00:00",
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_002",
                      "internalTag": "march-batch",
                      "modality": "phone_only",
                      "data_completeness": null,
                      "error": {
                        "errorCategory": "NOT_FOUND",
                        "errorCode": "MEMBER_NOT_FOUND",
                        "errorMessage": "Member could not be located"
                      },
                      "payerLookup": {
                        "inputPayerName": "Sample Insurance Co",
                        "inputPhoneNumber": "2125551234",
                        "matchedPayerName": null,
                        "matchedPayerPhone": null,
                        "phoneNumberToUse": "2125551234",
                        "phoneNumberSource": "input"
                      },
                      "resultSummary": null,
                      "to": "+12125551234",
                      "callDuration": "00:04:11",
                      "callSummary": "Representative could not locate the member.",
                      "callSteps": [
                        {
                          "key": "verification-of-benefits",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "name": "Verification of Benefits",
                          "state": "FAILURE",
                          "fieldsRequired": 2,
                          "fieldsCaptured": 0,
                          "missingFields": [
                            "planActive",
                            "copay"
                          ],
                          "numContributingCalls": 1,
                          "triggeredBy": null,
                          "error": {
                            "errorCategory": "NOT_FOUND",
                            "errorCode": "MEMBER_NOT_FOUND",
                            "errorMessage": "Member could not be located"
                          }
                        }
                      ]
                    }
                  },
                  "partial": {
                    "summary": "PARTIAL (accounts with follow-up calls only): the benefits call succeeded but the prior-authorization follow-up failed. `results` holds the benefits answers, `error` is `null`, and the failed step's gaps and cause are in `callSteps`.",
                    "value": {
                      "requestId": "kT9bR2mP6nE3yV1xD7Aq",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "vob",
                      "state": "PARTIAL",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST555444333",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "phoneNumber": "2125551234"
                      },
                      "results": {
                        "planActive": "YES",
                        "copay": "30.00"
                      },
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:33:10.123000+00:00",
                      "completedAt": "2026-04-24T15:41:42.456000+00:00",
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_003",
                      "internalTag": "march-batch",
                      "modality": "phone_only",
                      "data_completeness": null,
                      "error": null,
                      "payerLookup": {
                        "inputPayerName": "Sample Insurance Co",
                        "inputPhoneNumber": "2125551234",
                        "matchedPayerName": null,
                        "matchedPayerPhone": null,
                        "phoneNumberToUse": "2125551234",
                        "phoneNumberSource": "input"
                      },
                      "resultSummary": null,
                      "to": "+12125551234",
                      "callDuration": "00:06:12",
                      "callSummary": "Confirmed plan active; copay $30.",
                      "callSteps": [
                        {
                          "key": "verification-of-benefits",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "name": "Verification of Benefits",
                          "state": "SUCCESS",
                          "fieldsRequired": 2,
                          "fieldsCaptured": 2,
                          "missingFields": [],
                          "numContributingCalls": 1,
                          "triggeredBy": null
                        },
                        {
                          "key": "prior-authorization",
                          "schemaId": "qP2bN8rT6mK1xC3vW9aL",
                          "name": "Prior Authorization",
                          "state": "FAILURE",
                          "fieldsRequired": 2,
                          "fieldsCaptured": 0,
                          "missingFields": [
                            "priorAuthRequired",
                            "priorAuthNumber"
                          ],
                          "numContributingCalls": 1,
                          "triggeredBy": "verification-of-benefits",
                          "error": {
                            "errorCategory": "SYSTEM_ERROR",
                            "errorCode": "UNABLE_TO_REACH_HUMAN_IN_TIME",
                            "errorMessage": "Could not connect to a human representative"
                          }
                        }
                      ],
                      "contributingCalls": [
                        {
                          "id": "9nQ4vT7xB2mK5pR8sL0w",
                          "call": 1,
                          "callStep": "verification-of-benefits",
                          "callDuration": "00:06:12",
                          "callSummary": "Confirmed plan active; copay $30.",
                          "fieldsCaptured": [
                            "planActive",
                            "copay"
                          ]
                        },
                        {
                          "id": "3kW8yH2nR5tL9pM4vB0x",
                          "call": 2,
                          "callStep": "prior-authorization",
                          "to": "+18005559090",
                          "callDuration": "00:12:30",
                          "callSummary": "Held past the time limit without reaching a representative.",
                          "fieldsCaptured": []
                        }
                      ],
                      "resultSources": {
                        "planActive": 1,
                        "copay": 1
                      }
                    }
                  },
                  "failureSystemError": {
                    "summary": "FAILURE (SYSTEM_ERROR): no representative answered within the retry budget. `results` is `{}` and `error.errorCode` is `UNABLE_TO_REACH_HUMAN_IN_TIME`.",
                    "value": {
                      "requestId": "vM7gB4nC2pE9yU1xH3Tj",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "vob",
                      "state": "FAILURE",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST555444333",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "phoneNumber": "2125551234"
                      },
                      "results": {},
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:34:20.456000+00:00",
                      "completedAt": "2026-04-24T16:02:55.789000+00:00",
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_004",
                      "internalTag": "march-batch",
                      "modality": "phone_only",
                      "data_completeness": null,
                      "error": {
                        "errorCategory": "SYSTEM_ERROR",
                        "errorCode": "UNABLE_TO_REACH_HUMAN_IN_TIME",
                        "errorMessage": "Could not connect to a human representative"
                      },
                      "payerLookup": {
                        "inputPayerName": "Sample Insurance Co",
                        "inputPhoneNumber": "2125551234",
                        "matchedPayerName": null,
                        "matchedPayerPhone": null,
                        "phoneNumberToUse": "2125551234",
                        "phoneNumberSource": "input"
                      },
                      "resultSummary": null,
                      "to": "+12125551234",
                      "callDuration": "00:15:00",
                      "callSummary": "Held past the time limit without reaching a representative.",
                      "callSteps": [
                        {
                          "key": "verification-of-benefits",
                          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                          "name": "Verification of Benefits",
                          "state": "FAILURE",
                          "fieldsRequired": 2,
                          "fieldsCaptured": 0,
                          "missingFields": [
                            "planActive",
                            "copay"
                          ],
                          "numContributingCalls": 1,
                          "triggeredBy": null,
                          "error": {
                            "errorCategory": "SYSTEM_ERROR",
                            "errorCode": "UNABLE_TO_REACH_HUMAN_IN_TIME",
                            "errorMessage": "Could not connect to a human representative"
                          }
                        }
                      ]
                    }
                  },
                  "processing": {
                    "summary": "PROCESSING: request still running; no modality dispatched yet, no terminal data.",
                    "value": {
                      "requestId": "aC3hN5jD8eL1fM2gK6Yo",
                      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
                      "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
                      "requestType": "claim-status",
                      "state": "PROCESSING",
                      "inputs": {
                        "payerName": "Sample Insurance Co",
                        "memberId": "TEST987654321",
                        "patientFirstName": "Sample",
                        "patientLastName": "Patient",
                        "patientDateOfBirth": "1990-01-15",
                        "beginningDateOfService": "2026-03-15",
                        "billingProviderName": "Test Clinic LLC",
                        "billingProviderTaxId": "999999999",
                        "renderingProviderName": "Dr Test Provider",
                        "renderingProviderNpi": "1234567890",
                        "claimChargeAmount": "150.00",
                        "phoneNumber": "2125551234"
                      },
                      "results": {},
                      "missingFields": [],
                      "dateCreated": "2026-04-24T15:31:02.456789+00:00",
                      "completedAt": null,
                      "dueDate": "2026-04-25T23:00:00+00:00",
                      "internalId": "claim_internal_004",
                      "internalTag": "march-batch",
                      "modality": null,
                      "data_completeness": null,
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Request not found, or account not found.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "examples": {
                  "requestNotFound": {
                    "summary": "Request ID does not exist for this account",
                    "value": {
                      "error": "REQUEST_NOT_FOUND",
                      "message": "No request with that ID exists for your account."
                    }
                  },
                  "accountNotFound": {
                    "summary": "The API key resolves to an account that no longer exists. Rare: wrong-API-key cases hit `INVALID_API_KEY` at `/v1/auth` first.",
                    "value": {
                      "error": "ACCOUNT_NOT_FOUND",
                      "message": "No account is associated with this API key. Contact support if you believe this is an error."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error. Retry once; escalate if persistent.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "error": "INTERNAL_ERROR",
                  "message": "An internal error occurred. Please try again or contact support if the problem persists."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: enforced by the API gateway. Returned when the `Authorization: Bearer <token>` header is missing, malformed, or the token is invalid/expired.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer realm and (when applicable) error code per RFC 6750.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayErrorResponse" },
                "examples": {
                  "missingAuth": {
                    "summary": "No Authorization header",
                    "value": { "code": 401, "message": "Jwt is missing" }
                  },
                  "malformedJwt": {
                    "summary": "Authorization header value isn't a valid JWT",
                    "value": { "code": 401, "message": "Jwt is not in the form of Header.Payload.Signature with two dots and 3 sections" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Robodialer-API-Key",
        "description": "Your SuperDial API key"
      },
      "apiSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "Robodialer-API-Secret",
        "description": "Your SuperDial API secret"
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer token obtained from the /v1/auth endpoint"
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "description": "Uniform error envelope returned by every non-2xx response from `/v1/requests` and `/v1/schemas`. The `error` field is a stable machine-readable code; the `message` field is a human-readable description safe to surface to end users; `details` (optional) carries the structured `missingInputs` / `invalidInputs` block on the `INVALID_INPUTS` path. Unmatched paths and unsupported HTTP methods fall back to the framework's default response (typically HTML); use a documented endpoint and method to receive this envelope.",
        "required": ["error", "message"],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "INVALID_REQUEST",
              "INVALID_INPUTS",
              "PAYER_NOT_FOUND",
              "ACCOUNT_NOT_FOUND",
              "SCHEMA_NOT_FOUND",
              "REQUEST_NOT_FOUND",
              "INTERNAL_ERROR",
              "PAYER_LOOKUP_FAILURE",
              "PAYER_REQUIRED_INPUTS_DISABLED"
            ],
            "description": "Machine-readable error code for the HTTP envelope. See [Creating a Request → Error handling](/guides/creating-a-request#error-handling) for what each code means, when it fires, and how to handle it."
          },
          "message": {
            "type": "string",
            "description": "Human-readable error description. Never contains stack traces or internal identifiers."
          },
          "details": {
            "type": "object",
            "description": "**Optional.** Currently set only for `INVALID_INPUTS`, where it contains `missingInputs` (array of field names) and/or `invalidInputs` (object mapping field name to reason). See the [Input Validation](/guides/input-validation) guide for the full set of rules behind these reasons.",
            "properties": {
              "missingInputs": {
                "type": "array",
                "description": "Field names that were required but absent, null, or empty/whitespace-only.",
                "items": { "type": "string" }
              },
              "invalidInputs": {
                "type": "object",
                "description": "Maps each rejected field name to a human-readable reason (e.g. `phoneNumber is not a valid U.S. phone number`, `claimChargeAmount is scientific notation`, `memberId contains invalid characters (curly braces)`, or a member-ID structure message).",
                "additionalProperties": { "type": "string" }
              }
            }
          }
        }
      },
      "SchemaSummary": {
        "type": "object",
        "description": "One row in the `GET /v1/schemas` response.",
        "required": ["schemaId", "name", "requestType"],
        "properties": {
          "schemaId": {
            "type": "string",
            "description": "Stable identifier for the schema. Pass to `POST /v1/requests` as `schemaId`."
          },
          "name": {
            "type": "string",
            "description": "Human-readable schema name. Falls back to the `schemaId` if no name was set."
          },
          "requestType": {
            "type": "string",
            "description": "The kind of extraction this schema produces (e.g. `vob`, `claim-status`). Server-derived; surfaces on `RequestResponse.requestType` after the request runs. You don't need to pass it on `POST /v1/requests`."
          }
        }
      },
      "ListSchemasResponse": {
        "type": "object",
        "description": "Success response from `GET /v1/schemas`.",
        "required": ["schemas"],
        "properties": {
          "schemas": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SchemaSummary" },
            "description": "Schemas that have been retired or hidden for your account are filtered out of this list."
          }
        }
      },
      "SchemaDetailResponse": {
        "type": "object",
        "description": "Success response from `GET /v1/schemas/{schemaId}`. New keys may be added over time; ignore ones you do not recognise. Inputs are deliberately not included — see `GET /v1/schemas/{schemaId}/required-inputs`.",
        "required": ["schemaId", "name", "requestType", "resultsFields"],
        "properties": {
          "schemaId": {
            "type": "string",
            "description": "Echoes the path parameter."
          },
          "name": {
            "type": "string",
            "description": "Human-readable schema name, the same value as in `GET /v1/schemas`. Falls back to the `schemaId` when the schema sets no name."
          },
          "requestType": {
            "type": "string",
            "description": "The request type this schema produces (e.g. `vob`, `claim-status`), the same value as in `GET /v1/schemas`. Informational: derived from the schema, not something you supply on `POST /v1/requests`, which is keyed on `schemaId`."
          },
          "resultsFields": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SchemaFieldDefinition" },
            "description": "Every field this schema can return in `results`, sorted by `name`, describing the schema's current latest version. Never empty: a schema with no readable fields returns `500`. A superset of the keys any single request contributes from this schema. A chained request can also carry a follow-up schema's keys, which are not listed here."
          }
        }
      },
      "SchemaFieldDefinition": {
        "type": "object",
        "description": "One field a schema can return. `name` is the key that carries this field's value in `results` on `GET /v1/requests/{requestId}`. Optional keys are omitted, never `null`.",
        "required": ["name", "label"],
        "properties": {
          "name": {
            "type": "string",
            "description": "The `results` key for this field, and the value used in the top-level `missingFields`. Always present."
          },
          "label": {
            "type": "string",
            "description": "Human-readable display name. Falls back to `name` when the schema sets none. Always present."
          },
          "description": {
            "type": "string",
            "description": "What the field captures, usually the question the agent asks. May contain literal `{placeholder}` tokens; those are input *names*, never values. Omitted when empty."
          },
          "type": {
            "type": "string",
            "description": "Declared value type. Wire shapes: `boolean` → JSON `true`/`false`; `date` → ISO `yyyy-mm-dd` string; `dollar`, `number`, `percentage` → **bare-numeric string OR JSON number; accept both** (`dollar` carries no `$`); `multiple` → one of `allowedValues`; `text`, `alphanumeric`, `address`, `phoneNumber`, `faxNumber` → string. Those eleven are the full vocabulary. A schema can still declare a type outside the list, which is returned as-is, so treat an unrecognised `type` as an opaque string. A value of `CANNOT ANSWER - <reason>` can arrive as a string on any type, including `boolean` and `multiple`. Omitted when the schema declares no type."
          },
          "allowedValues": {
            "type": "array",
            "items": { "type": "string" },
            "description": "The declared choices, present on `multiple` fields. **Not a closed set**: `CANNOT ANSWER - <reason>` can arrive instead. Omitted when the schema declares no choices."
          }
        }
      },
      "RequiredInputsResponse": {
        "type": "object",
        "description": "Success response from `GET /v1/schemas/{schemaId}/required-inputs`. Carries both required and optional input field lists; the two are disjoint: if a name is required by any source, it appears only in `requiredInputs.fields`.",
        "required": ["schemaId", "requiredInputs", "optionalInputs"],
        "properties": {
          "schemaId": {
            "type": "string",
            "description": "Echoes the path parameter."
          },
          "requiredInputs": {
            "type": "object",
            "required": ["fields"],
            "properties": {
              "fields": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Sorted list of required input field names. Use these as the keys of the `inputs` object on `POST /v1/requests`. Returned verbatim: the names are exactly what the request validator expects. This is the baseline; with per-payer required inputs enabled, some payers require additional fields not listed here."
              }
            }
          },
          "optionalInputs": {
            "type": "object",
            "required": ["fields"],
            "properties": {
              "fields": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Sorted list of optional input field names, accepted but not required by `POST /v1/requests`. Disjoint from `requiredInputs.fields`. This is what the schema declares, not a limit on what `inputs` accepts: `POST /v1/requests` also takes additional keys that appear in neither list."
              }
            }
          }
        }
      },
      "RequiredPayerInputsRequest": {
        "type": "object",
        "description": "Request body for `POST /v1/schemas/{schemaId}/required-payer-inputs`.",
        "required": ["payerNames"],
        "properties": {
          "payerNames": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": { "type": "string" },
            "description": "Payer names to resolve, 1–50 per request. Resolved independently, in order, with no de-duplication. The response's `payers` array is positionally aligned 1:1 with this array. More than 50 entries returns 400 `INVALID_REQUEST` (no truncation). A blank/whitespace-only entry is not a whole-request error. It comes back as a per-payer `INVALID_PAYER_NAME` entry in `payers`."
          }
        },
        "example": {
          "payerNames": ["Sample Insurance Co", "Unknown Payer"]
        }
      },
      "RequiredPayerInputsResponse": {
        "type": "object",
        "description": "Success body from `POST /v1/schemas/{schemaId}/required-payer-inputs`. Carries the schema's own `requiredInputs`/`optionalInputs` (identical shape and semantics to `GET /v1/schemas/{schemaId}/required-inputs`) plus a `payers` array with one entry per requested name.",
        "required": ["schemaId", "requiredInputs", "optionalInputs", "payers"],
        "properties": {
          "schemaId": {
            "type": "string",
            "description": "Echoes the path parameter."
          },
          "requiredInputs": {
            "type": "object",
            "required": ["fields"],
            "properties": {
              "fields": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Sorted schema-level required input field names: the baseline every request against this schema needs, independent of payer."
              }
            }
          },
          "optionalInputs": {
            "type": "object",
            "required": ["fields"],
            "properties": {
              "fields": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Sorted schema-level optional input field names. Disjoint from `requiredInputs.fields`."
              }
            }
          },
          "payers": {
            "type": "array",
            "description": "One entry per `payerNames` entry, in input order, with no de-duplication (positionally aligned 1:1 with the request). Each item is either a `MatchedPayerEntry` or a `PayerInputError`. Discriminate on the presence of `errorCode`.",
            "items": {
              "oneOf": [
                { "$ref": "#/components/schemas/MatchedPayerEntry" },
                { "$ref": "#/components/schemas/PayerInputError" }
              ]
            }
          }
        }
      },
      "MatchedPayerEntry": {
        "type": "object",
        "description": "A `payers[]` entry for a name that resolved to a canonical payer. The resolved phone number is intentionally omitted: dialing happens server-side and is never echoed back.",
        "required": ["inputPayerName", "matchedPayerName", "payerRequiredInputs"],
        "properties": {
          "inputPayerName": {
            "type": "string",
            "description": "Echoes the requested name (trimmed of surrounding whitespace), verbatim."
          },
          "matchedPayerName": {
            "type": "string",
            "description": "Canonical payer name SuperDial matched. Compare against `inputPayerName` to confirm the match landed where you expected."
          },
          "payerRequiredInputs": {
            "type": "object",
            "required": ["fields"],
            "properties": {
              "fields": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Sorted list of the **additional** required-input field names this payer needs, beyond the schema-level `requiredInputs.fields`, not the full set (it may be empty when the payer adds nothing). Union it with `requiredInputs.fields` to get everything a request for this payer must supply to avoid an `INVALID_INPUTS` rejection."
              }
            }
          }
        }
      },
      "PayerInputError": {
        "type": "object",
        "description": "A `payers[]` entry for a name that could not be resolved. This is an inline, per-payer error: it does not fail the whole request. Distinguished from `MatchedPayerEntry` by the presence of `errorCode`.",
        "required": ["inputPayerName", "errorCode", "message"],
        "properties": {
          "inputPayerName": {
            "type": "string",
            "description": "Echoes the requested name, verbatim (empty string when the input was blank/whitespace-only)."
          },
          "errorCode": {
            "type": "string",
            "enum": ["INVALID_PAYER_NAME", "PAYER_NOT_FOUND", "PAYER_LOOKUP_FAILURE"],
            "description": "`INVALID_PAYER_NAME`: the entry was blank/whitespace-only, so no lookup ran. `PAYER_NOT_FOUND`: no canonical payer matched the name. `PAYER_LOOKUP_FAILURE`: the lookup errored transiently; retry that name. These codes are scoped to this array and are distinct from the whole-request `{error, message}` envelope."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the per-payer failure."
          }
        }
      },
      "AuthTokenResponse": {
        "type": "object",
        "description": "Response from `GET /v1/auth`. Contains a short-lived bearer token usable as `Authorization: Bearer <token>` on subsequent calls.",
        "required": ["token"],
        "properties": {
          "token": {
            "type": "string",
            "description": "Short-lived bearer token (1-hour TTL)."
          }
        },
        "example": {
          "token": "eyJhbGciOiJSUzI1NiIs...truncated...signature"
        }
      },
      "GatewayErrorResponse": {
        "type": "object",
        "description": "Error envelope returned by the API Gateway for auth failures and routing errors. Distinct from the service's own `ApiError` envelope: gateway responses use `{code, message}` because they're produced before the request reaches the service.",
        "properties": {
          "code": {
            "type": "integer",
            "description": "HTTP status code, repeated in the body.",
            "example": 401
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message from the gateway.",
            "example": "Jwt is missing"
          }
        },
        "required": ["code", "message"]
      },
      "SimpleErrorResponse": {
        "type": "object",
        "description": "Standard error envelope. The `error` field is a human-readable message describing what went wrong; per-endpoint examples are listed under each response.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          }
        },
        "required": ["error"]
      },
      "CreateRequestPayload": {
        "type": "object",
        "required": ["schemaId", "inputs"],
        "properties": {
          "schemaId": { "type": "string", "description": "Schema ID. Discover yours via `GET /v1/schemas`." },
          "requestType": { "type": "string", "description": "**Optional and ignored.** Historical field; the request type is derived server-side from the schema. You'll see the canonical value on the `requestType` field of the `RequestResponse` returned by `GET /v1/requests/{requestId}`." },
          "inputs": {
            "type": "object",
            "additionalProperties": { "type": "string" },
            "description": "Inputs as a flat `{ key: value }` object: every value must be a string or null. The required and optional keys are schema-specific; discover them with `GET /v1/schemas/{schemaId}/required-inputs`. Those two lists are the baseline, not an allow-list: additional keys outside both are accepted, stored with the request, echoed back on reads and webhooks, and given to the voice agent as context on any phone call the request makes. A non-string value (number, boolean, nested object, array) is rejected with `INVALID_INPUTS` and `details.invalidInputs` (`<field> must be a string (got list)`). A field that holds several values is therefore one comma-delimited string, not an array: send `\"cptCodes\": \"99213,99214\"`. The legacy `POST /v1/calls` accepts an array here and this endpoint does not, so check those fields when you migrate. Each supplied value is format-checked by type (phone, date, dollar amount, boolean, regex-constrained string) and against two universal rules (no scientific notation, no curly braces); some accounts also enforce `memberId` structure and per-payer required inputs. Missing or format-invalid inputs return `INVALID_INPUTS` (400) with `details.missingInputs` and/or `details.invalidInputs`. See the [Input Validation](/guides/input-validation) guide for the full rule list, [Creating a Request](/guides/creating-a-request) for examples, and [Payer Phone Number Lookup](/guides/payer-resolution) for how omitting `phoneNumber` affects the response."
          },
          "webhookUrl": { "type": "string", "nullable": true, "description": "**Optional.** Per-request webhook URL override. Wins over the account-level webhook URL for this single request." },
          "useMatchedPayerPhone": { "type": "boolean", "default": false, "nullable": true, "description": "**Optional.** When `true` and payer phone number lookup is enabled for your account, dial SuperDial's matched payer number even if you supplied `phoneNumber`, falling back to your supplied number when no match is found (no error). When omitted or `false`, a supplied `phoneNumber` is always dialed as-is. Ignored when lookup is off. See [Payer Phone Number Lookup](/guides/payer-resolution#choosing-which-number-to-dial)." },
          "internalId": { "type": "string", "nullable": true, "description": "**Optional** correlation ID that also serves as the request's idempotency key. A retry with the same `internalId` does not create a new request: it returns the original `requestId` and the original `payerLookup` (if any), even if our payer data has changed since. Because it is the idempotency key, a value you supply **must be unique per distinct request**; reusing one silently returns the original request instead of starting new work. If you omit it, SuperDial generates and maintains its own unique key server-side, so you only need to supply one when you want to correlate results to your own records. See the Correlation and idempotency section in the Creating a Request guide." },
          "internalTag": { "type": "string", "nullable": true, "description": "**Optional.** Customer tag, echoed back on reads and webhooks. Useful for grouping requests without polluting your correlation IDs." },
          "aiOnly": { "type": "boolean", "nullable": true, "description": "**Optional.** When `true`, any phone call this request makes is handled only by our automated (AI) voice agent, never a human agent. Leaving it `false` adds no restriction: it does not force human-agent handling. Defaults to `false`." },
          "onshoreOnly": { "type": "boolean", "nullable": true, "description": "**Optional.** When `true`, all phone handling for this request is restricted to US-based agents. Leaving it `false` adds no restriction. Defaults to `false`." }
        },
        "example": {
          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
          "inputs": {
            "payerName": "Sample Insurance Co",
            "memberId": "TEST123456789",
            "phoneNumber": "2125551234",
            "providerNpi": "1234567890",
            "dateOfService": "2026-03-15"
          },
          "internalId": "claim_internal_456",
          "internalTag": "march-batch",
          "aiOnly": true,
          "onshoreOnly": true
        }
      },
      "CreateRequestBatchPayload": {
        "type": "object",
        "required": ["requests"],
        "properties": {
          "requests": {
            "type": "array",
            "minItems": 1,
            "description": "Non-empty array of request bodies. Empty arrays are rejected with HTTP 400.",
            "items": { "$ref": "#/components/schemas/CreateRequestPayload" }
          }
        },
        "example": {
          "requests": [
            {
              "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
              "inputs": { "payerName": "Sample Insurance Co", "memberId": "TEST123456789", "phoneNumber": "2125551234" },
              "internalId": "claim_001"
            },
            {
              "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
              "inputs": { "payerName": "Sample Insurance Co", "memberId": "TEST987654321", "phoneNumber": "2125551234" },
              "internalId": "claim_002"
            }
          ]
        }
      },
      "AttemptDetail": {
        "type": "object",
        "description": "One dial attempt on a phone call. Returned inside `attemptDetails` when your account has attempt details enabled.",
        "properties": {
          "attemptNumber": { "type": "integer", "description": "1-based dial ordinal within the call." },
          "attemptStartTime": { "type": "string", "format": "date-time", "nullable": true, "description": "When the dial started." },
          "attemptEndTime": { "type": "string", "format": "date-time", "nullable": true, "description": "When the dial ended." },
          "attemptSummary": { "type": "string", "description": "Post-call summary for this attempt." },
          "callFromNumber": { "type": "string", "description": "Outbound caller number (E.164) used on this attempt." },
          "callToNumber": { "type": "string", "description": "The number dialed on this attempt, which can differ from `inputs.phoneNumber` (for example after a payer transfer). When the attempt has no number of its own, the call-level dialed number is reported. Omitted when SuperDial resolved the number on your behalf." },
          "agentType": { "type": "string", "enum": ["robo", "human"], "description": "Whether the AI agent (`robo`) or a person (`human`) handled this attempt." },
          "outcome": { "type": "string", "description": "`success`, or a human-readable failure reason." },
          "errorCode": { "type": "string", "description": "Why this attempt did not conclude the call. Omitted on a successful attempt. This vocabulary is per-attempt and separate from the request-level `error.errorCode`. Values today: `PHONE_NUMBER_INCORRECT`, `IVR_VERIFICATION_REJECTED`, `IVR_FAILURE`, `REQUIRES_OTHER_CHANNEL`, `PAYER_REFUSAL`, `PAYER_REFUSAL_AI`, `PAYER_REFUSAL_THIRD_PARTY`, `PAYER_REFUSAL_RECORDING`, `WRONG_DEPARTMENT`, `PAYER_SYSTEM_UNAVAILABLE`, `OFFICE_CLOSED`, `UNABLE_TO_REACH_HUMAN_IN_TIME`, `CALL_DISCONNECTED`, `NO_BLOCKER_IDENTIFIED`, `UNCLASSIFIED`, `OTHER`. **The list is not exhaustive and will grow.** Treat an unrecognized code as an unclassified failure; do not pin client-side validation to it." }
        }
      },
      "PayerLookup": {
        "type": "object",
        "description": "Payer/phone lookup outcome, returned on `POST /v1/requests` success responses and on the `GET /v1/requests` read endpoints. **Always present** on a created request when payer phone number lookup is enabled for your account. `phoneNumberToUse` is the number that will be dialed and `phoneNumberSource` says where it came from. The `matched*` fields are populated **only when SuperDial dials its own matched number** (you omitted `phoneNumber`, or set `useMatchedPayerPhone: true` and a match was found); when your supplied number is dialed they are `null` and `phoneNumberSource` is `input`. See the [Payer Phone Number Lookup guide](/guides/payer-resolution).",
        "required": ["inputPayerName", "inputPhoneNumber", "matchedPayerName", "matchedPayerPhone", "phoneNumberToUse", "phoneNumberSource"],
        "properties": {
          "inputPayerName": {
            "type": "string",
            "nullable": true,
            "description": "Echoes `inputs.payerName` from the request, verbatim. `null` when none was supplied."
          },
          "inputPhoneNumber": {
            "type": "string",
            "nullable": true,
            "description": "The `phoneNumber` you supplied in `inputs`, before any lookup. `null` when none was supplied."
          },
          "matchedPayerName": {
            "type": "string",
            "nullable": true,
            "description": "Canonical payer name SuperDial matched. `null` unless the matched payer's number was dialed. Compare against `inputPayerName` to confirm the match."
          },
          "matchedPayerPhone": {
            "type": "string",
            "nullable": true,
            "description": "Phone number of the matched payer. `null` unless it was the number dialed."
          },
          "phoneNumberToUse": {
            "type": "string",
            "nullable": true,
            "description": "The number that will actually be dialed. `null` when nothing is dialable."
          },
          "phoneNumberSource": {
            "type": "string",
            "nullable": true,
            "enum": ["superdial", "phoneBook", "input"],
            "description": "Origin of `phoneNumberToUse`: `superdial` is SuperDial's payer directory, `phoneBook` is a per-client override configured for your account, `input` is the number you supplied. `null` when nothing is dialable."
          }
        }
      },
      "CreateRequestSuccess": {
        "type": "object",
        "description": "Success response from `POST /v1/requests` on a single-item POST. `internalId` is echoed only when supplied in the body. `payerLookup` is present on every created request when payer phone number lookup is enabled for the account (its `matched*` fields are `null` unless SuperDial dialed its own matched number).",
        "required": ["requestId", "requestBatchId"],
        "properties": {
          "requestId": { "type": "string", "description": "Server-generated request ID. Stable across idempotent retries with the same `internalId`. Use it on `GET /v1/requests/{requestId}` to fetch the full result." },
          "requestBatchId": { "type": "string", "description": "Server-generated batch ID this request belongs to." },
          "internalId": { "type": "string", "nullable": true, "description": "**Optional.** Echoed back from the request body if you supplied one." },
          "payerLookup": { "$ref": "#/components/schemas/PayerLookup" }
        },
        "example": {
          "requestId": "8bF7xK2mP9qR4sT6uV0w",
          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
          "internalId": "claim_internal_456"
        }
      },
      "CreateRequestBatchResponse": {
        "type": "object",
        "description": "Response from `POST /v1/requests` on a batch POST. Each entry in `requests` is positionally aligned with the input and is either a `CreateRequestSuccess` payload or an `ApiError` envelope. In the batch context, schema-not-found surfaces per-entry as `INVALID_REQUEST` (with `\"Schema not found\"` in `message`); the `SCHEMA_NOT_FOUND` error code only appears on single-item 404s.",
        "required": ["requests"],
        "properties": {
          "requests": {
            "type": "array",
            "items": {
              "oneOf": [
                { "$ref": "#/components/schemas/CreateRequestSuccess" },
                { "$ref": "#/components/schemas/ApiError" }
              ]
            }
          }
        },
        "example": {
          "requests": [
            {
              "requestId": "8bF7xK2mP9qR4sT6uV0w",
              "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
              "internalId": "claim_001"
            },
            {
              "error": "INVALID_REQUEST",
              "message": "schemaId is required"
            }
          ]
        }
      },
      "RequestResponse": {
        "type": "object",
        "properties": {
          "requestId": { "type": "string" },
          "requestBatchId": { "type": "string" },
          "schemaId": { "type": "string" },
          "requestType": { "type": "string" },
          "state": { "type": "string", "enum": ["PROCESSING", "SUCCESS", "PARTIAL", "FAILURE"], "description": "Request lifecycle state (uppercase). See [State](/guides/concepts#state) for what each value means and which response fields are populated for it." },
          "inputs": { "type": "object", "description": "The request's inputs, echoed back exactly as submitted on `POST /v1/requests`, including any additional keys outside the schema's required and optional lists. Values are strings." },
          "results": { "type": "object", "description": "Structured request output fields. Empty `{}` on `PROCESSING` and `FAILURE`; partially populated on `PARTIAL`; fully populated on `SUCCESS`." },
          "missingFields": { "type": "array", "items": { "type": "string" }, "description": "Schema fields the request was unable to obtain. Populated on `PARTIAL` and `FAILURE` requests where extraction ran but came up short." },
          "dateCreated": { "type": "string", "format": "date-time", "nullable": true, "description": "Time the request was created, ISO-8601 with UTC offset (e.g. `\"2026-04-24T15:30:00.123456+00:00\"`)." },
          "completedAt": { "type": "string", "format": "date-time", "nullable": true, "description": "Time the request reached a terminal state (`SUCCESS`, `PARTIAL`, or `FAILURE`). `null` while the request is still `PROCESSING`." },
          "dueDate": { "type": "string", "format": "date-time", "nullable": true, "description": "Date this request is scheduled to run, as an ISO-8601 timestamp (e.g. `\"2026-05-08T03:00:00+00:00\"`). Set at submission time based on your account's daily call capacity and any work already pending. `null` when no due date is set." },
          "internalId": { "type": "string", "nullable": true, "description": "**Optional.** Echoed back from the request body if you supplied one at create time. The key is always present in this response (as `null` when not supplied), unlike on webhook payloads where the key is omitted entirely." },
          "internalTag": { "type": "string", "nullable": true, "description": "**Optional.** Echoed back from the request body if you supplied one at create time. The key is always present in this response (as `null` when not supplied), unlike on webhook payloads where the key is omitted entirely." },
          "modality": {
            "type": "string",
            "enum": ["digital_only", "phone_only", "digital_plus_phone"],
            "nullable": true,
            "description": "How the result was obtained. See [Modality](/guides/concepts#modality) for the value semantics. `phone_only` and `digital_plus_phone` both mean a phone call was placed (billable at the phone-call rate); `digital_only` means no phone call."
          },
          "data_completeness": {
            "type": "string",
            "enum": ["minimum"],
            "nullable": true,
            "description": "Completeness tier of a digital-only result. See [data_completeness](/guides/concepts#data_completeness) for current and reserved values."
          },
          "error": {
            "type": "object",
            "nullable": true,
            "description": "Structured error details. Populated on `FAILURE`; `null` on `PROCESSING`, `SUCCESS`, and `PARTIAL` (a `PARTIAL` request's primary call effort succeeded, so it has no single failure cause: use `missingFields`). See [error object](/guides/concepts#error-object) for the schema and the full `errorCode` taxonomy.",
            "properties": {
              "errorCategory": {
                "type": "string",
                "enum": ["NOT_FOUND", "SYSTEM_ERROR"],
                "description": "Two-bucket category. `NOT_FOUND` = the payer couldn't find what you asked about. `SYSTEM_ERROR` = any other failure (IVR navigation, payer refusal, unreachable, etc.)."
              },
              "errorCode": {
                "type": "string",
                "description": "Machine-readable failure code within the category. The taxonomy includes a small set of `SYSTEM_ERROR` codes (`IVR_FAILURE`, `PAYER_REFUSAL`, `UNABLE_TO_REACH_HUMAN_IN_TIME`, `REQUIRES_OTHER_CHANNEL`, `MATCHED_PHONE_NUMBER_INCORRECT`, `OTHER`), entity `NOT_FOUND` codes (`MEMBER_NOT_FOUND`, `CLAIM_NOT_FOUND`, `PRIOR_AUTH_NOT_FOUND`, `APPEAL_NOT_FOUND`), and two field-specific `NOT_FOUND` families: `{FIELD}_MISSING` (input not supplied) and `{FIELD}_INCORRECT` (input didn't match payer records). An incorrect dialing number is attributed by where the number came from: SuperDial-looked-up (`MATCHED_PHONE_NUMBER_INCORRECT`, `SYSTEM_ERROR`) vs. caller-supplied (`INPUT_PHONE_NUMBER_INCORRECT`) or representative-referred (`REPRESENTATIVE_PHONE_NUMBER_INCORRECT`), both `NOT_FOUND`. See [errorCode](/guides/concepts#errorcode) for the complete enumeration. Existing codes won't be renamed; new codes may be added over time. Default unknown values to `OTHER` in analytics."
              },
              "errorMessage": {
                "type": "string",
                "nullable": true,
                "description": "Human-readable sentence describing what went wrong. Wording may change between releases; use `errorCode` for programmatic dispatch."
              }
            }
          },
          "payerLookup": { "$ref": "#/components/schemas/PayerLookup", "description": "Payer/phone lookup for this request: the same six-field block returned on the `POST /v1/requests` create response. `phoneNumberToUse` is the number dialed; `phoneNumberSource` says where it came from. `matched*` fields are populated only when SuperDial dialed its own matched number." },
          "to": { "type": "string", "description": "The phone number that was dialed, echoed back in sanitized form. Present only once a representative phone call has completed (any terminal `state`), **and only when the number was one you supplied** (`payerLookup.phoneNumberSource` is `input`). When SuperDial dialed a number from its own payer directory (`superdial` or `phoneBook`), `to` is omitted; read the number from `payerLookup.phoneNumberToUse` instead, which is populated in every case and is also available before the call completes." },
          "transcript": { "type": "string", "description": "Full call transcript. Present only when a representative phone call has completed." },
          "recordingDownloadUrl": { "type": "string", "description": "Signed URL for the call recording. Present only when a phone call has completed and a recording exists. The URL is short-lived: it expires 7 days after it is issued, and sooner on accounts configured for a shorter window. Download the recording rather than storing the URL, and fetch the request again if you need a fresh one." },
          "callDuration": { "type": "string", "description": "Call duration in `HH:MM:SS` format. Present only when a phone call has completed and recording length data exists." },
          "callFromNumber": { "type": "string", "description": "**Optional.** Outbound caller number (E.164): the line the call originated from. Present only when a phone call has completed AND your account has outbound-number visibility enabled. Contact your account team to turn this on." },
          "callSummary": { "type": "string", "description": "AI-generated call summary. Present only when a representative phone call has completed." },
          "callAuditSummary": { "type": "string", "description": "AI-generated audit summary. Present only when a representative phone call has completed." },
          "resultSummary": { "type": "string", "nullable": true, "description": "Prose summary of `results` for a `SUCCESS` or `PARTIAL` request that finished without a phone call (the electronic-only path). A phone-backed request carries `callSummary` instead. Null otherwise. Not a per-account setting, but a request only finishes without a phone call when electronic channels are enabled for your account, so this stays null on phone-only accounts." },
          "attemptDetails": { "type": "array", "description": "**Optional.** One entry per dial attempt on the request's primary phone call. Does not span follow-up legs; see `contributingCalls` for those. Returned on the single-request read only, on a completed phone call, and only when your account has attempt details enabled. Contact your account team to turn this on.", "items": { "$ref": "#/components/schemas/AttemptDetail" } },
          "scriptVersion": { "type": "string", "description": "**Optional.** Script version used for the call. Present only when a phone call has completed AND your account has script-version visibility enabled." },
          "isRoboCall": { "type": "boolean", "description": "**Optional.** Whether the winning attempt was handled by the AI agent (`true`) or a human (`false`). Returned on the single-request read only, and only when your account has compliance fields enabled." },
          "callAttempts": { "type": "object", "description": "**Optional.** Attempt counts by type. Returned on the single-request read only, and only when your account has compliance fields enabled.", "properties": { "total": { "type": "integer" }, "robo": { "type": "integer" }, "human": { "type": "integer" } } },
          "audit": { "type": "object", "description": "**Optional.** Audit metadata. Returned on the single-request read only, and only when your account has compliance fields enabled.", "properties": { "isHumanAudited": { "type": "boolean" } } },
          "contributingCalls": {
            "type": "array",
            "nullable": true,
            "description": "The individual phone calls behind this request's `results`: one entry per call, in the order they were placed. This is the detailed counterpart to the `callSteps` summary: each entry carries that one call's transcript, recording, duration, summary, and captured fields, plus a `call` sequence number and a `callStep` tying it to the step it belongs to. A request usually completes in one call but can take more (see [Calls behind a request](/guides/reading-requests#calls-behind-a-request)). Present only on the single-request read (`GET /v1/requests/{requestId}`) of a `SUCCESS` or `PARTIAL` request fulfilled by at least one phone call, a single-call request included. Omitted when no phone call produced a value (e.g. a `digital_only` result), and not returned by the list endpoint.",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string", "description": "Opaque, stable identifier for the contributing call." },
                "call": { "type": "integer", "description": "Sequence number of this call within the request, starting at 1, in the order the calls were placed. `resultSources` points at this number to identify which call produced each field." },
                "callStep": { "type": "string", "description": "The `key` of the `callSteps` entry this call belongs to." },
                "to": { "type": "string", "nullable": true, "description": "The number this call dialed. Present only when the step dialed a different number than the original call; omitted otherwise, and omitted when the number came from payer phone number lookup (dialing stays server-side)." },
                "transcript": { "type": "string", "nullable": true, "description": "This call's transcript." },
                "recordingDownloadUrl": { "type": "string", "nullable": true, "description": "Signed URL for this call's recording, when one exists." },
                "callDuration": { "type": "string", "nullable": true, "description": "This call's duration in `HH:MM:SS` format." },
                "callSummary": { "type": "string", "nullable": true, "description": "AI-generated summary of this call." },
                "callAuditSummary": { "type": "string", "nullable": true, "description": "AI-generated audit summary of this call." },
                "fieldsCaptured": { "type": "array", "items": { "type": "string" }, "description": "Schema field names whose final value in `results` came from this call. A field this call captured but whose final value came from another call or an electronic source is not listed here." },
                "results": { "type": "object", "description": "What this call captured on its own: the same keys as the top-level `results`." },
                "completedAt": { "type": "string", "nullable": true, "description": "When this call completed." }
              }
            }
          },
          "callSteps": {
            "type": "array",
            "nullable": true,
            "description": "The steps SuperDial worked through to complete this request: a summary, one entry per step. Each step gathers one [schema](/guides/concepts#schema)'s fields and reports its own outcome. A request usually has a single step, but can have more, for example verifying benefits and then checking prior authorization on a separate call (see [Calls behind a request](/guides/reading-requests#calls-behind-a-request)). A single step can itself involve more than one call (a redial); `numContributingCalls` reports how many. This summarizes *what* was gathered; the captured values live in the top-level `results`, and the individual calls behind each step are in `contributingCalls` (tied back by `callStep`). Present on the single-request read (`GET /v1/requests/{requestId}`) of a completed phone request in any state: `SUCCESS`, `PARTIAL`, or `FAILURE`; the per-call `contributingCalls`/`resultSources` breakdown is added on `SUCCESS` and `PARTIAL`. Omitted for `digital_only` results, and not returned by the list endpoint.",
            "items": {
              "type": "object",
              "properties": {
                "key": { "type": "string", "description": "Stable, human-readable identifier for this step within the request (a slug of the schema name, suffixed `-2`/`-3` when the same schema runs in more than one step). Referenced by `resultSources` and by `contributingCalls[].callStep`." },
                "schemaId": { "type": "string", "nullable": true, "description": "The schema this step gathered. Two steps that ran the same schema share `schemaId` but have distinct `key`. `null` if the step has no schema." },
                "name": { "type": "string", "nullable": true, "description": "Display name of that schema." },
                "state": { "type": "string", "enum": ["PROCESSING", "SUCCESS", "PARTIAL", "FAILURE"], "description": "Outcome of this individual step. The request's overall state is the top-level `state`." },
                "fieldsRequired": { "type": "integer", "description": "How many fields this step's schema required." },
                "fieldsCaptured": { "type": "integer", "description": "How many of those required fields this step captured." },
                "missingFields": { "type": "array", "items": { "type": "string" }, "description": "Required fields this step did not capture." },
                "numContributingCalls": { "type": "integer", "description": "How many phone calls contributed a value to this step. When the per-call breakdown is present (a `SUCCESS` or `PARTIAL` request), these are the `contributingCalls` entries whose `callStep` is this step's `key`." },
                "triggeredBy": { "type": "string", "nullable": true, "description": "For a step that was opened off an earlier one, the `key` of that earlier step. `null` for the request's first step." }
              }
            }
          },
          "resultSources": {
            "type": "object",
            "nullable": true,
            "additionalProperties": { "type": "integer" },
            "description": "Maps each field in `results` to the `call` number (`contributingCalls[].call`) of the phone call that produced its final value. Useful when a request spanned more than one call and you want to know which call each answer came from. Fields with no phone-call source (e.g. `digital_only` values) are omitted. Present alongside `contributingCalls` on the single-request read."
          }
        },
        "example": {
          "requestId": "8bF7xK2mP9qR4sT6uV0w",
          "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
          "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
          "requestType": "claim-status",
          "state": "SUCCESS",
          "inputs": {
            "payerName": "Sample Insurance Co",
            "memberId": "TEST123456789",
            "providerNpi": "1234567890",
            "phoneNumber": "2125551234",
            "dateOfService": "2026-03-15"
          },
          "results": {
            "claimStatus": "PAID",
            "paidAmount": "150.00",
            "checkNumber": "CHK998877",
            "paidDate": "2026-04-10"
          },
          "missingFields": [],
          "dateCreated": "2026-04-24T15:30:00.123456+00:00",
          "completedAt": "2026-04-24T15:32:18.987654+00:00",
          "dueDate": "2026-04-25T23:00:00+00:00",
          "internalId": "claim_internal_456",
          "internalTag": "march-batch",
          "modality": "phone_only",
          "data_completeness": null,
          "error": null,
          "payerLookup": {
            "inputPayerName": "Sample Insurance Co",
            "inputPhoneNumber": "2125551234",
            "matchedPayerName": null,
            "matchedPayerPhone": null,
            "phoneNumberToUse": "2125551234",
            "phoneNumberSource": "input"
          },
          "to": "+12125551234",
          "transcript": "SuperDial Agent: Hi, I'm calling to check on a claim status.\nRepresentative: Sure, can I get the claim number?...",
          "recordingDownloadUrl": "https://storage.googleapis.com/sd-recordings/.../recording.mp3?X-Goog-Signature=...",
          "callDuration": "00:08:42",
          "callSummary": "Verified claim status as PAID. Check #CHK998877 issued on 2026-04-10 for $150.00.",
          "callAuditSummary": "All claim status questions answered. Representative confirmed paid amount and check number.",
          "callSteps": [
            {
              "key": "claim-status",
              "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
              "name": "Claim Status",
              "state": "SUCCESS",
              "fieldsRequired": 4,
              "fieldsCaptured": 4,
              "missingFields": [],
              "numContributingCalls": 1,
              "triggeredBy": null
            }
          ],
          "contributingCalls": [
            {
              "id": "9nQ4vT7xB2mK5pR8sL0w",
              "call": 1,
              "callStep": "claim-status",
              "fieldsCaptured": ["claimStatus", "paidAmount", "checkNumber", "paidDate"],
              "results": {
                "claimStatus": "PAID",
                "paidAmount": "150.00",
                "checkNumber": "CHK998877",
                "paidDate": "2026-04-10"
              },
              "completedAt": "2026-04-24T15:32:18.987654+00:00"
            }
          ],
          "resultSources": {
            "claimStatus": 1,
            "paidAmount": 1,
            "checkNumber": 1,
            "paidDate": 1
          }
        }
      }
    }
  }
}
