Postman collection
A ready-to-import Postman collection covering the /v1 control-plane surface — 27 folders, 163 requests — plus an environment with the two variables you have to fill in.
- Download the collection (
dialer-core.postman_collection.json) - Download the environment (
dialer-public.postman_environment.json)
Import and run
- In Postman, Import → drop both files in.
- Select the Dialer Digital — public environment in the top-right picker.
- Set these two variables:
| Variable | What it is |
|---|---|
baseUrl | The ingress in front of core. Shipped as https://api.usa.dialerdigital.com, the deployment server declared in the OpenAPI spec — point it at your own cell if yours differs. |
api_token | Ships empty on purpose. Paste your own key; see below. |
The collection authenticates at the collection level with Bearer , so every request inherits it — there is no per-request auth to configure.
Which token goes in api_token
/v1 keys are tenant-scoped and live on the dd_ rail: mint one with POST /v1/api_keys and copy the plaintext, which is shown once and never again. The full rules — the three rails (dd_, ddu_, ddw_), what each one may reach, and how the tenant is resolved from the key — are in Authentication.
Two rails you may see elsewhere in the docs do not belong in this variable: ddu_ (dashboard user sessions) and ddw_ (widget). The collection exercises the tenant API.
The published environment carries no credential
api_token is empty in the file you download, and that is not an oversight — a token shipped in a public artifact is a token someone keeps. Fill it in locally; Postman stores it in your own environment, not in the file.
Where this comes from, and what keeps it honest
The collection is vendored, not authored here. Its source of truth is postman/dialer-core.postman_collection.json in DialerDigital/integration-tests, where it doubles as the harness that exercises a live stack. public/postman/SOURCE.json records the exact integration-tests commit each published copy came from.
Four things change on the way out, and the script fails rather than publish if any of them stops matching — the check is on the output, not on whether the rewrite fired:
baseUrlmoves from the local harness (http://127.0.0.1:4000) to the deployment placeholder;- the collection description stops naming the demo token that the local harness seeds;
- the SMS-provider registration example points at a name reserved for documentation instead of the harness's mock, and ships an empty
webhook_secret. Both belonged to the harness — a pointer at a local mock, and the secret the harness seeds — and neither belongs in a public download. The API would refuse that loopback anyway:base_urlis tenant input the control plane later signs requests to, so it is checked against an SSRF guard (see the field description in the vendoredopenapi/dialer-v1.yaml). Stripping it here is about what we publish, not about what the API accepts; - the harness-only mail-sink request is dropped, along with the variable that fed it. It read a mailbox served by the local stack, so there was never anything for it to reach from outside. The two
password-reset/confirmrequests therefore expect you to paste intoreset_tokenthe token from the mail you actually received.
Refresh it with a sibling checkout of integration-tests:
npm run docs:sync-postman # rewrite the published copy
node scripts/sync-postman.mjs --check # report drift without rewriting--check warns by default and fails hard with POSTMAN_SYNC_STRICT=1. The sanitiser itself fails closed: if its rewrite ever stops matching the source, it aborts instead of publishing, so a sanitiser that quietly stopped sanitising cannot ship.
--check also takes --anchor=pinned|moving, which says what the sibling checkout is pointing at and therefore what is comparable. It defaults to moving — the right answer for the command above, where your integration-tests checkout is wherever you left it. CI passes it explicitly, resolved from the event: on pull_request/push the checkout sits at the commit public/postman/SOURCE.json declares, so --anchor=pinned additionally checks that the checkout really is at that commit and compares SOURCE.json in full; on schedule the checkout sits at the source repo's default branch, where commit moves with every unrelated commit, so --anchor=moving leaves that one field out.
On schedule there is one more input, and it is what keeps the nightly from crying wolf. The same run also has the contract-refresh job, which opens (or updates) a pull request with the refreshed copy whenever the source has moved — so a drift the freshness step sees is very often a drift whose fix is already open, waiting for review. The two jobs have no ordering between them, so the step first waits for contract-refresh to finish, then takes --refresh-prs=<json>: the list of this repo's open pull requests with the commit each one declares in its own public/postman/SOURCE.json. If one of them declares exactly the commit the check is comparing against, the drift is known — the step prints a ::notice:: naming that pull request, writes what it considered and why to the job summary, and stays green. With no such pull request the step is red exactly as before: that red belongs to somebody, either a sync job that did not run or a source commit nobody has brought over yet. The match is deliberately narrow — an open pull request and the exact commit; one that is closed, or that vendors an older commit, silences nothing, and a list the step cannot read does not either. The flag is refused with --anchor=pinned: on pull_request/push a drift is an integrity failure and no open pull request excuses it.
Alignment with the /v1 contract
The requests track core's OpenAPI spec — the same one this site renders as the API Reference and vendors under openapi/dialer-v1.yaml — the vendored version is the spec_version that openapi/SOURCE.json records, next to the core tag and commit it was copied from by scripts/sync-openapi.mjs. In integration-tests, a drift gate (.ci/qa/check_openapi_postman_drift.py) keeps the collection and the spec from separating.
One difference worth knowing before you go looking for it: the collection includes GET /healthz, the unauthenticated liveness probe, and the spec does not describe it — the spec covers /v1 only. It is a real endpoint; it just has no schema to check it against.
See also
- REST API — the hand-written narrative of the surface
- API Reference — generated from the spec at every build
- Authentication — the rails, in full