Pigeon Atlas
← Integrations

Send email from Xano

An External API Request in a Xano function stack sends from your domain with your DKIM key, keeps the key in an environment variable, and returns a message id your table can keep.

Updated September 15, 2026

Xano's function stack has an External API Request step, and a Pigeon Atlas send is exactly one of those. The key goes in Xano's environment variables so it is never in a function, and the response comes back as an object the rest of the stack can use.

The environment variable

Settings → Environment Variables → Add: name PIGEONATLAS_API_KEY, value your key. Every function stack can read it as $env.PIGEONATLAS_API_KEY, and rotating the key later is one edit.

The request

In the function stack — an API endpoint, a background task, a trigger on a table — add External API Request:

Field Value
URL https://pigeonatlas.com/v1/emails
Method POST
Headers Authorization: Bearer + $env.PIGEONATLAS_API_KEY, Content-Type: application/json
Params an object (below)

For Params, build an object with the inputs of the stack:

from    = "Your App <hello@mail.yourapp.com>"
to      = $input.email
subject = "Your order " ~ $input.order_number ~ " is confirmed"
text    = "Thanks — order " ~ $input.order_number ~ " is on its way."

With Content-Type: application/json Xano sends the object as a JSON body. Use the ~ concatenation in the subject rather than a separate text step; it reads as one line in the stack.

The response, and the id

The step's output is { "response": { "status": 200, "result": { "id": "..." } } }. Take result.id and write it to the record that caused the message — an email_id column on the order — with an Edit Record step. Later, "did they get it?" is a search on the messages page by that id.

Branch on response.status. A 402 is the month's allowance gone; a 403 with validation_error is a from address on a domain that is not verified. Both are worth surfacing in the API's own response rather than swallowing, so the front end knows the receipt did not go.

Table triggers and not sending twice

Xano's Triggers run a stack when a record is added. A stack that sends from a trigger should add a third header, Idempotency-Key, set to something unique to the record — "order-" ~ $input.id — so a retried run returns the original message instead of sending another.

Before it works

Add mail.yourapp.com in Pigeon Atlas, publish the DKIM, SPF and MX records it shows, and wait for the ticks beside them. Sending from a domain that has not resolved is refused with a message naming the missing record. Use a subdomain rather than the bare domain, so the app's transactional mail keeps a reputation of its own.

A thousand a month free, no card

Enough to verify a domain and run a small app from it.

Start sending

Other platforms