5 minute setup

Quickstart

Create an API key, send your first Algerian SMS, and handle the accepted response.

Before you start

Submit a message template in Dashboard → Templates first. Include every language you will send and use {{placeholder}} names for runtime values. An administrator must accept the complete multilingual submission before either the test or production Messages API can use it.

Then start in the dashboard's Test environment and create a test API key with the sms:send and sms:read scopes. Test keys work only with /v1/test/* endpoints and never send or charge.

Keep the key in a server-side secret store. Never embed it in browser code, a mobile app, a public repository, or a client-visible environment variable.

Choose API-key scopes

Bar9 accepts only the scopes below when a key is created. Any other value is rejected with 400 validation_error and no key is saved.

Scope Allows
sms:send Send one SMS.
sms:send:bulk Send SMS batches.
sms:read List and retrieve messages.
otp:create Create OTP sessions.
otp:read Retrieve OTP session state.
stats:read Read account statistics.
marketing:audiences:read List audiences and members.
marketing:audiences:write Manage audiences and members.
marketing:campaigns:read List campaigns and delivery results.
marketing:campaigns:write Submit campaigns for review.
templates:read List template submissions and decisions.
templates:write Submit and update templates for review.
sender-ids:read List SenderID applications and decisions.
sender-ids:write Submit SenderID applications for review.

If scopes are omitted, a key receives sms:send, sms:read, otp:create, and otp:read. Management permissions are never granted by default; select them explicitly using least privilege. Campaign and SenderID permissions require a production key, while audience and template permissions work with either key environment. Code verification remains a public end-user operation and has no API-key scope.

Send your first test SMS

Use the test key for an executable first request. Sandbox messages apply production validation and require an accepted template, but they never contact a provider or debit credit.

export BAR9_API_KEY="bar9_your_test_key"

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": "Amine" }
  }'

The API returns 202 Accepted with an ID beginning with test_msg_, status: "delivered", and cost_credits: 0. Retrieve that exact record to verify your read permission and response handling:

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

Test and production histories are isolated. Continue with the Test API Sandbox reference for bulk sends and test OTP sessions.

Promote the request to production

After production verification is approved, create a production key with sms:send and sms:read, replace the test key, and use the live path shown below.

Bar9 accepts Algerian mobile numbers in local or E.164 form. E.164 is recommended at integration boundaries.

export BAR9_API_KEY="bar9_your_key"

curl https://api.bar9.dev/v1/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": "Amine" }
  }'

The API returns 202 Accepted after the message is validated, charged, and queued. Accepted does not mean delivered; retain the message id and follow its status.

{
	"ok": true,
	"data": {
		"id": "msg_...",
		"to": "+213555000000",
		"status": "queued",
		"segments": 1,
		"cost_credits": 5
	}
}

Read the latest delivery state with the same production key:

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

The status progresses from queued to sent, then reaches delivered or failed. For production systems, configure a DLR webhook instead of frequent polling.

Use Bar9 from a server

const response = await fetch('https://api.bar9.dev/v1/messages', {
	method: 'POST',
	headers: {
		Authorization: `Bearer ${process.env.BAR9_API_KEY}`,
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({
		to: '+213555000000',
		template_id: 'tpl_your_accepted_template',
		language: 'fr',
		variables: { name: 'Amine' }
	})
});

const result = await response.json();
if (!response.ok) {
	throw new Error(result.error?.message ?? 'Bar9 rejected the message');
}

console.log(result.data.id, result.data.status);

API errors use { "ok": false, "error": { "code": "...", "message": "..." } }. A request sent to an existing path with an unsupported HTTP method returns HTTP 405 with error.code: "method_not_allowed".

Next steps

Production checklist

  • Request production verification in the dashboard and wait for approval before creating live credentials.
  • Submit all message language variants and wait for template approval before integrating their IDs.
  • Restrict each API key to the scopes its service needs and rotate exposed keys immediately.
  • Validate and normalize phone numbers before submitting them.
  • Add application-level rate limits and abuse controls before any endpoint that sends SMS.
  • Treat 202 Accepted as queued, not delivered, and handle terminal delivered and failed states.
  • Log Bar9 message or OTP session IDs, but do not log API keys or OTP codes.