> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superdial.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a Request

> 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.



## OpenAPI

````yaml /openapi.json post /v1/requests
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
security: []
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 and the required input
      keys for each. All non-2xx responses use the uniform `{error, message,
      [details]}` envelope (see the `ApiError` schema).
paths:
  /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.
      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
                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
      security:
        - bearerAuth: []
components:
  schemas:
    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. The required and optional keys are schema-specific; discover
            them with `GET /v1/schemas/{schemaId}/required-inputs`. 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
    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
    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
    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
    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.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Bearer token obtained from the /v1/auth endpoint

````