DoDomain

OpenAPI spec

The machine-readable OpenAPI 3.1 description of the /api/v1 surface — generated from the same schemas the API validates with.

The whole /api/v1 surface is published as an OpenAPI 3.1 document:

https://dodomain.io/docs/openapi.json

It describes every endpoint on the REST API page — request and response bodies, query parameters, both authentication schemes and their OAuth scopes, and the exact error codes each endpoint can answer with, including the 429 Retry-After contract.

It is generated, not written

The document is produced from the same zod schemas the request handlers validate with. A CI gate regenerates it on every pull request and fails the build if it differs by a single byte from the committed file, and a second gate fails if any endpoint exists in the code without an entry in the spec. So the spec cannot quietly fall behind the API: either it is current, or the build is red.

Two consequences worth knowing:

  • Response objects do not set additionalProperties: false. We add response fields additively — records and warnings on the create-session response both arrived that way — so a client that rejected unknown keys would break on a release that broke nothing else. Ignore fields you do not recognise.
  • The version is v1, not a semver. The surface is versioned by its /api/v1 path prefix.

Using it

curl -sSL https://dodomain.io/docs/openapi.json -o dodomain-openapi.json

Point any OpenAPI-aware tool at that file or URL — an API client (Postman, Insomnia, Bruno, Hoppscotch), a client generator (openapi-generator, openapi-typescript, Kiota, Speakeasy), a mock server, or a contract-test runner.

AI assistants can call the API directly

If you want an assistant to use DoDomain rather than write code against it, connect the MCP server instead — see Connecting AI assistants. It runs on the same authentication, scopes and rate limits described here.

Authentication in the spec

Two security schemes are declared, and integrator endpoints accept either:

SchemeHow it appearsNotes
secretKeyAuthorization: Bearer dd_sk_...App-scoped, no scope grammar, server-to-server only.
oauth2Authorization-code flow with PKCETeam-scoped. Each operation lists the scope it needs; a missing scope answers 403 with details.code: SCOPE_MISSING.

Session-scoped endpoints (/api/v1/sessions/{token}/detect, /verify, and the one-click entry points) carry security: [] — that is not an oversight. The unguessable session token in the path is the credential, which is what lets the hosted flow and the embeddable widget call them from a browser. Treat that token like a bearer token.

Two classes deviate from "either credential", and the spec says so per operation rather than in prose:

  • Credential-management operations take the secret key only. POST /api/v1/keys/rotate and every /api/v1/webhook-endpoints operation declare secretKey as their sole security requirement. An OAuth access token is refused with 403 and details.code: SECRET_KEY_REQUIRED — signing secrets and key rotation stay with the app's own credential rather than with a delegated consent grant.
  • GET /api/v1/sessions/{token} accepts either, or neither. It is one path with two arms, told apart by the shape of the path segment: pass a dd_sess_... token and send no Authorization header, or pass the session id and authenticate. The spec encodes that as an optional security requirement (a leading {} alongside the two credential entries) and the 200 as a oneOf over the two response shapes, because the two arms genuinely return different objects.

On this page