API key

Test API Sandbox

Exercise message and OTP integrations without sending SMS or spending credits.

POST
/v1/test/messages
Scope sms:send - Create a delivered test message.
POST
/v1/test/messages/bulk
Scope sms:send:bulk - Create 1 to 100 delivered test messages.
GET
/v1/test/messages
Scope sms:read - List test messages.
GET
/v1/test/messages/:message_id
Scope sms:read - Fetch one test message.
GET
/v1/test/messages/events
User session - List test message lifecycle events.
POST
/v1/test/otp/sessions
Scope otp:create - Create a test OTP session.
GET
/v1/test/otp/sessions/:id
Scope otp:read - Read a test OTP session.
POST
/v1/test/otp/sessions/:id/verify
None - Verify a test OTP code.

Overview

The test API accepts the same message and OTP request fields, validation rules, API-key scopes, response envelopes, pagination, and verification flow as the production endpoints. Create a key while the dashboard is switched to Test, then replace /v1 with /v1/test in the supported paths while developing your integration.

Test traffic is isolated from production traffic. It does not contact an SMS provider, enqueue a delivery job, create a credit-ledger entry, change your balance, appear in production message history, or contribute to production statistics and analytics.

POST /v1/test/messages

curl https://api.bar9.dev/v1/test/messages \
  -H "Authorization: Bearer $BAR9_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+213555000000",
    "template_id": "tpl_your_accepted_template",
    "language": "fr",
    "variables": { "name": "Test user" }
  }'

The response is 202 Accepted. Sandbox messages still require an accepted, account-owned template so integration behavior matches production. The message ID starts with test_msg_, status is delivered, and cost_credits is 0.

POST /v1/test/messages/bulk

Send the same messages array accepted by the production bulk endpoint. The request accepts 1 to 100 items and returns 202 Accepted with count and a messages array. Every returned ID begins with test_msg_; no credits are charged.

GET /v1/test/messages

List sandbox messages with page, per_page, status, type, and to, matching the production list endpoint:

curl "https://api.bar9.dev/v1/test/messages?page=1&per_page=25" \
  -H "Authorization: Bearer $BAR9_API_KEY"

The response uses the standard data and pagination list envelope.

GET /v1/test/messages/:message_id

Fetch one sandbox message with a test key that has sms:read:

curl https://api.bar9.dev/v1/test/messages/test_msg_123 \
  -H "Authorization: Bearer $BAR9_API_KEY"

A production message ID is not visible through this endpoint.

GET /v1/test/messages/events

List sandbox message lifecycle events with an authenticated dashboard session:

curl "https://api.bar9.dev/v1/test/messages/events?page=1&per_page=25&status=delivered" \
  --cookie "$BAR9_SESSION_COOKIE"

Supported filters are page, per_page, status, and event_type. Every sandbox event has event_type: "delivered"; the response includes the test message ID, status, timestamps, recipient, sender, type, and segment count. Production events are excluded.

The message endpoints map to production as follows:

Test path Production counterpart
POST /v1/test/messages POST /v1/messages
POST /v1/test/messages/bulk POST /v1/messages/bulk
GET /v1/test/messages GET /v1/messages
GET /v1/test/messages/:message_id GET /v1/messages/:message_id
GET /v1/test/messages/events GET /v1/messages/events

Production and test lists are separate. A test_msg_ ID is available only through the test retrieval endpoint.

POST /v1/test/otp/sessions

curl https://api.bar9.dev/v1/test/otp/sessions \
  -H "Authorization: Bearer $BAR9_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+213555000000",
    "template": "Your test code is {{code}}",
    "code_length": 6,
    "ttl_seconds": 300
  }'

The session ID starts with test_otp_. Creation returns the generated code, just like the production OTP API, and attaches a delivered test_msg_ record without sending it. Use the returned code against the public test verification endpoint:

GET /v1/test/otp/sessions/:id

Read the sandbox session with a test key that has otp:read:

curl https://api.bar9.dev/v1/test/otp/sessions/test_otp_123 \
  -H "Authorization: Bearer $BAR9_API_KEY"

The response omits the generated code and otherwise matches the production session representation.

POST /v1/test/otp/sessions/:id/verify

curl https://api.bar9.dev/v1/test/otp/sessions/test_otp_123/verify \
  -H "Content-Type: application/json" \
  -d '{ "code": "773421" }'

Incorrect, expired, and repeated verification attempts return API errors. Test OTP sessions never appear in production OTP analytics.

Common errors

Request validation and error envelopes match production. Test keys used on production endpoints—and production keys used on test endpoints—return 403. Unknown sandbox message or session IDs return 404.

Authentication scopes

Use a test-environment API key. Test keys are rejected by production endpoints, and production keys are rejected by test endpoints, even when their scopes match.

Operation Required scope
Create one message sms:send
Create bulk messages sms:send:bulk
List or get a message sms:read
Create an OTP session otp:create
Get an OTP session otp:read
Verify an OTP code Public