# Finalize a domain purchase after the embedded payment completes

> Finalize a domain purchase after the embedded payment completes: CustomDomain™ API reference. Covers parameters, request body, responses and error codes.

Source: https://docs.customdomain.ai/docs/api-reference/registrar/fulfillDomainPurchase

## `POST https://api.customdomain.ai/v1/registrar/fulfill`

Verifies the session, registers the domain, captures the charge, and auto-connects the domain. Idempotent per session id (the Stripe webhook drives the same path server-side, so a closed tab never strands a paid session). `201` on first fulfillment, `200` on an idempotent replay. Exactly one caller fulfills a session: the first to claim its order registers the domain and captures the charge, and a caller that arrives while it is still working waits briefly, then gets that result or a `409` with code `fulfillment_in_progress`. A `409` never releases the authorization; retry the call, or read `GET /v1/sell/orders/{id}`, to see the outcome.

### Authentication

`widgetJWT`

### Request body (JSON)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `session_id` | string | yes |  |

### Responses

| Status | Description |
| --- | --- |
| `200` | Already fulfilled (idempotent replay) |
| `201` | Purchased |
| `400` | Error envelope: {code, title, details}. |
| `401` | Error envelope: {code, title, details}. |
| `409` | Another call is still completing this purchase (code: fulfillment_in_progress). The payment stays authorized and `order` is the order as it stands (status `purchasing`). Also `conflict` when the order can no longer be fulfilled (for example `expired`); the card was not charged. |
| `502` | Registrar registration failed after payment authorization; the card authorization was released (code: registration_failed). |
| `503` | Error envelope: {code, title, details}. |

### `200` response body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `Domain` | string | no |  |
| `Registrar` | string | no |  |
| `RegOrderID` | string | no |  |

The full specification is served at `GET https://api.customdomain.ai/v1/openapi.json`.
