Skip to main content
POST /v1/requests creates one or more requests and returns their IDs. The body shape varies based on whether you’re submitting a single item or a batch.

Authentication

Protected routes require a bearer token — including POST /v1/requests and the other /v1/requests* endpoints. Get one with GET /v1/auth (passing your API key and secret as the Robodialer-API-Key and Robodialer-API-Secret headers). Pass the returned token as Authorization: Bearer <token> on every subsequent HTTP request. Tokens are valid for 1 hour. Refresh by calling GET /v1/auth again — there’s no refresh-token flow. For long-running batches or background workers, fetch a fresh token at the start of each work cycle, or refresh on 401 responses.
import requests

def fetch_token(api_key: str, api_secret: str) -> str:
    r = requests.get(
        "https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/auth",
        headers={
            "Robodialer-API-Key": api_key,
            "Robodialer-API-Secret": api_secret,
        },
    )
    r.raise_for_status()
    return r.json()["token"]

Single request

Submit a single request by sending a JSON body with the request’s fields directly:
curl -X POST https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/requests \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "schemaId": "fWxzG4nqtpHsJxS5Lm3q",
    "inputs": {
      "payerName": "Sample Insurance Co",
      "memberId": "TEST123456789",
      "phoneNumber": "2125551234",
      "providerNpi": "1234567890",
      "dateOfService": "2026-03-15"
    },
    "internalId": "claim_internal_456"
  }'

Response

{
  "requestId": "8bF7xK2mP9qR4sT6uV0w",
  "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
  "internalId": "claim_internal_456"
}
If your account is enabled for payer-phone resolution (opt-in — ask your account team) and your inputs supplied payerName without phoneNumber, the POST takes about 15 seconds to respond — set your HTTP-client timeout accordingly. The response then carries a payerLookup sub-object:
{
  "requestId": "8bF7xK2mP9qR4sT6uV0w",
  "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
  "internalId": "claim_internal_456",
  "payerLookup": {
    "inputPayerName": "Sample Insurance Co",
    "matchedPayerName": "Sample Insurance Company, Inc."
  }
}
inputPayerName echoes what you sent. matchedPayerName is the canonical name SuperDial matched — compare them if you want to confirm the right payer was picked. The resolved phone number is not returned: dialing happens server-side and the number is never echoed back. When you supply phoneNumber yourself, lookup is skipped and payerLookup is omitted from the response. The same payerLookup block is also returned on reads for read-after-write consistency. See the Payer Resolution guide for more. The request begins running immediately. Configure a webhook to be notified when it reaches a terminal state, then call GET /v1/requests/{requestId} to fetch the full result.

Batch

Submit multiple requests in one call by wrapping them in { "requests": [...] }. The response returns one entry per submitted request, in the same order. Each entry carries its own requestBatchId, and those IDs may or may not match across the batch. Within a single submission, entries scheduled for the same business day share a requestBatchId; entries scheduled for different days get distinct ones. Whether your batch lands on a single day or spills across multiple days depends on your account’s daily call capacity and any work already pending from prior submissions on those days. Always read each entry’s requestBatchId from the response — don’t assume they match.
curl -X POST https://robodialer-service-api-9nc4t1p9.uc.gateway.dev/v1/requests \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "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"
      }
    ]
  }'

Batch response

A batch responds with one entry per request, in the same order as the input. Each entry is either a success body or the uniform {error, message, [details]} envelope:
{
  "requests": [
    {
      "requestId": "8bF7xK2mP9qR4sT6uV0w",
      "requestBatchId": "pH9kJ2lM4nB6vC8xZ7Qr",
      "internalId": "claim_001"
    },
    {
      "error": "INVALID_REQUEST",
      "message": "schemaId is required"
    }
  ]
}
The HTTP status code reflects the aggregate outcome:
Status codeMeaning
200All entries in the batch were created successfully.
207Mixed — at least one entry succeeded and at least one failed with a client-side (4xx) error. Inspect each entry.
400Either the top-level request body was invalid (e.g., requests was empty), OR every entry in the batch failed with a client-side error.
500An internal failure occurred during batch processing. Body is either the top-level {error: "INTERNAL_ERROR", message: "..."} envelope (the common case) or {"requests": [...]} with per-entry envelopes — check for the requests key to tell them apart, and treat each entry independently.
Batches don’t have to be all-or-nothing. We recommend treating each entry independently — successful entries are real, persisted requests, even if other entries in the same batch failed.
To list every request under a given requestBatchId later — for example to track progress on one day’s slice of a large batch — use GET /v1/requests?requestBatchId=.... For a multi-day batch, iterate over the unique IDs returned in the create response.

Required fields

Every request body must include:
FieldDescription
schemaIdThe schema that defines the output fields. Discover yours via GET /v1/schemas.
inputsA JSON object of { key: value } pairs. All values must be strings. The keys are schema-specific — discover required and optional ones via GET /v1/schemas/{schemaId}/required-inputs. Typical examples include payerName, memberId, phoneNumber, providerNpi, dateOfService.
requestType is server-derived from the schema — you’ll see the canonical value on the RequestResponse returned by GET /v1/requests/{requestId}. You can still send a requestType field on the POST body if existing client code does; it’s silently ignored. Required inputs.{key} fields are validated when the request is created — if any are missing or fail format checks, the request is rejected with HTTP 400 and the uniform INVALID_INPUTS error envelope:
{
  "error": "INVALID_INPUTS",
  "message": "Required inputs are missing or invalid.",
  "details": {
    "missingInputs": ["memberId", "providerNpi"],
    "invalidInputs": { "dateOfService": "must be YYYY-MM-DD" }
  }
}
details is only present on this INVALID_INPUTS path; other 400 errors carry just error + message. Discover the required inputs per schema with GET /v1/schemas/{schemaId}/required-inputs, or ask your account team. See the API Reference for POST /v1/requests for the full request body schema.
If your account is enabled for per-payer required inputs (opt-in — ask your account team), some payers require additional inputs beyond the schema’s fields, depending on payerName. A missing one is reported here in details.missingInputs like any other — add it and retry.

Optional fields

FieldDescription
webhookUrlPer-request webhook URL override. Wins over the account default for this one request.
internalIdOptional correlation ID, and also the request’s idempotency key. Echoed on all reads and webhooks. If you supply one it must be unique per request — see below. If you omit it, SuperDial generates one for you.
internalTagOpaque tag echoed on reads and webhooks (e.g. "march-batch").
aiOnlyBoolean. When true, any phone call this request makes is handled only by our automated voice agent, never a human agent. Leaving it false adds no restriction — it doesn’t force human-agent handling. Defaults to false.
onshoreOnlyBoolean. When true, all phone handling for this request is restricted to US-based agents. Leaving it false adds no restriction. Defaults to false.

Correlation and idempotency

internalId is optional and serves two purposes:
  1. Correlation — when you supply one, it’s echoed back on every read and every webhook for that request, so you can tie SuperDial results to your own records.
  2. IdempotencyinternalId is the idempotency key. A POST /v1/requests that reuses an internalId you’ve sent before does not create a new request; it returns the originally created requestId (and the original payerLookup, if any).
Because internalId is the idempotency key, a new internalId must be different on every distinct request you want to place. Reusing one is not an error and produces no warning — it silently returns the original request instead of starting new work. Use a value that’s naturally unique per request (a UUID, or your own primary key), not a constant or a reused batch label.
You don’t have to send one. internalId is optional. If you omit it, SuperDial generates and maintains its own unique idempotency key server-side, so retries are still de-duplicated for you. Supply your own only when you want to correlate results back to records on your end; otherwise leave it off and let SuperDial manage it.
// First call
POST /v1/requests  { "internalId": "claim_001", ... }
200  { "requestId": "8bF7xK2mP9qR4sT6uV0w", ... }

// Retry with the SAME internalId — no new request is created
POST /v1/requests  { "internalId": "claim_001", ... }
200  { "requestId": "8bF7xK2mP9qR4sT6uV0w", ... }   // same ID, no duplicate

// Omit internalId entirely — SuperDial generates its own key
POST /v1/requests  { ... }            // no internalId
200  { "requestId": "aC3hN5jD8eL1fM2gK6Yo", ... }   // new request every call
internalId-based idempotency applies on a per-request basis. In batch submissions, each entry with an internalId is independently deduped: a duplicate entry returns the previously created requestId and requestBatchId rather than creating a new request. There is no batch-level idempotency key — only per-entry.

What happens after creation

The request immediately begins running through one or more modalities (electronic systems and/or phone calls). Completion time varies — electronic-only requests can finish quickly; phone-backed requests depend on payer responsiveness and hold times. Configure a webhook to be notified the moment a request finishes, then call GET /v1/requests/{requestId} to fetch the full result.

Error handling

Every non-2xx response from /v1/requests returns the same envelope:
{
  "error": "MACHINE_CODE",
  "message": "Human-readable description.",
  "details": { /* optional, only on INVALID_INPUTS */ }
}
Switch on error for programmatic dispatch; surface message to humans.
HTTP codeerror codeMeaningWhat to do
400INVALID_REQUESTBody wasn’t a JSON object, a required field is missing (schemaId, inputs), the batch requests array is empty, or scheduling capacity is exceeded. The validator’s specific reason is in message.Fix the body and retry
400INVALID_INPUTSInput validation failed. details.missingInputs lists field names that weren’t supplied; details.invalidInputs maps field name to the reason it was rejected. With per-payer required inputs enabled, some payers add inputs that can appear here too.Fix the inputs and retry
400PAYER_NOT_FOUNDPayer-phone resolution path: the supplied payerName did not match any known payer. Only fires when resolution is enabled for your account, payerName is set, and phoneNumber is not.Confirm spelling, try a more canonical payer name, or supply phoneNumber directly to skip resolution
401(gateway envelope)Bearer token missing, malformed, or expired. Returns the gateway’s {code, message} shape, not the envelope above.Fetch a fresh token via GET /v1/auth
404SCHEMA_NOT_FOUNDschemaId doesn’t exist for your account, or has been retired. On a batch, schema-not-found surfaces per-entry as INVALID_REQUEST with "Schema not found" in message — read message to distinguish 4xx causes when an entry has no status code.Discover valid schemaId values with GET /v1/schemas
404ACCOUNT_NOT_FOUNDThe API key resolves to an account that no longer exists. Rare — wrong-API-key cases hit INVALID_API_KEY at /v1/auth first.Contact support
500INTERNAL_ERRORUnexpected server failure. Single-item POST: body is the envelope above. Batch: body can take either shape — the top-level INTERNAL_ERROR envelope (most common) or {"requests": [...]} with per-entry envelopes (server-error entries surface here as INVALID_REQUEST rather than INTERNAL_ERROR). Check for the requests key to tell the two shapes apart.Retry once; escalate if persistent
500PAYER_LOOKUP_FAILUREPayer-phone resolution path: the supplied payerName matched a payer but our database has no phone number on file, or the resolver hit a transient infra failure. Only fires when resolution is enabled for your account.Retry with backoff, or supply phoneNumber directly to skip resolution
For batch submissions, each failed entry inside the requests array carries the same envelope shape as a top-level error — so you can use the same error handler everywhere.