Search the docs
Find a page, a section, or an endpoint.
Connecting a domain
The records to publish, delegated to your customer — and how to wait.
A domain is the one thing this API cannot finish for you. We can generate every record, check them, and tell you the moment they land — but we cannot write in somebody else's zone, and a product that asked you to move your nameservers so it could would be a different product.
So the job here is to make that step delegable. You get the records in the same response as the domain, you show them to your own customer in your own words, and nobody ever sees a Pidgeon screen.
Connect one
curl https://pidgeon.ai/api/v1/domains \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "domain": "acme.com" }'Five kinds of record come back. ownership is a TXT record proving the domain
is yours; mx routes inbound mail to us; spf and dkim are what stop your
outgoing mail being treated as spam; dmarc asks other providers to report on
anything claiming to be you. Each carries a one-line description written for
the person who has to publish it, so you do not have to write those sentences
yourself.
Check dns_complete before you show the list. The DKIM records are derived
from what our mail provider issued, and until that has happened the list looks
complete and is missing three CNAMEs. Publishing it in that state gives you a
domain that verifies and cannot sign mail — which fails in a way nobody
debugs quickly.
Wait for it
curl -X POST https://pidgeon.ai/api/v1/domains/$DOMAIN_ID/verify \
-H "Authorization: Bearer $PIDGEON_API_KEY"Idempotent and safe to poll. Calling it on a domain that is already verified re-checks and says so rather than erroring, because a poll loop that has to special-case success is a poll loop with a bug in it.
Two states, not one: verified means we believe the domain is yours,
mail_configured means it can actually send and receive. A domain can sit at
the first for a while — somebody publishes the TXT record and stops reading
the instructions.
Better than polling: subscribe to domain.verified and do not poll at
all. DNS propagation is measured in a zone's TTL and neither of us controls
it, so a webhook costs you one request and a poll loop costs you hundreds.
When it does not verify
GET /v1/domains/{id} returns every record with its own status —
connected, waiting, incorrect, or not_required — and found, which is
what we actually read at that name.
That last field is the one that matters. A record with the right name and the
wrong value looks exactly like a missing one until you can see what is there
instead, and "your domain is not verified" is not something your customer can
act on. "Your MX record points at mail.oldhost.com" is.
Disconnecting
DELETE /v1/domains/{id} takes the domain's addresses, their mail, their
routing rules and their webhooks with it. There is no undo and no soft form of
it. It takes an id rather than a name on purpose: an id comes from a list you
just read, and a name comes from a variable that might be wrong.