Rate limits and retries
How fast you can send, and how to retry without sending anything twice.
Messages per second#
Each account may send a set number of messages per second; ask us if you need more. Every message counts once, however many parts it has, and the limit is shared by everything your account sends: the API, the console and SMPP.
Over the limit, a send is refused with 429 rate_limited and nothing is charged. Wait a moment and send it again; spreading sends evenly over each second avoids it altogether.
A batch counts each of its messages, and waits its turn under the limit instead of refusing them, for up to 25 seconds.
async function send(message, key) {
for (let attempt = 0; ; attempt++) {
const res = await fetch("https://api.siellabs.com/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SMSGW_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": key, // the same key on every attempt
},
body: JSON.stringify(message),
}).catch(() => null); // a network error: retry
if (res && res.status < 500 && res.status !== 429) return res.json();
if (attempt === 5) throw new Error("gave up");
await new Promise((r) => setTimeout(r, 250 * 2 ** attempt)); // 0.25 s, 0.5 s, 1 s…
}
}Idempotency#
A timeout doesn't tell you whether a message was accepted. Send an Idempotency-Key header, unique to each message you mean to send, and use the same key on every retry of it:
- The first request sends the message and answers
201. - A repeat with the same key,
to,fromandbodysends nothing, charges nothing, and answers200with the original message, whatever became of it since. - The same key with a different
to,fromorbodyis refused with409 idempotency_key_reused.
Keys are per account, up to 255 bytes, and last as long as the message is kept. Build them from what makes the message unique in your system: order-4821-shipped, signin-7f3a-attempt-2.
Retry only errors that may pass: network errors, 429 and 5xx. A 4xx such as 422 or 402 will fail the same way until you change something.