Sending Invoice Email from Your Own Domain
By default every invoice email GoRoute sends leaves from a GoRoute address. If you would rather your buyers saw your own domain in the From line, you register that domain, publish a short list of DNS records, and wait for verification. Five API calls cover the whole feature.
All paths below are relative to https://app.goroute.ai/peppol-api. Every call is scoped to
the organisation of the credential you send.
A verified sending domain changes the From address of the draft invoice email:
POST /api/v1/drafts/{draft_id}/send-via-gorouteโ the first send of a draftPOST /api/v1/drafts/{draft_id}/resendโ any later send of the same draft
It does not change these, which always send from GoRoute's own verified sender, whether or not you have a domain of your own:
POST /api/v1/transactions/{transaction_id}/emailโ emailing a transaction's documentPOST /api/v1/documents/{document_id}/emailโ emailing a pro forma invoice or delivery note
On those two calls sender_name sets the display name only. The From address stays
GoRoute's, exactly as
Delivery and Formats says.
The five callsโ
| Call | What it does |
|---|---|
GET /api/v1/sender-domains | Lists the domains your organisation has registered, newest first |
POST /api/v1/sender-domains | Registers a domain and asks for its DKIM records |
GET /api/v1/sender-domains/{domain_id} | Reads one domain, including the DNS records to publish |
POST /api/v1/sender-domains/{domain_id}/verify | Re-checks verification now instead of waiting for the next automatic check |
DELETE /api/v1/sender-domains/{domain_id} | Removes the domain |
Authentication. All five accept either an organisation API key in the X-API-Key header
or a signed-in portal session. None of them requires a particular permission, so any valid
API key for your organisation can register, verify and delete a sending domain. Treat that as
it is: there is no separate "manage sending domains" right to withhold.
Step 1 โ register the domainโ
POST /api/v1/sender-domains
X-API-Key: your-api-key
Content-Type: application/json
{
"domain": "acme.example",
"from_address": "billing@acme.example",
"reply_to_address": "accounts@acme.example"
}
domain is required and is stored lower-case with any trailing dot removed. Anything that is
not a valid domain name is refused with 400. from_address and reply_to_address are
optional; both are addresses, up to 320 characters.
The answer is 201 with the domain's current state and the DNS records you have to publish:
{
"id": "4f0f2a76-5a3c-4e3a-9a1b-22c0f1d7e3b4",
"domain": "acme.example",
"status": "pending",
"dkim_status": "pending",
"spf_status": null,
"dmarc_status": null,
"dkim_tokens": [
"hs4mkvbn7q2xz6rt3ldjw9cyp5gu8af1",
"t9wbq3nd7v2hm5kzx8plr4jc6sy1gaef",
"z2cpx7fk4nmr9td6wsvh3ylb8qja5geu"
],
"from_address": "billing@acme.example",
"reply_to_address": "accounts@acme.example",
"verified_at": null,
"last_checked_at": "2026-09-14T09:12:44.118000+00:00",
"dns_records": {
"dkim": [
{
"type": "CNAME",
"name": "hs4mkvbn7q2xz6rt3ldjw9cyp5gu8af1._domainkey.acme.example",
"value": "hs4mkvbn7q2xz6rt3ldjw9cyp5gu8af1.dkim.amazonses.com"
}
],
"spf": {
"type": "TXT",
"name": "acme.example",
"value": "v=spf1 include:amazonses.com ~all"
},
"dmarc": {
"type": "TXT",
"name": "_dmarc.acme.example",
"value": "v=DMARC1; p=none; rua=mailto:dmarc-reports@acme.example"
},
"verification": null
},
"is_verified": false
}
The dkim list is shortened above: there is one CNAME for every entry in dkim_tokens.
Registering the same domain twice is safe. If your organisation already has a row for
that domain, the call updates it and re-fetches the DKIM records rather than creating a
second one. Note that sending from_address or reply_to_address again replaces the stored
value, but sending them as null does not clear an address you set earlier.
If the mail provider cannot be reached when you register, the domain is stored as
pending with no DKIM records issued yet โ dkim_tokens is empty and the dkim list in
dns_records is empty with it. Call the domain again later; the records appear once they
have been issued.
Step 2 โ publish the DNS recordsโ
Publish everything in dns_records at the registrar or DNS host for the domain.
| Record | Name | Purpose |
|---|---|---|
| CNAME, one per DKIM token | <token>._domainkey.<your-domain> | Lets the mail be signed as yours. This is the one verification waits for |
| TXT | <your-domain> | SPF โ names the sending service as allowed to send for you |
| TXT | _dmarc.<your-domain> | DMARC โ a monitoring-only policy (p=none) with a reports address on your own domain |
| TXT | _amazonses.<your-domain> | Only present when a verification token has been issued. It is null in dns_records until then |
Two honest notes about these:
- The SPF and DMARC values are suggestions, not our checks. If your domain already
publishes SPF or DMARC, merge rather than replace โ a second SPF record on the same name
breaks both. The DMARC value we hand back monitors only; it enforces nothing, and it points
reports at
dmarc-reports@<your-domain>, an address you have to be able to receive at if you want them. spf_statusanddmarc_statusare alwaysnull. They are in the response, but nothing in the service ever fills them in. Do not read them as "we checked your SPF" โ we do not check it. Verification depends on DKIM alone.
Step 3 โ wait for verification, or ask for it nowโ
GoRoute re-checks every domain that is pending or temporary_failure every ten
minutes, and re-checks an already verified domain about once a day. DNS changes are usually
picked up within the hour, but that is your DNS host's timing, not ours.
To check immediately rather than wait for the next round:
POST /api/v1/sender-domains/{domain_id}/verify
X-API-Key: your-api-key
This re-reads the domain's status from the mail provider and returns the same shape as
GET /api/v1/sender-domains/{domain_id}. It does not query your DNS itself, so a record you
published seconds ago may still show as pending.
status is one of:
status | Meaning |
|---|---|
pending | Registered; DKIM not verified yet. This is also where a domain sits when the provider could not be asked |
verified | Verified. verified_at is set, is_verified is true, and draft emails can now go out from this domain |
failed | Verification failed. Check the DKIM CNAMEs are published exactly as given |
temporary_failure | A transient failure at the provider. It stays in the ten-minute re-check loop |
dkim_status is the provider's own DKIM state in lower case โ pending while it waits,
success once the signature verifies. last_checked_at is the last time we asked, and it
moves even when nothing changed.
What changes once a domain is verifiedโ
Draft invoice emails go out from your domain:
- The From address is your
from_addressif you set one. If you did not, the mail is sent frominvoices@<your-domain>. - The name the buyer sees is your
from_addressif you set one, and the bare domain โacme.exampleโ if you did not. These are deliberately two different things, so a buyer never sees a synthesisedinvoices@address presented as your name. - Replies go to
reply_to_addresswhen you set one.
Until a domain is verified, POST /api/v1/drafts/{draft_id}/send-via-goroute and
POST /api/v1/drafts/{draft_id}/resend are refused with 412 and the message "No verified
sender domain for this organization." That refusal is about the domain only; a draft send can
still fail for other reasons โ 400 with no buyer address, 409 when a first send has
already happened, 429 after three resends of the same draft in 24 hours, and 503 when
email is not switched on in that environment.
If you have more than one verified domain, only one of them is used, and there is no setting that chooses which. Register the single domain you want to send from.
Removing a domainโ
DELETE /api/v1/sender-domains/{domain_id}
X-API-Key: your-api-key
204, and the domain is gone. Read that literally before you call it:
- There is no confirmation step and no undo. The record is deleted outright, not archived.
- Any valid API key for your organisation can do it, with no special permission.
- From that moment, every draft invoice email for your organisation is refused with 412 until you register the domain again and it verifies โ which waits on DNS and on the ten-minute check, so it is not a matter of seconds.
An unknown id, or one belonging to another organisation, answers 404 on this call and on
every other call that takes a domain_id.
What this page does not tell youโ
- Whether email is switched on in the environment you are calling. Draft sends answer 503 when it is not. That is configuration, not something these five calls report.
- Anything about GoRoute's own sending domain. The address transaction and non-fiscal document emails come from is ours and is not configurable through this API.
Related pagesโ
- Delivery and Formats โ when a document travels by email at all, and how the transaction email call behaves
- Pro Forma Invoices and Delivery Notes โ the other email that always comes from GoRoute's sender
- Tracking Delivery โ what happens to a document after it leaves