aslio.

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 verified

Errors 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 shortly

Ready to try it?

Create an account and your API key is waiting after you verify your email.

Create a free account