API reference
Everything is one HTTP call
JSON in, JSON out, over HTTPS at https://aslio.asli.one/v1. No SDK required — though you are welcome to wrap it in one.
Authentication
Every request carries an API key as a bearer token. Keys are created and revoked in the dashboard and shown only once. Treat one like a password: server-side only, never in a browser or a mobile app.
curl https://aslio.asli.one/v1/account \
-H "Authorization: Bearer as_live_…"Send one email
The From address must be on a domain you have verified. Pass an Idempotency-Key and you can retry the same request safely — a duplicate replays the original response rather than sending twice.
curl https://aslio.asli.one/v1/email/send \
-H "Authorization: Bearer as_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-4417" \
-d '{
"from": "Acme <news@acme.in>",
"to": ["priya@example.com"],
"subject": "Your invoice is ready",
"html": "<p>Hello</p>",
"statusCallbackUrl": "https://acme.in/hooks/aslio"
}'Send a campaign
Up to 1,000 recipients per call, each with their own merge variables and its own message row, charge and unsubscribe link. Suppressed addresses are skipped and reported rather than silently dropped.
POST /v1/email/send-batch
{
"from": "Acme <news@acme.in>",
"subject": "Hi {{firstName}}, your fee is due",
"html": "<p>Hi {{firstName}} — {{course}}</p>",
"recipients": [
{ "email": "priya@example.com",
"variables": { "firstName": "Priya", "course": "NEET" } }
]
}OTP verification
One call sends a one-time code over email, SMS or WhatsApp; a second call checks it. Codes are never stored or returned — only a salted hash — and expire in 5 minutes by default. Wrong guesses are counted (5 lock the challenge), resends invalidate earlier codes, and per-number throttles blunt SMS-pumping attacks. For SMS the code is filled into your registered DLT template automatically.
POST /v1/otp/send
{ "channel": "email", "to": "priya@example.com",
"from": "no-reply@acme.in" }
→ { "id": "otp_…", "status": "PENDING", "expiresAt": "…" }
POST /v1/otp/verify
{ "id": "otp_…", "code": "482913" }
→ { "verified": true, "status": "VERIFIED" }
// wrong code → 400 { "verified": false, "attemptsRemaining": 4 }Delivery webhooks
Set statusCallbackUrl and each outcome is POSTed to you as it happens: SENT, DELIVERED, BOUNCED, COMPLAINED or FAILED. Verify the signature before trusting the payload.
X-Aslio-Timestamp: 1769…
X-Aslio-Signature: 9f2c…
{ "type": "message.status",
"messageId": "cms4…",
"status": "DELIVERED",
"toAddress": "priya@example.com" }
// signature = HMAC_SHA256(secret, timestamp + "." + rawBody)Verify a domain
Add the domain, publish the three CNAME records returned, then poll the same resource until verified turns true. Verifying a domain covers every address on it.
POST /v1/senders
{ "type": "domain", "value": "acme.in" }
→ { "dnsRecords": [
{ "type": "CNAME", "name": "abc._domainkey.acme.in", "value": "abc.dkim.amazonses.com" }
] }
GET /v1/senders/{id} // poll until verifiedErrors and money
402 means the wallet is empty. 403 means the From address is not verified. A permanent provider failure refunds the charge automatically and releases the idempotency key so your retry can succeed.
400 Malformed request
401 Missing, invalid or revoked key
402 Wallet balance too low
403 Sender not verified for this account
429 Rate limit exceeded — retry shortlyReady to try it?
Create an account and your API key is waiting after you verify your email.
Create a free account