Developers
Ship OTPs in minutes
Sneek delivers OTPs and transactional messages over SMS, WhatsApp, and email through pre-approved DLT senders, a verified WhatsApp BSP number, and a warmed email domain. You generate and verify the code; Sneek handles the regulated delivery plumbing.
1. Get an API key
Create an organization and application in the Sneek console, then open Applications → API keys. Keys are shown once. snk_test_… keys hit dev adapters (no real delivery); snk_live_… keys deliver for real. Send every request with Authorization: Bearer <key>.
2. Send a message (curl)
One endpoint, POST /api/messages/send. Set type to "otp" or "transactional" so Sneek selects the correct approved provider template.
curl -X POST https://api.sneek.in/api/messages/send \
-H "Authorization: Bearer $SNEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"channel": "auto",
"type": "otp",
"body": "Your code to login to ConfHub is 482917. Do not share it."
}'Prefer server-rendered DLT templates? Pass template + variables instead of body:
curl -X POST https://api.sneek.in/api/messages/send \
-H "Authorization: Bearer $SNEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"channel": "sms",
"type": "otp",
"template": "otp_login",
"variables": { "appName": "ConfHub", "otp": "482917" }
}'3. Or use the Node SDK
npm install @sneekin/sdkimport { Sneek } from '@sneekin/sdk';
const sneek = new Sneek({ apiKey: process.env.SNEEK_API_KEY! });
// OTP intent -> uses the approved auth template
await sneek.messages.send({
to: '+919876543210',
channel: 'auto',
type: 'otp',
body: 'Your code is 482917',
});
// Communication intent -> uses the utility template
await sneek.messages.send({
to: '+919876543210',
type: 'transactional',
body: 'Your booking BK-7781 is confirmed.',
});The SDK retries transient 5xx/network failures and throws SneekApiError with RFC-7807 problem details on other errors.
4. Drop-in login UI for React
@sneekin/ui renders the whole passwordless flow — enter email/mobile → enter code → signed in.
npm install @sneekin/uiimport { SneekOtpLogin, createFetchHandlers } from '@sneekin/ui';
export function LoginPage() {
return (
<SneekOtpLogin
title="Sign in to ConfHub"
{...createFetchHandlers({
requestUrl: '/api/auth/request-otp',
verifyUrl: '/api/auth/verify-otp',
})}
onSuccess={() => (window.location.href = '/dashboard')}
/>
);
}// POST /api/auth/request-otp (your server, secret key stays here)
import { Sneek } from '@sneekin/sdk';
const sneek = new Sneek({ apiKey: process.env.SNEEK_API_KEY! });
const result = await sneek.sendOTP({
to: identifier,
code: generateAndStoreCode(identifier), // you own the code + verification
appName: 'ConfHub',
channel: 'auto',
});
return { requestId: result.id, channels: [result.channel], expiresInSeconds: 300 };Errors
Non-2xx responses return RFC-7807 problem details:
{
"type": "https://sneek.in/errors/unauthorized",
"title": "Invalid API key",
"status": 401,
"detail": "The provided bearer token was rejected."
}Rate limits & idempotency
- Sends are rate-limited per application (your plan's per-minute and per-day quota), per recipient, and per source IP. Exceeding a limit returns 429 with a retry_after (seconds) in the problem body.
- Send an Idempotency-Key header to make retries safe: the first request is processed and its result is replayed for any repeat with the same key, so a dropped connection never sends twice. A retry that arrives mid-flight gets 409.
curl -X POST https://api.sneek.in/api/messages/send \
-H "Authorization: Bearer $SNEEK_API_KEY" \
-H "Idempotency-Key: order-4815-otp" \
-H "Content-Type: application/json" \
-d '{ "to": "+919876543210", "type": "otp", "body": "Your code is 482917" }'The Node SDK exposes it directly and pairs it with automatic 5xx retries:
await sneek.messages.send({
to: '+919876543210',
type: 'otp',
body: 'Your code is 482917',
idempotencyKey: 'order-4815-otp', // same key -> delivered once
});Channels & intent
- channel: auto (email → email; mobile → WhatsApp then SMS fallback), or pin to sms / whatsapp / email.
- type: otp for auth codes, transactional for communications. Omitting it lets Sneek infer intent from the body, which can misclassify digit groups — pass it explicitly.
- Message wording is governed by Sneek's pre-approved templates; only your App Name and the code vary.
Need help? Email support@sneek.in.