Send an SMS from your code for 2 cents.
TextRail is an SMS API for OTP codes, alerts and reminders, in a few lines of code. One flat price for every country, and you pay only for what goes out. Top up from $10. No subscription.
Test keys are free. No card needed.
Sample recipient: To +1 416 555 0123
40 of 160
Fits in one text. 2 cents.
curl https://textrail.devflovv.com/api/v1/sms \
-H "Authorization: Bearer $TEXTRAIL_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+14165550123",
"message": "Your table for two is ready. Come on in."
}'const response = await fetch('https://textrail.devflovv.com/api/v1/sms', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TEXTRAIL_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
phoneNumber: '+14165550123',
message: 'Your table for two is ready. Come on in.',
}),
});
const result = await response.json();
console.log(result.id, result.status);Nothing is sent from this page. Run the request with your own key.
OTP codes take two calls.
Ask for a code and TextRail makes one and texts it. Send back what your user typed and get a yes or a no. Codes have 6 digits, last 5 minutes and allow 5 tries.
A code costs 2 cents like any other text, and checking it is free. How it works
curl https://textrail.devflovv.com/api/v1/otp/send \
-H "Authorization: Bearer $TEXTRAIL_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+14165550123",
"purpose": "login"
}'const response = await fetch('https://textrail.devflovv.com/api/v1/otp/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TEXTRAIL_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
phoneNumber: '+14165550123',
purpose: 'login',
}),
});
const result = await response.json();
// Keep this to check the code later.
console.log(result.requestId);curl https://textrail.devflovv.com/api/v1/otp/verify \
-H "Authorization: Bearer $TEXTRAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"requestId": "otp_01KA7QX8C2HF6TN3PV9WD4MK7S",
"code": "482913"
}'const response = await fetch('https://textrail.devflovv.com/api/v1/otp/verify', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TEXTRAIL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
requestId: 'otp_01KA7QX8C2HF6TN3PV9WD4MK7S',
code: '482913',
}),
});
const result = await response.json();
console.log(result.verified);You pay only for what goes out.
Every text reports where it is, so your code never has to guess. If a text doesn’t go out, it costs nothing.
- Queued
Accepted. 2 cents is held from your balance.
- Sending
On its way out.
- Sent
Sent to the carrier. The 2 cents is charged.
- Delivered
The carrier reported that it arrived.
Any other ending isn’t charged. The hold goes back to your balance.
- Failed
It did not go out.
- Expired
It could not go out in time.
- Unknown
We could not confirm it, so it is not resent.
A bill you can predict.
One price, everywhere: every text costs 2 cents, whichever country it goes to.
Example bill
- 1,000 texts at 2 cents
- $20
- Texts that didn’t go out
- $0
- Setup and monthly fees
- $0
- Total
- $20
One text, one price
A long text can’t grow into a bigger bill. One that doesn’t fit comes back with a clear error and costs nothing.
You can’t overspend
You top up first, from $10, so there’s no surprise bill. At zero, new texts return a clear error until you top up.
Built for one-way texts
Codes, alerts and reminders. If people need to text you back, TextRail isn’t the right tool.
Build it free with a test key.
Test keys run the whole API with no real text and no charge. When it works, top up from $10 and send real texts.
No card needed.