Verify Domain
Check a domain's DNS records now, without waiting for the periodic check, and return the result. Call it after publishing the records from Create Domain.
The check runs before the response is sent, so the status in the response is the outcome. DNS changes can take a while to propagate; if the domain is still pending, wait a few minutes and call it again. A domain that is already verified is returned as it is.
A failed domain does not recover: its records did not validate within the verification window (around 72 hours). Delete it and register it again to get new records.
Endpoint
POST /email/domains/:id/verify
Returns: 200 OK
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer <your-api-key> | Yes |
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The domain ID |
No request body.
Response
{
"id": "01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a",
"name": "mail.acme.com",
"status": "verified",
"verified_at": "2026-03-08T12:20:00.000Z",
"created_at": "2026-03-08T12:00:00.000Z",
"records": [
{
"type": "CNAME",
"name": "4hbfxq3v2nkd6wz5ymtj7ra2ue3lc5po._domainkey.mail.acme.com",
"value": "4hbfxq3v2nkd6wz5ymtj7ra2ue3lc5po.dkim.amazonses.com",
"purpose": "dkim",
"required": true,
"status": "verified"
},
{
"type": "CNAME",
"name": "s7kq2mwx9pzr4tbv6ny3hd8cgj5fa2le._domainkey.mail.acme.com",
"value": "s7kq2mwx9pzr4tbv6ny3hd8cgj5fa2le.dkim.amazonses.com",
"purpose": "dkim",
"required": true,
"status": "verified"
},
{
"type": "CNAME",
"name": "zt5c8rjd2wqy7mhn4xkb9vp3ga6fe2us._domainkey.mail.acme.com",
"value": "zt5c8rjd2wqy7mhn4xkb9vp3ga6fe2us.dkim.amazonses.com",
"purpose": "dkim",
"required": true,
"status": "verified"
},
{
"type": "TXT",
"name": "mail.acme.com",
"value": "v=spf1 include:amazonses.com ~all",
"purpose": "spf",
"required": false,
"status": "verified"
},
{
"type": "TXT",
"name": "_dmarc.mail.acme.com",
"value": "v=DMARC1; p=none;",
"purpose": "dmarc",
"required": false,
"status": "pending"
}
]
}
The fields are the same as in Get Domain.
Examples
- cURL
- JavaScript
- Python
- C#
- PHP
curl -X POST "https://api.arsel.sa/v1/email/domains/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/verify" \
-H "Authorization: Bearer $ARSEL_API_KEY"
const response = await fetch("https://api.arsel.sa/v1/email/domains/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ARSEL_API_KEY}`,
},
});
const data = await response.json();
if (!response.ok) {
throw new Error(`${data.name}: ${data.message}`);
}
console.log(data);
import os
import requests
response = requests.post(
"https://api.arsel.sa/v1/email/domains/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/verify",
headers={"Authorization": f"Bearer {os.environ['ARSEL_API_KEY']}"},
)
response.raise_for_status()
print(response.json())
using System.Net.Http.Headers;
var client = new HttpClient(); // share one instance across requests
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("ARSEL_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.arsel.sa/v1/email/domains/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/verify");
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException($"{(int)response.StatusCode}: {body}");
Console.WriteLine(body);
<?php
$ch = curl_init("https://api.arsel.sa/v1/email/domains/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/verify");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ARSEL_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) {
throw new Exception("{$data['name']}: {$data['message']}");
}
print_r($data);
Rate Limit
This endpoint allows 10 requests per 60-second window per organization, separate from the default limit.
Error Responses
- 400 Domain Unavailable
- 404 Not Found
- 401 Unauthorized
- 429 Rate Limited
A parent or subdomain of the domain has since been verified by another organization.
{
"status_code": 400,
"name": "domain_unavailable",
"message": "This domain cannot be verified because a related domain is already verified by another organization."
}
{
"status_code": 404,
"name": "not_found",
"message": "Domain not found"
}
{
"status_code": 401,
"name": "unauthorized",
"message": "Invalid API Key"
}
{
"status_code": 429,
"name": "rate_limit_exceeded",
"message": "Too many requests. Please retry after the period indicated in the retry-after header."
}