Make and troubleshoot an HTTP API request
Use this journey to connect your backend to Delphi's HTTP API and verify a read-only request before adding session or usage operations. The API origin is the deployment's TelAPI address, which can differ from TelWeb and the documentation address. Ask the deployment operator for that origin.
Availability: The operator must enable the API routes with FEATURE_API_ACCESS; the team needs the appropriate API entitlement and allowed scopes. A team administrator supplies a key with the operation's scope. A product login, documentation login and team API key are separate credentials. Use Manage team API keys for creation, storage, rotation and revocation.
The linked HTTP reference is explicitly a 0.9.17-patch1 schema snapshot. This guide's endpoint, pagination and error handling are checked against the selected product version. Do not relabel the snapshot as the selected release or infer that every newer operation appears in it.
1. Select the operation and credential
For the first check, use GET /api/v1/endpoints with a key containing READ_TEAM_APPS. This operation lists browser endpoints in the key's team, not all applications, telephone endpoints or another team's resources. You do not supply a team identifier to broaden the result.
Send the long-lived key in the X-API-Key header from your backend. Do not put it in browser code or a URL. A bearer/session token is not interchangeable with this key. If the next task is browser voice or chat, continue with the browser integration journey for scoped session credentials and readiness; listing an endpoint does not create or start a session.
2. Send a bounded read-only request
This Node.js backend example reads configuration from your server environment, applies a ten-second client timeout and logs only a count and pagination metadata. Set DELPHI_API_ORIGIN to the operator-supplied HTTPS origin and keep DELPHI_API_KEY in your secret storage. The timeout is this client's choice, not a server timeout guarantee.
const origin = process.env.DELPHI_API_ORIGIN;
const key = process.env.DELPHI_API_KEY;
if (!origin || !key) throw new Error('Configure the API origin and team API key');
const url = new URL('/api/v1/endpoints?page=1&limit=20', origin);
const response = await fetch(url, {
headers: {'X-API-Key': key},
signal: AbortSignal.timeout(10_000),
});
const contentType = response.headers.get('content-type') || '';
const body = contentType.includes('application/json') ? await response.json() : null;
if (!response.ok) {
// Keep full response bodies and credentials out of routine logs.
const code = body?.error?.code || 'HTTP_ERROR';
const requestId = body?.error?.requestId || 'unavailable';
throw new Error(
`Endpoint request failed: HTTP ${response.status}; ${code}; request ${requestId}`,
);
}
if (!Array.isArray(body?.endpoints) || !body?.pagination) {
throw new Error('Unexpected endpoint response; check the API origin and deployed contract');
}
console.log({endpointCount: body.endpoints.length, pagination: body.pagination});
A 200 response contains endpoints and pagination. Each endpoint has an id and name; the name comes from its application and is not a unique identifier. Use the endpoint ID when another operation requires it. An empty array can be a valid result for a team without browser endpoints. Confirm the selected team and application entry points before replacing the key.
A proxy or another server can return HTML or a different error body. Check the HTTP status and content type before assuming every response uses the TelAPI JSON envelope. A successful login page is not a successful API response.
3. Read further pages deliberately
page is one-based and defaults to 1; limit defaults to 20 and must be between 1 and 100. Use positive integer query values. Invalid values, including zero or an excessive limit, are rejected rather than silently clamped.
The response's pagination contains total, page, limit and totalPages. When the total is zero, totalPages is zero. Continue only while the returned page is below totalPages; a page beyond the available results can return an empty array.
This is offset pagination, not a stable snapshot or cursor. The query does not declare a stable ordering, and the count and page reads are separate. If endpoints change while you read, do not assume a complete, duplicate-free export. For application selection, prefer storing the chosen endpoint ID and reconciling it when configuration changes rather than continually rebuilding identity from display names.
4. Interpret errors before retrying
TelAPI's shared error handler returns an error object with code and message, and can include details and requestId. Details depend on the operation and error; do not require a fixed structure or display raw details to an end user. A request identifier helps an operator correlate logs; it is not a call ID or session credential.
| HTTP result | Meaning and next action |
|---|---|
400 / VALIDATION_ERROR | Correct the query or body according to the operation. Retrying the same invalid input does not help. |
401 / AUTHENTICATION_ERROR | Check missing, inactive, expired or invalid key, team state and entitlement. The team daily request allowance can also be rejected through authentication, so read the safe message before assuming the secret is wrong. |
403 / AUTHORIZATION_ERROR | Check required scope and operation-specific authority. Repeated requests cannot add permission. |
404 / NOT_FOUND | A shared-handler resource error can use NOT_FOUND. Check origin, path, route availability and resource identifier; routing and proxy 404 responses can have a different body. |
409 / CONFLICT | Where the operation uses this error, reconcile its current state before attempting a conflicting change again. |
429 / RATE_LIMIT_EXCEEDED | Stop immediate retries. Honor Retry-After when supplied and inspect whether the cause is request rate or repeated credential failures. |
500 / INTERNAL_ERROR, network error or client timeout | Capture safe context and investigate. A failed response does not establish whether a state-changing operation took effect. |
503 / WEBRTC_DISABLED or TELPRO_UNCONFIGURED | A browser-voice operation can reject unavailable voice capability or gateway configuration. Ask the operator to correct availability; retrying cannot enable it. Other 503 responses can have different causes. |
An IP-tier rate-limit response can include limiter-specific details, for example:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"details": {"max": 600, "after": "1 minute", "ttlMs": 42000},
"requestId": "example-request"
}
}
The shared builder forwards the limiter's max and after values and includes ttlMs when a TTL was supplied. This is an illustrative shape, not your deployment's configured limit. Other errors or limiters need not provide these fields; use Retry-After when present and investigate the actual limit rather than parsing the human-readable message.
Per-IP request controls, the team's daily allowance and the credential-retry jail are separate limits. A credential jail can temporarily reject a valid replacement key from the same client IP; changing keys repeatedly is not a recovery strategy. Follow API rate-limit operations when multiple clients share an egress address or failures persist.
For an idempotent read, bounded retries with delay can be appropriate after a transient failure. Set your own retry cap and stop on validation, authentication or authorization failures. Do not automatically replay a session-creation or other state-changing request after a timeout. Check that operation's state and contract first; this guide does not promise a universal idempotency key or exactly-once execution.
Read team TTS usage
Use GET /api/v1/usage/tts-characters with a backend API key containing READ_TEAM_USAGE to retrieve the calling team's recorded TTS character totals. The team comes from the key; a query parameter cannot select another team. Applications excluded from the dashboard are excluded from this aggregate too. These are character counts, not a currency invoice or proof that every provider has reported final usage.
| Query field | Meaning |
|---|---|
from | Optional ISO 8601 date-time, inclusive start of the usage-event window. Defaults to the Unix epoch. |
to | Optional ISO 8601 date-time, inclusive end of the window. Defaults to the request's current time. |
timeframe | day, week, month or total; defaults to total. This is an echoed label and does not select or shorten the time window. |
For a monthly report, send explicit from and to values; timeframe=month alone still uses the default all-time window. Either bound can be supplied alone. Invalid dates or labels and a start later than the end return validation errors. Both bounds are inclusive: avoid counting events on a shared boundary twice when combining adjacent windows.
GET /api/v1/usage/tts-characters?from=2026-06-01T00%3A00%3A00.000Z&to=2026-06-30T23%3A59%3A59.999Z&timeframe=month
X-API-Key: <server-side-team-key>
| Response field | Meaning |
|---|---|
teamId | Team associated with the calling key. |
timeframe | Effective label, independent of the date bounds. |
from, to | Resolved report bounds as ISO date-times. |
charactersTotal | Recorded total TTS characters in the window. |
charactersFromCache | Recorded characters served from the TTS cache. |
charactersGenerated | Recorded characters generated by an upstream provider. |
cacheHitRatio | Cached characters divided by total characters, rounded to four decimal places; zero when the total is zero. |
An empty result returns zero totals. If figures differ from an expected dashboard view, check the team, explicit date window, application exclusions and when usage was recorded before changing credentials. Use API key administration to grant reporting scope and dashboard reporting to interpret the UI view.
5. Verify the intended integration, then hand over
A successful endpoint list proves that this key, team, route and request worked at that time. It does not prove a browser session can start, a provider is configured, a SIP call can connect or a later write is permitted.
- For browser sessions, use session readiness, events and recovery.
- For key lifecycle and scope changes, return to API key administration.
- For missing endpoints, verify the app's channel and binding.
- For persistent failures, give the operator the deployment, operation, HTTP status/code, approximate time and safe request identifier. Do not include a key, authorization header, full response payload or customer conversation content. Use logs and traces to correlate the request without assuming its request ID is a call's correlation identifier.