SendrinSendrin Docsv1.0 (Current)
Getting Started

API Quickstart

Configure email OTP and send and verify a code with cURL, Python, or Node.js using the Sendrin API.

Send and verify your first OTP

This guide uses Sendrin's dedicated OTP API to send a code by email and verify the code entered by its recipient. Choose one of the examples below; running every example sends multiple codes.

Prerequisites

  1. Create an application in the Sendrin Console and generate an application API key under Credentials. Save it as SENDRIN_API_KEY in your backend environment. Never expose the key in browser code.
  2. Add and verify a sending domain for your workspace. Follow Custom Sending Domains and the email setup in the OTP guide. OTP email uses the platform's email delivery configuration; it does not use a general notification event template.
  3. Confirm that your workspace has available OTP credits. Use an email address you control to receive the test code.
  4. These examples use the production base URL https://api.sendrin.com. Sending consumes quota and can incur delivery charges. See the API reference for endpoint details.

A send response includes otp_id, expires_at, and ttl_seconds. The code is sent to the recipient and is not returned by the API. Provider acceptance does not guarantee inbox placement.

cURL

Use cURL with --fail-with-body support. Replace [email protected] in both requests with your test recipient. Set SENDRIN_API_KEY before running them.

curl --fail-with-body --silent --show-error \
  --request POST 'https://api.sendrin.com/api/v1/otp/send' \
  --header "Authorization: Bearer $SENDRIN_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "channel": "email",
    "recipient_email": "[email protected]",
    "purpose": "login",
    "code_length": 6,
    "ttl_seconds": 300
  }'

After a successful send, enter the code from the email in place of 123456:

curl --fail-with-body --silent --show-error \
  --request POST 'https://api.sendrin.com/api/v1/otp/verify' \
  --header "Authorization: Bearer $SENDRIN_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "channel": "email",
    "recipient_email": "[email protected]",
    "purpose": "login",
    "code": "123456"
  }'

Check the response's verified boolean. A successful HTTP request alone does not mean the code is valid.

Python, using the standard library

Set SENDRIN_API_KEY and SENDRIN_RECIPIENT_EMAIL in your environment, save this as otp_example.py, and run it with Python 3. No Sendrin SDK package is required.

import json
import os
from urllib.error import HTTPError
from urllib.request import Request, urlopen

API_BASE = "https://api.sendrin.com"
API_KEY = os.environ["SENDRIN_API_KEY"]
RECIPIENT = os.environ["SENDRIN_RECIPIENT_EMAIL"]


def post(path, payload):
    request = Request(
        API_BASE + path,
        data=json.dumps(payload).encode("utf-8"),
        headers={
            "Authorization": "Bearer " + API_KEY,
            "Content-Type": "application/json",
        },
        method="POST",
    )
    try:
        with urlopen(request, timeout=30) as response:
            return json.load(response)
    except HTTPError as error:
        raise RuntimeError(
            f"Sendrin HTTP {error.code}: {error.read().decode('utf-8')}"
        ) from error


identity = {
    "channel": "email",
    "recipient_email": RECIPIENT,
    "purpose": "login",
}
sent = post("/api/v1/otp/send", {
    **identity,
    "code_length": 6,
    "ttl_seconds": 300,
})
print("Dispatched:", sent["otp_id"], "Expires:", sent["expires_at"])
code = input("Enter the code from your email: ").strip()
result = post("/api/v1/otp/verify", {**identity, "code": code})
if not result["verified"]:
    raise SystemExit("Verification failed: " + result["message"])
print("Verified successfully")

Node.js, using built-in fetch

Use Node.js 20 or later. Set SENDRIN_API_KEY and SENDRIN_RECIPIENT_EMAIL, save this as otp_example.mjs, and run node otp_example.mjs on your backend or development machine.

import { createInterface } from 'node:readline/promises';
import { stdin, stdout } from 'node:process';

const apiKey = process.env.SENDRIN_API_KEY;
const recipient = process.env.SENDRIN_RECIPIENT_EMAIL;
if (!apiKey || !recipient) {
  throw new Error('Set SENDRIN_API_KEY and SENDRIN_RECIPIENT_EMAIL');
}

async function post(path, payload) {
  const response = await fetch('https://api.sendrin.com' + path, {
    method: 'POST',
    headers: {
      Authorization: 'Bearer ' + apiKey,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
    signal: AbortSignal.timeout(30000),
  });
  const body = await response.text();
  if (!response.ok) {
    throw new Error('Sendrin HTTP ' + response.status + ': ' + body);
  }
  return JSON.parse(body);
}

const identity = {
  channel: 'email',
  recipient_email: recipient,
  purpose: 'login',
};
const sent = await post('/api/v1/otp/send', {
  ...identity,
  code_length: 6,
  ttl_seconds: 300,
});
console.log('Dispatched:', sent.otp_id, 'Expires:', sent.expires_at);
const prompt = createInterface({ input: stdin, output: stdout });
let code;
try {
  code = (await prompt.question('Enter the code from your email: ')).trim();
} finally {
  prompt.close();
}
const result = await post('/api/v1/otp/verify', { ...identity, code });
if (!result.verified) {
  throw new Error('Verification failed: ' + result.message);
}
console.log('Verified successfully');

Handle the result in your application

Keep the recipient, channel, and purpose consistent between send and verify. Generated codes can be 4–8 digits and expiry can be 60–3600 seconds. Custom codes have a separate format and require otp:custom_code; they are not needed for this example.

Only advance your application's authenticated flow after the server receives verified: true. Keep the pending verification identity in trusted server state. A successful verification invalidates the code, so it cannot be used for another verification.

For rate-limit responses (429), wait before offering resend and show the user an appropriate cooldown. For exhausted credits (402), check billing and quotas. For validation failures (422), inspect the request fields. Do not automatically loop sends after a timeout: the provider may already have accepted the message. Consult the OTP guide for resend behavior and channel-specific prerequisites.

Next steps

  • OTP service: SMS and WhatsApp setup, resend, and verification responses.
  • API reference: Full request and response schemas.
  • Platform overview: Event templates and provider setup for general notifications.

On this page