> ## Documentation Index
> Fetch the complete documentation index at: https://developers.entri.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sell SDK

> The purchaseDomain() method, configuration options, error handling, and the Sell server-side endpoints for async DNS configuration and listing purchased domains.

## `entri.purchaseDomain(config)`

This method launches the [Entri Sell](/sell/overview) modal. The `config` object includes the same set of properties as those specified in [entri.connectDomain(config)](/connect/configuration#entri-connectdomain-config), plus additional Sell-specific options:

<Note>
  For browser callback events (`onSuccess`, `onEntriClose`), see [Sell Events](/sell/events#browser-callback-events).
</Note>

<Note>
  Domains purchased through `purchaseDomain()` are not monitored by default. To track them with [Entri Monitor](/monitor/overview), pass `monitor: true` in the config as described in [Monitor configuration](/monitor/configuration). Only [`showUnify()`](/unify/overview) enrolls domains in Monitor automatically.
</Note>

| Property | Type | Required? | Default | Description |
| - | - | - | - | - |
| `disableConnect` | boolean | No | false | If true, the flow will only run the domain(s) purchase process, but no specific DNS records will be configured. |
| `debugMode` | boolean | No | false | For testing purposes. It skips the actual payment process and takes the user to the congratulations step. Not currently supported when GoDaddy is the selected registrar. |
| `successCallbackUrl` | string | No | N/A | The URL where the user will be redirected after a successful domain purchase. |
| `exitCallbackUrl` | string | No | N/A | The URL where the user will be redirected if they exit the purchase flow before completing it (e.g. closing the modal). |
| `dnsRecords` | array | Yes | N/A | An array of DNS records to configure for the purchased domain. Each record should include `type`, `host`, `value`, and `ttl`. |
| `freeDomain` | boolean | No | false | This feature allows you to offer your users their first domain at no cost. Should only be used on paid users on your platform. Please contact your account manager to enable this feature. |
| `locale` | string | No | `"en"` | The language/locale used in the domain purchase flow. |
| `disableMailUpsell` | boolean | No | false | If set to true, the mail inbox upsell step is disabled and will not appear in the domain purchase flow. This property allows you to prevent the mail inbox upsell step seamlessly, ensuring a streamlined user experience without optional distractions. |
| `searchType` | string | No | `"classic"` | (IONOS only) Use "ai" to enable AI-generated domain suggestions instead of the default "classic" search. |
| `whiteLabel` | object | No | N/A | Customizes the branding and appearance of the purchase flow. Includes options for setting the logo, theme colors, hiding logos, and customizing text on the initial screen. |
| `whiteLabel.sell.flowTarget` | string | No | `_parent` | The target location where the purchase flow window will be displayed. If \_blank is specified, the flow will open in a new browser tab. |
| `whiteLabel.sell.partnerLogo` | string | No | N/A | The URL of the partner’s logo, which will be displayed prominently in the cobranded header of the purchase flow. |
| `whiteLabel.sell.partnerName` | string | No | N/A | The name of the partner company to display within the purchase flow. |
| `whiteLabel.sell.contact` | object | No | N/A | Prefilled user data required for creating the domain. This includes fields like `firstName`, `lastName`, `email`, `phone`, `address`, `zip`, `city`, `state`, `postalCode`, and `country`. |

This `purchaseDomain` method includes all the latest theming options, cobranded elements, and features such as `successCallbackUrl` and `exitCallbackUrl`. Make sure to set the appropriate fields to customize the flow according to your needs.

### Possible `purchaseDomain()` Errors

When any of the following critical errors occur, a console error will be logged, and the user will only see “Entri is misconfigured. Please contact support for assistance.” in the UI.

| Error | Console Message | Reason |
| - | - | - |
| Failed to Fetch Application Settings | "Failed to fetch application settings" | API call failed (network error, invalid appId, or API down). |
| Missing Registrar | "Entri is misconfigured. Your preferred registrar is missing. Please contact support for assistance." | No Sell registrar is selected for the application. Select one in the Entri Dashboard under Application Settings, Sell Registrars tab (see [Step 2 of the integration guide](/sell/modal-integration#step-2-select-your-sell-registrar-partner)). |
| Unsupported Registrar | "Preferred registrar {registrar} is not supported. Please contact support for assistance." | The registrar selected for the application is not one Entri supports. Supported registrars are IONOS, Squarespace, and GoDaddy. |

## Asynchronous DNS configurations ([Entri Sell](/sell/overview) only)

You can make asynchronous DNS configurations after the initial **Entri Sell** flow has finished, for as long as the domain stays registered with the Sell registrar.

<Note>
  There is no time limit on asynchronous configurations. They remain available until the domain expires or is transferred to another registrar.
</Note>

This feature allows you to add or update DNS records after the initial setup without requiring users to repeat the full flow. (Not supported on `debugMode=true` flows.)

```bash theme={"system"}
POST https://api.goentri.com/connect/async
Header "Authorization: [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

### Sample body:

```JSON JSON theme={"system"}
{
  "applicationId": "clickfunnels",
  "domain": "domain.com",
  "subdomain": "www",
  "wwwRedirect": false,
  "dnsRecords": [
    {
      "value": "13.248.155.104",
      "host": "@",
      "ttl": 300,
      "type": "A"
    }
  ]
}
```

### Properties:

| Type | Property | Required? | Default | Description |
| - | - | - | - | - |
| string | applicationId | Yes | N/A | The ID of your application (set in the dashboard) |
| string | domain | Yes | N/A | The domain that will have the DNS records configured, e.g. example.com |
| array of DNSRecord objects | dnsRecords | Yes | N/A | The DNS records you wish to configure for your users |
| string | subdomain | No | N/A | The subdomain that will have the DNS records configured, e.g. www |
| boolean | wwwRedirect | No | false | If true, Entri will automatically set the redirect from the bare domain to the www subdomain. |

## List purchased domains

This server-side endpoint returns every domain your application has sold through Entri Sell, along with the `userId` you passed in the config at purchase time. Use it to match each purchased domain to the right account in your system, run audits, or backfill data missed by [webhook notifications](/webhooks-overview). Results are scoped to your `applicationId`.

<Note>
  Only domains purchased through the Sell flow are returned, regardless of which registrar (IONOS, GoDaddy, etc.) fulfilled the purchase. Domains transferred directly to another registrar outside of Sell, for example as part of a bulk migration, are not included.
</Note>

```bash theme={"system"}
GET https://api.goentri.com/sell/domains?{query-params}
Header "Authorization: Bearer [JWT authorization]"
Header "applicationId: [yourApplicationID]"
Header "Accept: application/json"
```

Authentication uses the same short-lived JWT as every other Entri API. Mint it server-side with your `applicationId` and `secret` as described in [Token creation (JWT)](/connect/configuration#token-creation-jwt), and send it as a Bearer token together with the `applicationId` header.

### Query parameters

| Parameter | Required? | Description |
| - | - | - |
| `userId` | No | Return only the domain(s) purchased for this end user. Matches the `userId` you passed in your integration config at purchase time. |
| `domain` | No | Return only domains whose name contains this text (partial match, not case-sensitive). |
| `fromDate` | No | Only include purchases made on or after this date. Format: `YYYY-MM-DD`. |
| `toDate` | No | Only include purchases made on or before this date. Format: `YYYY-MM-DD`. |
| `page` | No | Page number, starting at `0`. Defaults to `0`. |
| `limit` | No | Number of results per page. Defaults to `100`, maximum `500`. |

If no filters are supplied, the endpoint returns every domain purchased through Sell for your application, most recent first.

### Example request

```bash theme={"system"}
curl -X GET \
"https://api.goentri.com/sell/domains?fromDate=2026-01-01&toDate=2026-01-31&page=0&limit=10" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-H "applicationId: <YOUR_APPLICATION_ID>" \
-H "Accept: application/json"
```

### Example response

```json theme={"system"}
{
  "items": [
    {
      "purchaseId": "fb044917-e35d-42fb-a195-c43c4e031d6b",
      "domain": "example.com",
      "userId": "user-123",
      "purchaseDate": "2026-01-14 19:43:46",
      "status": "purchased",
      "provider": "GODADDY",
      "connectionId": "gYSe9Q8cKEw4KEhyLA==",
      "companyId": "79fa2550-1e21-4fd8-9ec7-61351e4fd8f9",
      "couponCode": "",
      "freeDomain": false,
      "mailUpsell": false,
      "customerId": "",
      "sourceApplicationUuid": ""
    }
  ],
  "total": 56,
  "page": 0,
  "limit": 10,
  "count": 10,
  "pages": 6,
  "nextPage": 1,
  "prevPage": null
}
```

Each entry in `items` represents one purchased domain:

| Field | Description |
| - | - |
| `purchaseId` | Unique identifier for this purchase record. Useful when referencing a specific purchase in support requests. |
| `domain` | The purchased domain name. |
| `userId` | The end-user ID you passed in your integration config at purchase time. Empty string if none was provided. |
| `purchaseDate` | Date and time of the purchase, in `YYYY-MM-DD HH:MM:SS` format. |
| `status` | Currently always `purchased`. |
| `provider` | The registrar that fulfilled the purchase, e.g. `IONOS`, `GODADDY`. |
| `connectionId` | Internal identifier linking this purchase to a DNS connection flow, if applicable. Empty string otherwise. |
| `companyId` | Identifier for the Entri company account associated with this purchase. |
| `couponCode` | Coupon code applied at purchase. Empty string if none was used. |
| `freeDomain` | `true` if the domain was provided at no cost as part of a bundle or promotion. |
| `mailUpsell` | `true` if the user also purchased an email add-on at the same time. |
| `customerId` | Internal customer identifier, if available. Empty string otherwise. |
| `sourceApplicationUuid` | Identifies the originating application when the purchase came through a sub-account or reseller flow. Empty string when it originated directly from your application. |

The response envelope carries the pagination data:

| Field | Description |
| - | - |
| `total` | Total number of domains matching your filters, across all pages. |
| `page` | The page number returned. |
| `limit` | The page size used. |
| `count` | Number of items in this response. |
| `pages` | Total number of pages at this page size, rounded up (56 results at `limit: 10` is `6` pages). |
| `nextPage` | The next page number to request, or `null` on the last page. |
| `prevPage` | The previous page number, or `null` on the first page. |

### Errors

Errors are returned as `{ "message": "Error description" }` with the corresponding HTTP status code.

| HTTP Status | When it happens |
| - | - |
| `401 Unauthorized` | Credentials are missing or invalid: no `applicationId`, an expired or invalid JWT, or a JWT that does not match the `applicationId`. |
| `400 Bad Request` | A query parameter is invalid, e.g. `fromDate`/`toDate` is not `YYYY-MM-DD`, or `limit`/`page` is not a number. |
| `500 Internal Server Error` | An unexpected error occurred on Entri's side. |

An empty result is not an error. If no domains match your filters, or your application has no Sell purchases yet, the request returns `200 OK` with `"items": []` and `"total": 0`.

## Check flow status

This server-side endpoint returns the current state of a Sell flow identified by its `job_id`. Use it to follow a purchase you started from your backend, for example through the [Sell sharing links API](/sell/modal-integration#sharing-links-api-entri-sell), or to confirm on demand that the purchased domain's DNS records have propagated. [Webhooks](/sell/events#webhook-event-types) remain the recommended way to be notified when a purchase progresses; this endpoint complements them when you need to read the state at a given moment.

```bash theme={"system"}
GET https://api.goentri.com/sell/{job_id}/status
Header "Authorization: Bearer [JWT authorization]"
Header "applicationId: [yourApplicationID]"
```

Authentication uses the same short-lived JWT as every other Entri API. Mint it server-side with your `applicationId` and `secret` as described in [Token creation (JWT)](/connect/configuration#token-creation-jwt), and send it as a Bearer token together with the `applicationId` header. The endpoint only returns flows that belong to that `applicationId`.

### Path parameters

| Parameter | Type | Required? | Description |
| - | - | - | - |
| `job_id` | string (UUID v4) | Yes | The Sell flow identifier. Capture it from the [`onSuccess`](/sell/events#onsuccess-callback-event) browser event or from the `job_id` returned when you create a sharing link. |

<Note>
  On an order with several domains, the webhooks for each domain carry their own per-domain `id`. Those identifiers have no flow record of their own. Always query this endpoint with the flow's `job_id`, not with a per-domain webhook `id`.
</Note>

### Example request

```bash theme={"system"}
curl -X GET \
"https://api.goentri.com/sell/9c128fe4-63cd-4ec4-9ae8-8a9d06c0e6de/status" \
-H "Authorization: Bearer <AUTH_TOKEN>" \
-H "applicationId: <YOUR_APPLICATION_ID>"
```

### Example response

```json theme={"system"}
{
  "job_id": "9c128fe4-63cd-4ec4-9ae8-8a9d06c0e6de",
  "connected": false,
  "status": "in_progress",
  "prefilled_domain": "example.com",
  "domains": ["example.com", "example.net"]
}
```

| Field | Type | Description |
| - | - | - |
| `job_id` | string | The flow identifier from the path. |
| `connected` | boolean | `true` once Entri has confirmed that the DNS records for the purchased domain propagated. This is the same condition that produces `propagation_status: "success"` in the webhook. |
| `status` | string | The progress marker of the purchase flow. See the table below. |
| `prefilled_domain` | string | The domain passed as `prefilledDomain` in the configuration, or the domain of the flow when none was prefilled. |
| `domains` | array of strings | The domains in the order. Only present once the user has reached the checkout. |

### Status values

`status` reflects the step the purchase flow reached and is reported as stored. The values below are the ones the flow produces today.

| `status` | Meaning |
| - | - |
| `pending` | The link was created and the user has not started the flow. |
| `in_progress` | The user entered the checkout. |
| `purchase flow completed` | The payment went through and the order was placed. |
| `success` | The DNS records for the purchased domain propagated. `connected` is `true` at this point. |
| `purchase_canceled`, `user_aborted`, `account_linking_failed`, `invalid_config` | The purchase did not complete. The value names the reason. |

<Warning>
  These values are an internal vocabulary and may change. Base decisions on `connected` and on the [`domain.purchased`](/sell/events#webhook-event-types), [`domain.registered`](/sell/events#registration-events) and [`domain.added`](/connect/events#webhook-event-types) webhooks rather than on exact `status` strings.
</Warning>

### Errors

Errors are returned as `{ "message": "Error description" }` with the corresponding HTTP status code.

| HTTP Status | Message | When it happens |
| - | - | - |
| `400 Bad Request` | `Invalid job_id format` | The `job_id` is missing or is not a UUID v4. |
| `400 Bad Request` | `Sell flow not found for job id: {job_id}` | No flow exists with that `job_id`. |
| `400 Bad Request` | `Sell flow not found for job id associated with application id: {application_id}` | The flow exists but belongs to a different `applicationId`. |
| `403 Forbidden` | `Application ID not found` or `JWT token is expired or invalid` | Credentials are missing or invalid. |
| `500 Internal Server Error` | `Failed to retrieve Connect flow status` | An unexpected error occurred on Entri's side. The message reads "Connect" on this endpoint as well. |
