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.

Single request

Submit a single request by sending a JSON body with the request’s fields directly:

Response

If your account is enabled for payer phone number lookup (opt-in: ask your account team), the response carries a payerLookup sub-object describing the payer/phone lookup for the request.
payerLookup is always present on the response and reports the number that will be dialed (phoneNumberToUse) and where it came from (phoneNumberSource: superdial, phoneBook, or input). The matched* fields are populated only when SuperDial dials its own matched number; if your supplied phoneNumber is dialed, they’re null and phoneNumberSource is "input". By default a supplied phoneNumber always wins: set useMatchedPayerPhone: true to dial the matched number instead. The same block is returned on reads. See the Payer Phone Number Lookup guide for the full field reference. 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.

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:
The HTTP status code reflects the aggregate outcome:
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: 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:
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.

Multi-value inputs

Send a field that holds several values as one comma-delimited string, not a JSON array. Every value in inputs must be a string, and the type check runs before anything else, so an array is rejected on arrival.
Nothing validates the separator: the string is handed to the voice agent as you sent it, and a comma-delimited list reads naturally on the call. A space after each comma is fine. The same rule covers any field you use this way, cptCodes and icd10Codes being the common ones.
Moving from the legacy Calls API? This is the difference most likely to catch you. POST /v1/calls accepts an array for a field like cptCodes; POST /v1/requests does not. A mapping that has worked for months against /v1/calls will fail on every request here, and because a 400 creates nothing, no request appears in the portal to tell you so. See Migrating from the Calls API.

Optional fields

Extra inputs

The keys of inputs aren’t limited to the ones your schema declares. Any additional key you send is accepted, stored with the request, echoed back on every read and webhook, and given to the voice agent as context on any phone call the request makes. Nothing rejects a key just because GET /v1/schemas/{schemaId}/required-inputs didn’t list it. Use this for context that helps the call but that the schema never asked to collect: why the claim was denied last time, a deadline the representative should hear about, which department has already turned you away.

Rules that still apply

An extra key is not a way around validation. The same checks run on it as on a schema field: An extra key is never reported in details.missingInputs, because nothing requires it. Leave it out on some requests and send it on others, as you like.

What extra inputs don’t do

Extra inputs are context, not instructions. They don’t add questions to the call: the agent won’t ask a payer about a key you invented, and the key won’t come back in the request’s results. What gets asked, and what gets returned, are both fixed by the schema. If you need the agent to ask something new, the schema itself has to change. Talk to your account team.
Two rules change what the agent actually sees. A key whose name contains internal (case-insensitive) is withheld from the agent entirely, so an internalNote is stored and echoed back but never reaches the call; for data you only want correlated, use the top-level internalId and internalTag instead. And values are reformatted so they can be spoken aloud: keys whose name contains name, date, or address get title-casing, underscores as spaces, or a long-form spoken date, and any value of more than two words is title-cased whatever its key is called. The priorDenialReason above reaches the agent as Co-197 No Authorization On File. Keep an extra value short if its capitalization matters, and don’t name an extra key ...Name unless it holds a person’s or organization’s name.
Send what helps the call, not your whole record. Every extra key is put in front of the agent on every turn of the conversation, so a long tail of irrelevant identifiers gives it more chances to offer a representative something beside the point. Two or three well-chosen fields beat twenty.

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. Idempotency: internalId 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.
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:
Switch on error for programmatic dispatch; surface message to humans. 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.