Appearance
Claim a domain
Take over a domain another team has already verified, by proving you own it.
http
POST /v1/domains/claimRequires a Full access API key.
Use this only when a domain is already verified by a different team and you control the DNS for it. If no other team has it, add it the normal way with Create a domain instead.
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The domain to claim, e.g. example.com. A valid, lowercase domain; max 253 characters. |
region | string | No | Where your sending identity will live once the claim verifies: us-east-1, eu-west-1, sa-east-1 or ap-northeast-1. Defaults to us-east-1. |
custom_return_path | string | No | The Return-Path subdomain for your identity. A bare label; max 63 characters. Defaults to send. |
Example
bash
curl -X POST 'https://api.sendgrail.com/v1/domains/claim' \
-H "Authorization: Bearer $SENDGRAIL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"name": "example.com",
"region": "us-east-1",
"custom_return_path": "send"
}'js
const res = await fetch('https://api.sendgrail.com/v1/domains/claim', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SENDGRAIL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'example.com',
region: 'us-east-1',
custom_return_path: 'send',
}),
});
const claim = await res.json();Response
201 Created. A placeholder domain is created on your team, plus a domain_claim carrying the TXT record you must publish to prove ownership.
json
{
"object": "domain_claim",
"id": "9a3c1e64-1b17-4f8c-9f0e-3b6c1e0f5c31",
"name": "example.com",
"status": "pending",
"domain_id": "5f1c3a9e-0d42-4b7c-9a63-2e8b41d7c015",
"region": "us-east-1",
"record": {
"type": "TXT",
"name": "example.com",
"value": "sendgrail-domain-verification=6f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c",
"ttl": "Auto"
},
"blocked_reason": null,
"failure_reason": null,
"created_at": "2026-07-14T19:44:32+00:00",
"expires_at": "2026-07-21T19:44:32+00:00"
}| Field | Description |
|---|---|
object | Always domain_claim. |
id | The claim id. |
name | The domain being claimed. |
status | pending, verified or failed. |
domain_id | The placeholder domain's id. This is the id you poll and verify with — see below. |
region | Where your identity will live once verified. |
record | The ownership TXT record to publish: type, name, value and ttl. |
blocked_reason | Why the claim can't proceed, or null. |
failure_reason | Why the last verification attempt failed, or null. |
created_at | ISO 8601 time the claim was opened. |
expires_at | ISO 8601 time the claim expires — 7 days out. After this it can no longer be verified. |
The claim flow
- Open the claim with this call. Note
domain_id— the placeholder domain's id, which every later step uses. - Publish the TXT record from
recordat your DNS provider. - Verify with Verify a domain claim, or poll it with Get a domain claim.
- On success the placeholder becomes your own sending identity, with its own DKIM. Retrieve the domain to get its new records, add them, and run Verify a domain to finish standing it up.
You have 7 days — after expires_at, the claim goes failed and you must start over.
You already own it — 409
If the domain is already on your team, there's nothing to claim:
json
{
"message": "This domain is already on your team — no claim needed.",
"code": "domain_exists",
"request_id": "8f2c1e64-1b17-4f8c-9f0e-3b6c1e0f5c31"
}Nothing to claim — 422
Claiming only makes sense when another team has verified the domain. If no one has, add it directly instead:
json
{
"message": "No other team has verified this domain. Add it with POST /v1/domains instead.",
"code": "nothing_to_claim",
"request_id": "8f2c1e64-1b17-4f8c-9f0e-3b6c1e0f5c31"
}A Sending access key answers 403. See Errors.