Skip to content
Menu

Your first integration

Getting started

Send a test message, check its delivery, and connect your first webhook. Once you have workspace access, the first sandbox send takes just a few minutes.

1. Get your sandbox key

  1. Follow your beta invitation to create your business workspace with your work email, then confirm your email address.
  2. Copy the sandbox key shown when you first sign in. It starts with sg_test_ and is shown only once. To create another, open API keys in the portal and select the correct project and sandbox environment.
Set your sandbox key · Bash / Zsh
# Replace the placeholder with your sandbox key. Keep it on your server.
export SWITCHGEAR_KEY='your_sandbox_api_key'

2. Send your first message

Send a JSON request with your key in the Authorization header. Use a phone number in E.164 format, including the country code, such as +260971234567.

Send a sandbox SMS · curl
curl -i https://sandbox.switchgear.app/v1/messages \
  -H "Authorization: Bearer $SWITCHGEAR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d0f3c2e-8a51-4b6e-9c1d-2f4a6b8c0e13" \
  -d '{"channel": "sms", "to": "+260971234567", "body": "Your order A-17 is on its way."}'

A successful send returns 202 Accepted and a message id. This example shows the relevant fields:

202 Accepted · response excerpt
HTTP/1.1 202 Accepted

{
  "id": "0199f7a2-5c1e-7b3d-9a40-6e2f1c8d4b57",
  "channel": "sms",
  "status": "queued"
}

Copy the returned id into the command below to read the message and its events:

Check message status · curl
# Replace the placeholder with the id returned by your send request.
export SWITCHGEAR_MESSAGE_ID='your_message_id'

curl https://sandbox.switchgear.app/v1/messages/$SWITCHGEAR_MESSAGE_ID \
  -H "Authorization: Bearer $SWITCHGEAR_KEY"

In sandbox, read the simulated delivery from the test inbox. If the result is initially empty, repeat this query after delivery completes:

Read the sandbox inbox · curl
curl https://sandbox.switchgear.app/v1/sandbox/inbox/query \
  -H "Authorization: Bearer $SWITCHGEAR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+260971234567", "limit": 1}'

Match the inbox result’s message_id to the id from your send response. You should see the message body. You can also use this endpoint to read one-time codes in automated tests.

3. Use the TypeScript SDK (optional)

@brivo/switchgear provides typed requests and responses, generates idempotency keys, and verifies webhooks. The package is currently private: request access through your Switchgear contact before using this example. You can use curl or any HTTP client without SDK access.

Send and wait for simulated delivery · TypeScript
import { createClient } from '@brivo/switchgear';

const switchgear = createClient({
  apiKey: process.env.SWITCHGEAR_KEY!,
  baseUrl: 'https://sandbox.switchgear.app',
});

const since = new Date();
const message = await switchgear.messages.send({
  channel: 'sms',
  to: '+260971234567',
  body: 'Your order A-17 is on its way.',
});
console.log(message.id, message.status); // "queued"

// Sandbox only: read what the simulator delivered, as the phone would have.
const delivered = await switchgear.sandbox.waitForMessage('+260971234567', { since });
console.log(delivered.body);

4. Receive webhooks

Switchgear tells your server what happened (message.delivered, message.failed, otp.verified, verification.completed, inbound.received and more) by POSTing signed JSON to your webhook endpoints.

  1. In the portal, open Webhooks, add your HTTPS URL and choose the events. The signing secret (whsec_…) is shown once: store it.
  2. Verify X-Switchgear-Signature against the raw request body before processing the event. Return a 2xx response promptly; failed or timed-out deliveries are retried with backoff for up to 24 hours.
  3. Deliveries can repeat, so skip an event.id you have already handled.
Verify a webhook · Express + TypeScript SDK
import express from 'express';
import { parseWebhook } from '@brivo/switchgear';

const app = express();

// Express: keep the raw body, the signature covers its exact bytes.
app.post('/switchgear', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = parseWebhook(process.env.SWITCHGEAR_WEBHOOK_SECRET!, req.body.toString('utf8'), req.header('X-Switchgear-Signature'));
  } catch {
    return res.status(401).end();
  }
  // Deliveries can repeat: skip an event.id you have already handled.
  // Example receipt only: persist or enqueue your work before acknowledging.
  console.log(event.type, event.id);
  res.status(204).end();
});

app.listen(3000);

In your handler, persist the event or enqueue the work before acknowledging it. Use event.id to make processing safe when deliveries repeat.

Verify without the SDK · Node.js

If you use a different HTTP client, this helper verifies the signature with Node’s built-in crypto module. Pass it the endpoint secret, raw body, and signature header.

HMAC signature verification · Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';

/** X-Switchgear-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>"> */
function verify(secret: string, rawBody: string, header: string | undefined, toleranceSeconds = 300): boolean {
  const parts = Object.fromEntries((header ?? '').split(',').map((p) => p.split('=') as [string, string]));
  const t = Number(parts.t);
  if (!parts.v1 || !Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  const given = Buffer.from(parts.v1, 'hex');
  return given.length === expected.length && timingSafeEqual(given, expected);
}

5. Prepare for production

  1. Submit your business verification documents in the portal and request production access for your project. Approval and channel activation are required before sending live traffic.
  2. Top up your wallet; live sends are charged from it at the prices on the pricing page.
  3. For SMS with your own name as the sender, request a sender ID under Sender IDs; for WhatsApp, save your templates so they go to Meta for review.
  4. Use your production key (sg_live_) with https://api.switchgear.app. Keep sandbox and production credentials separate; the request and response shapes stay the same.

Troubleshooting

Start with the HTTP status and the response’s error.code. Keep the X-Request-Id response header when contacting support.

401 · Authentication failed
Check that SWITCHGEAR_KEY is set, the bearer header is present, and the key is active and valid for the API host you’re calling.
403 · Missing scope or restricted access
Read error.code. For insufficient_scope, check the key’s scopes; sending needs messages:send, and status and inbox queries need messages:read. The sandbox inbox requires a sandbox key.
409 · Idempotency conflict
A retry must use the original key and body within 24 hours. Use a new key for a new send or after the replay window has expired.
429 · Rate limited
Follow Retry-After when it is present and slow down requests. Check the API essentials for limits and batch behaviour.
The sandbox inbox is empty
Delivery is asynchronous. Query again using the same destination and environment as your send. The TypeScript SDK’s sandbox.waitForMessage polls for you.
The message was accepted but failed later
Read the message’s events to find the failure. The SMS simulator deliberately fails destinations ending in 00; the example number above uses the success path.
Your first integration is ready to grow.

Explore individual endpoints or build an interactive service using the same workspace.