---
title: "Create a connect session"
method: POST
path: "/api/v1/sessions"
tags: ["Sessions"]
---

# Create a connect session

`POST /api/v1/sessions`

## Request

- Base URL: `https://app.dodomain.io`
- URL: `https://app.dodomain.io/api/v1/sessions`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.dodomain.io/api/auth/oauth2/authorize`, token URL `https://app.dodomain.io/api/auth/oauth2/token`, scopes: `sessions:write`)

Mints a short-lived (24h) session for one domain and the DNS records the end user must create, and returns the hosted `connectUrl` plus the fully-qualified names verification will look up. Hosts are composed relative to the session's `domain` — read `records[].fqdn` in the response to confirm what will actually be checked. An OAuth caller is team-scoped and must send `appId`; a secret-key caller's app is implicit in the key and a mismatching `appId` is rejected.

## Headers

- `DoDomain-Team` string

## Request body

- CreateSessionInput
  - `appId` string
  - `domain` string, required
  - `recipe` string
  - `records` object[], required
    - `host` string, required
    - `priority` integer
    - `ttl` integer
    - `type` 'A' | 'AAAA' | 'CNAME' | 'TXT' | 'MX', required
    - `value` string, required
  - `returnUrl` string, uri

## Response `200`

Success.

- CreateSessionResponse
  - `connectUrl` string, required
  - `expiresAt` string, date-time, required
  - `id` string, required
  - `records` object[], required
    - `fqdn` string, required
    - `host` string, required
    - `type` 'A' | 'AAAA' | 'CNAME' | 'TXT' | 'MX', required
  - `token` string, required
  - `warnings` object[]
    - `code` 'duplicate_host_label', required
    - `fqdn` string, required
    - `host` string, required
    - `message` string, required

## Other responses

- `400`: `400 invalid_request` — The request body or query failed schema validation, or a documented capability rule rejected it. `details` carries the field-level report when the failure came from schema validation.
- `401`: `401 unauthorized` — No `Authorization: Bearer` header, or the credential is malformed, unknown, or (for OAuth tokens) fails verification.
- `402`: `402 quota_exceeded` — The team's monthly verified-connection allowance is exhausted (enforced at session creation on the Free plan).
- `403`: `403 forbidden` — The OAuth access token was not granted the scope this operation requires. `details.code` is `SCOPE_MISSING` and `details.requiredScope` names the scope. Secret keys (`dd_sk_`) carry no scopes and never see this for a missing scope. The one-click start routes also answer it for a session created without one-click (a Free-plan team's session): no `details`, and the end user falls back to the manual records.
- `404`: `404 not_found` — The addressed resource does not exist, or the caller does not own it — the two collapse to one status on purpose, so an id cannot be enumerated by a caller who does not own it.
- `429`: `429 rate_limited` — Rate limited. `Retry-After` (seconds) is set and `details.retryAfterSeconds` repeats it. Branch on `details.reason`: `request_rate` means the caller is calling too fast (`details.limit` carries the cap), `recently_checked` means this one connection was DNS-checked inside its cooldown.
- `500`: `500 internal` — An unhandled server-side failure. Reported to our error tracker; safe to retry.

---

[API](https://skmtc.dev/dodomain/apis/dodomain-api.md) · [All operations](https://skmtc.dev/dodomain/apis/dodomain-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dodomain/apis/dodomain-api/revisions/44cfb944de58?raw)
