Senders and domains
The email provider a project sends through and the domains verified with it.
Get the sender
GET/projects/{project_id}/sender
The provider account the project sends through, without its secrets. 404 sender_not_found until one is connected.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
curl "https://sendocado.com/api/v1/projects/$PROJECT_ID/sender" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"{
"id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"from_name": "Sam at Acme",
"from_email": "sam@acme.example",
"reply_to_email": null,
"max_sends_per_hour": 1000,
"provider": {
"type": "resend"
},
"webhook_url": "https://sendocado.com/api/webhooks/resend/pr16umx1bz99nfd02is5d9ik40vstqqz",
"status": "ready",
"last_check": {
"error": null,
"checked_at": 1789998200000
},
"created_at": 1788272000000
}Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sender_not_found | Sender not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Connect or change the sender
PUT/projects/{project_id}/sender
Credentials are tested before anything is saved, then Sendocado sets up the provider’s delivery events itself. A null credential keeps the one stored for the same provider. Gmail connects in the app only.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
Body
Send JSON with every field; use null for a value you do not set.
| Field | Type | Notes |
|---|---|---|
| from_name | string | null | Required |
| from_email | string | Required |
| reply_to_email | string | null | Required |
| max_sends_per_hour | integer | Required |
| provider | object | Required |
| provider.type | "resend" | Required, when type is "resend" |
| provider.api_key | string | null | Required, when type is "resend" |
| provider.type | "ses" | Required, when type is "ses" |
| provider.region | string | Required, when type is "ses" |
| provider.access_key_id | string | null | Required, when type is "ses" |
| provider.secret_access_key | string | null | Required, when type is "ses" |
| provider.type | "postmark" | Required, when type is "postmark" |
| provider.server_token | string | null | Required, when type is "postmark" |
| provider.account_token | string | null | Required, when type is "postmark" |
| provider.message_stream | string | Required, when type is "postmark" |
| provider.type | "sendgrid" | Required, when type is "sendgrid" |
| provider.api_key | string | null | Required, when type is "sendgrid" |
| provider.type | "mailgun" | Required, when type is "mailgun" |
| provider.api_key | string | null | Required, when type is "mailgun" |
| provider.domain | string | Required, when type is "mailgun" |
| provider.region | "us" | "eu" | Required, when type is "mailgun" |
| provider.type | "smtp" | Required, when type is "smtp" |
| provider.host | string | Required, when type is "smtp" |
| provider.port | integer | Required, when type is "smtp" |
| provider.is_secure | boolean | Required, when type is "smtp" |
| provider.username | string | Required, when type is "smtp" |
| provider.password | string | null | Required, when type is "smtp" |
| provider.type | "gmail" | Required, when type is "gmail" |
curl -X PUT "https://sendocado.com/api/v1/projects/$PROJECT_ID/sender" \
-H "Authorization: Bearer $SENDOCADO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from_name": "Sam at Acme",
"from_email": "sam@acme.example",
"reply_to_email": null,
"max_sends_per_hour": 1000,
"provider": {
"type": "resend",
"api_key": "re_9xKp2mQ7_vB4nR8tY1wZ6cF3hJ5sD0aL"
}
}'{
"id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"from_name": "Sam at Acme",
"from_email": "sam@acme.example",
"reply_to_email": null,
"max_sends_per_hour": 1000,
"provider": {
"type": "resend"
},
"webhook_url": "https://sendocado.com/api/webhooks/resend/pr16umx1bz99nfd02is5d9ik40vstqqz",
"status": "ready",
"last_check": {
"error": null,
"checked_at": 1790000000000
},
"created_at": 1790000000000
}Errors
| Status | Type | Example message |
|---|---|---|
| 400 | invalid_data | Send a JSON request body. |
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sender_not_found | Sender not found. |
| 409 | conflict | This campaign has enrollments, so it cannot be deleted. Pause it instead. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Disconnect the sender
DELETE/projects/{project_id}/sender
Removes what Sendocado set up in the provider account; the project sends nothing until a sender is connected again.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
curl -X DELETE "https://sendocado.com/api/v1/projects/$PROJECT_ID/sender" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"Answers 204 with no body.
Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sender_not_found | Sender not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Test sender credentials
POST/projects/{project_id}/sender-checks
Tests the same body as the sender update with the provider, without saving anything.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
Body
Send JSON with every field; use null for a value you do not set.
| Field | Type | Notes |
|---|---|---|
| from_name | string | null | Required |
| from_email | string | Required |
| reply_to_email | string | null | Required |
| max_sends_per_hour | integer | Required |
| provider | object | Required |
| provider.type | "resend" | Required, when type is "resend" |
| provider.api_key | string | null | Required, when type is "resend" |
| provider.type | "ses" | Required, when type is "ses" |
| provider.region | string | Required, when type is "ses" |
| provider.access_key_id | string | null | Required, when type is "ses" |
| provider.secret_access_key | string | null | Required, when type is "ses" |
| provider.type | "postmark" | Required, when type is "postmark" |
| provider.server_token | string | null | Required, when type is "postmark" |
| provider.account_token | string | null | Required, when type is "postmark" |
| provider.message_stream | string | Required, when type is "postmark" |
| provider.type | "sendgrid" | Required, when type is "sendgrid" |
| provider.api_key | string | null | Required, when type is "sendgrid" |
| provider.type | "mailgun" | Required, when type is "mailgun" |
| provider.api_key | string | null | Required, when type is "mailgun" |
| provider.domain | string | Required, when type is "mailgun" |
| provider.region | "us" | "eu" | Required, when type is "mailgun" |
| provider.type | "smtp" | Required, when type is "smtp" |
| provider.host | string | Required, when type is "smtp" |
| provider.port | integer | Required, when type is "smtp" |
| provider.is_secure | boolean | Required, when type is "smtp" |
| provider.username | string | Required, when type is "smtp" |
| provider.password | string | null | Required, when type is "smtp" |
| provider.type | "gmail" | Required, when type is "gmail" |
curl -X POST "https://sendocado.com/api/v1/projects/$PROJECT_ID/sender-checks" \
-H "Authorization: Bearer $SENDOCADO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from_name": "Sam at Acme",
"from_email": "sam@acme.example",
"reply_to_email": null,
"max_sends_per_hour": 1000,
"provider": {
"type": "ses",
"region": "us-east-1",
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}'{
"is_ok": true,
"error": null
}Errors
| Status | Type | Example message |
|---|---|---|
| 400 | invalid_data | Send a JSON request body. |
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sender_not_found | Sender not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
List sending domains
GET/projects/{project_id}/sending-domains
Every domain verified (or being verified) with the sender, with its DNS records.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
curl "https://sendocado.com/api/v1/projects/$PROJECT_ID/sending-domains" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"{
"sending_domains": [
{
"id": "ztj0wyuhvauvzhmasqxezyex1rdrgdsj",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"sender_id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"domain": "acme.example",
"status": "verified",
"records": [
{
"purpose": "dkim",
"type": "TXT",
"name": "resend._domainkey.acme.example",
"value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7",
"priority": null,
"status": "verified"
},
{
"purpose": "spf",
"type": "TXT",
"name": "send.acme.example",
"value": "v=spf1 include:amazonses.com ~all",
"priority": null,
"status": "verified"
},
{
"purpose": "return_path",
"type": "MX",
"name": "send.acme.example",
"value": "feedback-smtp.us-east-1.amazonses.com",
"priority": 10,
"status": "verified"
}
],
"checked_at": 1789999940000,
"created_at": 1788272000000
}
],
"next_cursor": null
}Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | project_not_found | Project not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Add a sending domain
POST/projects/{project_id}/sending-domains
Adds the domain at the provider and returns the DNS records to create. Sendocado checks them every few minutes; status becomes verified once the provider sees them.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| project_id | path | string | Required |
Body
Send JSON with every field; use null for a value you do not set.
| Field | Type | Notes |
|---|---|---|
| domain | string | Required |
curl -X POST "https://sendocado.com/api/v1/projects/$PROJECT_ID/sending-domains" \
-H "Authorization: Bearer $SENDOCADO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "acme.example"
}'{
"id": "ztj0wyuhvauvzhmasqxezyex1rdrgdsj",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"sender_id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"domain": "acme.example",
"status": "pending",
"records": [
{
"purpose": "dkim",
"type": "TXT",
"name": "resend._domainkey.acme.example",
"value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7",
"priority": null,
"status": "pending"
},
{
"purpose": "spf",
"type": "TXT",
"name": "send.acme.example",
"value": "v=spf1 include:amazonses.com ~all",
"priority": null,
"status": "pending"
},
{
"purpose": "return_path",
"type": "MX",
"name": "send.acme.example",
"value": "feedback-smtp.us-east-1.amazonses.com",
"priority": 10,
"status": "pending"
}
],
"checked_at": null,
"created_at": 1788272000000
}Errors
| Status | Type | Example message |
|---|---|---|
| 400 | invalid_data | Send a JSON request body. |
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | project_not_found | Project not found. |
| 409 | conflict | This campaign has enrollments, so it cannot be deleted. Pause it instead. |
| 422 | sender_not_ready | Verify the domain of your from address before you send email. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Get a sending domain
GET/sending-domains/{sending_domain_id}
Its status and each DNS record’s status, as last checked.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| sending_domain_id | path | string | Required |
curl "https://sendocado.com/api/v1/sending-domains/$SENDING_DOMAIN_ID" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"{
"id": "ztj0wyuhvauvzhmasqxezyex1rdrgdsj",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"sender_id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"domain": "acme.example",
"status": "verified",
"records": [
{
"purpose": "dkim",
"type": "TXT",
"name": "resend._domainkey.acme.example",
"value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7",
"priority": null,
"status": "verified"
},
{
"purpose": "spf",
"type": "TXT",
"name": "send.acme.example",
"value": "v=spf1 include:amazonses.com ~all",
"priority": null,
"status": "verified"
},
{
"purpose": "return_path",
"type": "MX",
"name": "send.acme.example",
"value": "feedback-smtp.us-east-1.amazonses.com",
"priority": 10,
"status": "verified"
}
],
"checked_at": 1789999940000,
"created_at": 1788272000000
}Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sending_domain_not_found | Sending domain not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Remove a sending domain
DELETE/sending-domains/{sending_domain_id}
Removes it from Sendocado only; the provider account keeps it, because it may send other mail from it.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| sending_domain_id | path | string | Required |
curl -X DELETE "https://sendocado.com/api/v1/sending-domains/$SENDING_DOMAIN_ID" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"Answers 204 with no body.
Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sending_domain_not_found | Sending domain not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |
Check a domain’s DNS now
POST/sending-domains/{sending_domain_id}/checks
Asks the provider to look at the DNS again. The domain comes back as it stands (202); get it again in a few seconds for the result.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| sending_domain_id | path | string | Required |
curl -X POST "https://sendocado.com/api/v1/sending-domains/$SENDING_DOMAIN_ID/checks" \
-H "Authorization: Bearer $SENDOCADO_API_KEY"{
"id": "ztj0wyuhvauvzhmasqxezyex1rdrgdsj",
"project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
"sender_id": "pr16umx1bz99nfd02is5d9ik40vstqqz",
"domain": "acme.example",
"status": "verified",
"records": [
{
"purpose": "dkim",
"type": "TXT",
"name": "resend._domainkey.acme.example",
"value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7",
"priority": null,
"status": "verified"
},
{
"purpose": "spf",
"type": "TXT",
"name": "send.acme.example",
"value": "v=spf1 include:amazonses.com ~all",
"priority": null,
"status": "verified"
},
{
"purpose": "return_path",
"type": "MX",
"name": "send.acme.example",
"value": "feedback-smtp.us-east-1.amazonses.com",
"priority": 10,
"status": "verified"
}
],
"checked_at": 1789999940000,
"created_at": 1788272000000
}Errors
| Status | Type | Example message |
|---|---|---|
| 401 | unauthorized | Send a valid API key as "Authorization: Bearer sc_…", or sign in. |
| 404 | sending_domain_not_found | Sending domain not found. |
| 429 | rate_limited | Too many requests. Try again in 12 seconds. |