# Aureus Prime Documentation — Aureus Desk SMS API (full text) Source: https://docs.aureusprime.com/en API base URL: https://api.getaureusdesk.com/v1 --- # Aureus Desk SMS API Send **transactional SMS** — sign-in codes, order confirmations, reminders, alerts — to mobiles in **open countries** — **Cameroon** today (MTN and Orange), with more countries to follow — through a simple REST API. You can be based anywhere: it is the recipients who must be in an open country. You pay by top-up, with credits that never expire, and you track every delivery. > **Get started in 5 minutes:** [create your account and your API key](https://docs.aureusprime.com/en/documentation/sms/compte-et-cle), then send your first SMS with the [quick start](https://docs.aureusprime.com/en/documentation/sms/demarrage). ## What you can do | | | |---|---| | **[Send an SMS](https://docs.aureusprime.com/en/documentation/sms/envoyer)** | One call, one SMS of 160 characters. Text automatically converted to the SMS alphabet. Longer message: sent as 2 SMS, in guaranteed order. | | **[Schedule an SMS](https://docs.aureusprime.com/en/documentation/sms/planifier)** | Choose the sending date up to 30 days ahead; cancel it and the credits come back. | | **[Track delivery](https://docs.aureusprime.com/en/documentation/sms/suivre)** | Queued, sent, delivered or failed, with the reason. A rejection gives the credits back. | | **[Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs)** | 1 credit = 1 FCFA; each SMS costs the price of its destination country (25 credits in Cameroon). | | **[Your sender name](https://docs.aureusprime.com/en/documentation/sms/expediteurs)** | A shared name right away, or your own for an organisation. | | **[Integrate with an AI assistant](https://docs.aureusprime.com/en/integration-ia/sms/assistants-ia)** | A ready-to-paste `AGENTS.md` so that your coding assistant uses the API correctly. | ## Useful links - **Account area:** https://dashboard.getaureusdesk.com — your API keys, your messages, your top-ups. - **[API reference](https://docs.aureusprime.com/en/reference/sms/routes)** — every public route. - **[Errors](https://docs.aureusprime.com/en/reference/sms/erreurs)** — stable codes and what to do. - **Full text for agents:** https://docs.aureusprime.com/en/llms-full.txt --- # Create an account and get an API key ## 1. Sign in Open the Aureus Desk account area (https://dashboard.getaureusdesk.com) and sign in with your **Aureus Prime account** (email and password, Google or Facebook): a single sign-in for all Aureus services. The account area opens on your personal account. ## 2. Have your account verified To send SMS to other people, you need: - **individual:** your identity verified (KYC); - **organisation:** your business verified (KYB). Verification takes place in your Aureus Prime account. Until it is done, sending to a third party returns `403 VERIFICATION_REQUIRED`. **Before verification**, only one kind of sending is allowed: the **test SMS to your own number**, if it is verified in your Aureus Prime account and is a mobile in an open country. This way you see the SMS arrive before having your account verified. **Based abroad?** You can open an account and send to mobiles in open countries. If your own number is not in an open country, it cannot receive a test SMS: have your identity or business verified straight away. ## 3. Top up A top-up is made **in FCFA, from 10,000**: 1 credit = 1 FCFA, with bonus credits on large top-ups (see [Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs)). During the pilot, you request the top-up from the account area, then pay by MTN Mobile Money, Orange Money, cash against a receipt, or through the online payment link we attach to your request (handy from abroad). The credits are added as soon as the payment is received. ## 4. Create an API key In the **API keys** section of the account area: 1. give the key a name (for example "Website"); 2. copy the key shown — it starts with `adk_sms_` and **will never be shown again**; 3. store it in your server's environment variables, for example `AUREUS_SMS_API_KEY`. You can have **2 active keys** at most: the second one lets you change keys without downtime (see [Authentication](https://docs.aureusprime.com/en/reference/sms/authentification)). ## Next Send your first SMS with the [quick start](https://docs.aureusprime.com/en/documentation/sms/demarrage). --- # Quick start The Aureus Desk SMS API sends **transactional SMS** (sign-in codes, confirmations, reminders, alerts) to mobiles in open countries (**Cameroon** today: MTN and Orange), immediately or on a scheduled date. You pay with credits: **1 credit = 1 FCFA**, and each SMS costs the price of its destination country (**25 credits** in Cameroon, listed by `GET /sms/coverage`). ## 1. Open an account and have it verified Sign in to the Aureus Desk account area (https://dashboard.getaureusdesk.com) with your Aureus Prime account. To send to other people, your identity (individual) or your business (organisation) must be verified in your Aureus Prime account. Before that, you can send yourself a test SMS on your own verified number (see [Create an account](https://docs.aureusprime.com/en/documentation/sms/compte-et-cle)). ## 2. Create an API key In the account area, under **API keys**, create a key. It starts with `adk_sms_` and is shown **only once**: copy it into your server configuration. You can have **2 active keys** at most. ## 3. Send your first SMS ```bash curl -X POST https://api.getaureusdesk.com/v1/sms/messages \ -H "Authorization: Bearer adk_sms_YOUR_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: first-test-1" \ -d '{"to": "699123456", "text": "Your code is 482913", "sensitive": true}' ``` `202` response: the SMS is queued and its credits are reserved. ```json { "id": "5b0f2c1e-8a4d-4f7e-9c3a-1d2b3c4d5e6f", "status": "QUEUED", "to": "+237*******56", "operator": "ORANGE", "countryIso": "CM", "priceCredits": 25, "senderId": "Aureus Desk", "errorCode": null, "groupId": null, "part": null, "scheduledAt": null, "createdAt": "2026-11-02T10:00:00.000Z", "sentAt": null, "deliveredAt": null, "likelyUndelivered": false, "normalized": false, "smsCount": 1, "totalCredits": 25 } ``` Then track its delivery with `GET /sms/messages/:id` (see [Track an SMS](https://docs.aureusprime.com/en/documentation/sms/suivre)). ## Key points - **API base URL:** `https://api.getaureusdesk.com/v1` - **Format:** JSON in and out, UTF-8. - **Text:** 160 characters per SMS, in the SMS alphabet (current rule, for all destinations). The text is **always converted**: ê becomes e, ç becomes Ç, the curly apostrophe becomes straight; é, è, à, ù stay as they are; emoji and non-Latin scripts are removed. A longer message is sent as 2 SMS if you ask for it (`allowTwoParts`); otherwise it is rejected, never cut without your knowledge. - **Numbers:** mobiles in open countries (Cameroon today); numbers are always masked in responses. - **Errors:** always the same shape, `{"error": {"code", "message"}}` (see [Errors](https://docs.aureusprime.com/en/reference/sms/erreurs)). --- # Send an SMS ```http POST https://api.getaureusdesk.com/v1/sms/messages ``` Queues an SMS. `202` response. Its price in credits, that of the destination country (25 in Cameroon, see `GET /sms/coverage`), is reserved immediately: consumed if the SMS is sent, given back if it is rejected before sending. ## Request body | Field | Type | Required | Description | |---|---|---|---| | `to` | string | yes | Mobile in an open country, in international format (`+237699123456`, `00237…`, `237…`) or local format (`699123456`, read as Cameroonian) | | `text` | string | yes | SMS text, 160 characters (see below) | | `allowTwoParts` | boolean | no | `true`: a text too long for one SMS is sent as **2 SMS** (see below) | | `senderId` | string | no | Approved sender of your account; the shared sender by default | | `sensitive` | boolean | no | `true` for a code or a secret: text erased as soon as it is sent, never stored | | `scheduledAt` | string | no | Scheduled sending (see [Schedule an SMS](https://docs.aureusprime.com/en/documentation/sms/planifier)) | ## Text: 160 characters, always in the SMS alphabet Today, for all destinations, SMS are sent in the **GSM alphabet**, the one every phone displays. Your text is **always converted** to it, even when short: | What you write | What is sent | |---|---| | é è à ù ì ò É Ç ä ö ü ñ, unaccented letters, digits, common punctuation | as is | | ê î ô û â ë ï, lowercase ç | e i o u a e i, Ç | | other accented letter (ş, ã…) | the letter without its accent | | ’ ‘ « » “ ” – — … n° | ' ' " " " " - - ... no | | emoji, non-Latin script | removed | `€ [ ] { } ^ ~ | \` are accepted but count as 2. The response shows `"normalized": true` when the text was converted. A text emptied by the conversion (only emoji, for example) is rejected: `422 TEXT_INVALID`. ## Long message: 2 SMS (`allowTwoParts`) Beyond 160 characters, the request is rejected (`422 TEXT_TWO_PARTS_REQUIRED`), never cut without your knowledge. With `"allowTwoParts": true`: - the text (about **310 characters** at most) is split between two words into 2 SMS of 159 characters at most, prefixed "1/2" and "2/2"; - it is billed **per part**: twice the country price (50 credits in Cameroon); - **the order is guaranteed**: part 2 is only sent once part 1 has been **delivered**. If delivery of part 1 is not confirmed within 15 minutes, part 2 is cancelled and its credits given back (`errorCode`: `PART1_NOT_DELIVERED`); - free credits cannot be used for 2-SMS messages; - longer than 2 SMS: `422 TEXT_TWO_PARTS_MAX`. The response then gives `smsCount: 2`, `totalCredits` and `parts`, the list of both parts (`part`: `"1/2"` and `"2/2"`, same `groupId`). `id` is the one of part 1. Cancelling a scheduled message cancels both of its parts. ## Optional header: `Idempotency-Key` Send the same key (100 visible characters at most) to replay a request without a new debit: the response returns the same message, with `"replayed": true`. If the same key is used for another number or another sender: `409 IDEMPOTENCY_CONFLICT`. See [Best practices](https://docs.aureusprime.com/en/documentation/sms/bonnes-pratiques). ## Example ```bash curl -X POST https://api.getaureusdesk.com/v1/sms/messages \ -H "Authorization: Bearer adk_sms_YOUR_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-4821" \ -d '{"to": "677000222", "text": "Order no 4821 confirmed. Delivery tomorrow.", "sensitive": false}' ``` ```js const response = await fetch("https://api.getaureusdesk.com/v1/sms/messages", { method: "POST", headers: { Authorization: `Bearer ${process.env.AUREUS_SMS_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "order-4821", }, body: JSON.stringify({ to: "677000222", text: "Order no 4821 confirmed." }), }); const message = await response.json(); ``` ## Response ```json { "id": "5b0f2c1e-8a4d-4f7e-9c3a-1d2b3c4d5e6f", "status": "QUEUED", "to": "+237*******22", "operator": "MTN", "countryIso": "CM", "priceCredits": 25, "senderId": "Aureus Desk", "errorCode": null, "groupId": null, "part": null, "scheduledAt": null, "createdAt": "2026-11-02T10:00:00.000Z", "sentAt": null, "deliveredAt": null, "likelyUndelivered": false, "normalized": false, "smsCount": 1, "totalCredits": 25 } ``` `likelyUndelivered: true`: the number belongs to a network we do not serve today (in Cameroon: Camtel, Nextel). The SMS is attempted; if it is rejected, the credits are given back. ## Credits used If you have **free credits** (promotional offer), they are used first, then your purchased credits (see [Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs)). ## Rejections before queuing (no debit) | Code | Case | |---|---| | `422 PHONE_INVALID` | Malformed number | | `422 PHONE_NOT_COVERED` | Country not open, or landline number | | `422 TEXT_INVALID` | Empty text, text with control characters, or text emptied by the conversion | | `422 TEXT_TWO_PARTS_REQUIRED` / `TEXT_TWO_PARTS_MAX` | Longer than one SMS without `allowTwoParts`, or longer than 2 SMS | | `422 SENDER_INVALID` / `SENDER_NOT_APPROVED` / `SENDER_NOT_ALLOWED` | Sender in the wrong format, not approved yet, or reserved for organisations | | `422 SCHEDULE_INVALID` | Invalid `scheduledAt` | | `402 INSUFFICIENT_CREDITS` | Not enough credits for this SMS (or these 2 SMS) | | `403 VERIFICATION_REQUIRED` | Identity or business not verified yet, and recipient other than your own verified number | --- # Schedule an SMS Add `scheduledAt` to the request to choose the sending date and time, **up to 30 days ahead**. ```bash curl -X POST https://api.getaureusdesk.com/v1/sms/messages \ -H "Authorization: Bearer adk_sms_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"to": "699123456", "text": "Reminder: your appointment is tomorrow at 10 am.", "scheduledAt": "2026-11-02T08:00:00+01:00"}' ``` ## Rules - **Format:** ISO 8601 date **with a time zone**: `2026-11-02T08:00:00+01:00` (Cameroon time) or `2026-11-02T07:00:00Z`. Without a time zone: rejected. - **In the future**, and **30 days at most** after the call. Otherwise: `422 SCHEDULE_INVALID`. - **Credits reserved as soon as the SMS is scheduled.** - The SMS stays in `QUEUED` status until its date, then goes out like the others. The response and `GET /sms/messages/:id` return `scheduledAt`. - A 2-SMS message (`allowTwoParts`) can be scheduled: part 1 goes out on the chosen date, part 2 after it is delivered. ## Cancel a scheduled SMS ```http DELETE https://api.getaureusdesk.com/v1/sms/messages/:id ``` As long as the SMS has not gone out, it moves to `CANCELLED` and **its credits are given back to you**. For a 2-SMS message, the cancellation covers both parts. `200` response with the state of the message. | Code | Case | |---|---| | `409 NOT_CANCELLABLE` | The SMS was not scheduled, or it has already gone out | | `404 NOT_FOUND` | The message does not belong to your account | ## Tip For a one-time code, do not use scheduling: send it right away with `"sensitive": true`. --- # Track an SMS ```http GET https://api.getaureusdesk.com/v1/sms/messages/:id ``` Returns the state of a message of your account, as a [message object](https://docs.aureusprime.com/en/reference/sms/routes). The text is never returned and the number is masked. ## Statuses | `status` | Meaning | |---|---| | `QUEUED` | Queued, credits reserved. A scheduled SMS stays here until its date; part 2 of a 2-SMS message stays here until part 1 is delivered | | `SENDING` | Being sent | | `SENT` | Accepted by the operator; delivery receipt awaited (tracked for 72 h) | | `DELIVERED` | Received by the phone | | `FAILED` | Failed; `errorCode` gives the reason ([list](https://docs.aureusprime.com/en/reference/sms/erreurs)). Credits given back if the SMS was not sent | | `CANCELLED` | Scheduled SMS cancelled by you (credits given back), or cancelled by the operator | `DELIVERED`, `FAILED` and `CANCELLED` are final. ## 2-SMS message Each part is a separate message, with its own `id`, its own status and `part` (`"1/2"` or `"2/2"`), linked by the same `groupId`. The send request returns both in `parts`. Part 2 is only sent after part 1 has been delivered. If that delivery is not confirmed within 15 minutes, part 2 ends in `FAILED` with `PART1_NOT_DELIVERED`, and its credits are given back: the message is then **partial**. ## Recommended polling pace Poll shortly after sending, then less and less often: a few seconds, one minute, a few minutes. An SMS still `SENT` without a delivery receipt after 72 h is no longer tracked. --- # Balance and top-ups ## Credits - **1 credit = 1 FCFA** paid at top-up. - Each SMS uses the **price of its destination country**, given by `GET /sms/coverage`: **25 credits** to a mobile in Cameroon today. A 2-SMS message uses twice as much. Prices for the countries that open will be announced here and in this route. - Purchased credits **never expire**. - Prices are net, without VAT. ## Balance ```http GET https://api.getaureusdesk.com/v1/sms/balance ``` ```json { "balance": 12500, "low": false, "promoBalance": 225, "promoExpiresAt": "2026-12-02T10:00:00.000Z" } ``` | Field | Description | |---|---| | `balance` | Purchased credits | | `low` | `true` below 10% of your last top-up or below 1,250 credits | | `promoBalance` | Free credits (promotional offer) still valid; 0 otherwise | | `promoExpiresAt` | End of validity of the free credits; `null` otherwise | **Free credits:** they are separate from purchased credits, are used **first**, are valid for 30 days and then expire, and are neither refundable nor transferable. They are used for single SMS (not for 2-SMS messages), within a limit of 50 recipients per day. ## Price per country ```http GET https://api.getaureusdesk.com/v1/sms/coverage ``` ```json { "countries": [{ "iso": "CM", "name": "Cameroun", "priceCredits": 25, "operators": [{ "name": "MTN", "status": "open" }, { "name": "ORANGE", "status": "open" }] }] } ``` This list is authoritative: each open country, the price in credits of an SMS to that country, and the state of each network (`open`, `paused`, `closed`; for information only: sending to a closed network is attempted, and its credits are given back if it is rejected). Read it rather than hard-coding a price. ## Price grid and top-up bonus ```http GET https://api.getaureusdesk.com/v1/sms/price-tiers ``` ```json [ { "minQuantity": 100, "unitPriceXaf": 25 }, { "minQuantity": 501, "unitPriceXaf": 24 }, { "minQuantity": 1001, "unitPriceXaf": 23 }, { "minQuantity": 5001, "unitPriceXaf": 22 }, { "minQuantity": 10001, "unitPriceXaf": 21 }, { "minQuantity": 50001, "unitPriceXaf": 20 } ] ``` A top-up is made **in FCFA, from 10,000**. The larger it is, the more credits you receive: the amount reaches a tier of the grid, and **credits received = amount × 25 ÷ tier price**, rounded down to the credit. With the initial grid: | Top-up | Tier reached | Credits received | Bonus | That is, in Cameroon | |---|---|---|---|---| | 10,000 FCFA | 25 | 10,000 | — | 400 SMS | | 20,000 FCFA | 24 | 20,833 | + 833 | 833 SMS | | 50,000 FCFA | 23 | 54,347 | + 4,347 | 2,173 SMS | | 100,000 FCFA | 23 | 108,695 | + 8,695 | 4,347 SMS | | 200,000 FCFA | 22 | 227,272 | + 27,272 | 9,090 SMS | The bonus applied is the one in the scale at the time of purchase. Beyond the equivalent of 100,000 SMS: on quotation. ## Topping up During the pilot, you request a top-up from the account area (https://dashboard.getaureusdesk.com): the number of credits is calculated and fixed when you make the request. You then pay by **MTN Mobile Money**, **Orange Money**, **cash against a receipt**, or through the **online payment link** we attach to your request ("Pay online" button, handy from abroad). The credits are added as soon as the payment is received. Integrated online payment will come with Aureus Gate. --- # Senders The sender is the name displayed on your customers' phones. - **Shared sender:** "Aureus Desk", used by default, available right away for every account. - **Own sender:** reserved for **organisations**. A name of 2 to 11 letters, digits or single spaces, usable after approval by the operator (a few days). **A single custom name per account**: under review or approved. ## List your senders ```http GET https://api.getaureusdesk.com/v1/sms/senders ``` ```json [{ "id": "…", "name": "BOUTIQUEX", "status": "REJECTED", "rejectionReason": "Name already used by another brand.", "createdAt": "2026-11-01T10:00:00.000Z", "updatedAt": "2026-11-03T09:00:00.000Z" }] ``` `status`: `PENDING` (under review), `APPROVED` (usable) or `REJECTED`. A rejection carries its reason in `rejectionReason` and frees the slot for another name. ## Request a sender ```http POST https://api.getaureusdesk.com/v1/sms/senders ``` ```json { "name": "BOUTIQUEX" } ``` `201` response with `PENDING` status. Then send with `"senderId": "BOUTIQUEX"` once the name is approved; before that, sending is rejected (`422 SENDER_NOT_APPROVED`). | Code | Case | |---|---| | `422 SENDER_INVALID` | Name in the wrong format | | `422 SENDER_NOT_ALLOWED` | Individual account | | `409 SENDER_LIMIT_REACHED` | A name is already under review or approved on your account (`details.current`, `details.status`) | | `409 SENDER_NAME_REFUSED` | This name has already been refused for your account (`details.reason`) | --- # Best practices ## Never debit twice After a network outage, you do not know whether your request got through. Send it again with the **same** `Idempotency-Key` (for example the order identifier): if it had got through, you receive the same message, without a new debit. ## One-time codes Send them with `"sensitive": true`: their text is erased as soon as they are sent and is never stored. Do not schedule them. ## Retries - `5xx` or timeout: retry with the **same** `Idempotency-Key`, spacing out the attempts (for example 1 s, 5 s, 30 s). The number of attempts and the acceptable wait depend on your use case. - `429`: wait for the number of seconds given by `Retry-After`, then retry with the same `Idempotency-Key`. - `4xx`: do not retry as is; fix the request (see [Errors](https://docs.aureusprime.com/en/reference/sms/erreurs)). ## Configuration Make the API base URL and the sender configurable, without changing the code. As long as your sender name is not approved, do not send `senderId`: the shared sender is used. A name not yet approved causes **every** request to be rejected (`422 SENDER_NOT_APPROVED`). ## Security - API key on the server side only; never in a mobile app or a web page. - Two active keys at most: use the second one to change keys without downtime. - Numbers are masked in every response. Rather, link the message `id` to your business object (order, notification); only keep a mapping to the number if you have a real use for it, and no longer than necessary. ## Permitted SMS The API is for **transactional** SMS: codes, confirmations, reminders, alerts linked to a service the recipient uses. Marketing and unsolicited messages are prohibited by the [terms of use](https://getaureusdesk.com/en/cgu). ## Text 160 characters per SMS, in the SMS alphabet: your text is always converted to it (ê becomes e, the curly apostrophe becomes straight, emoji are removed). Write it that way directly to know exactly what is sent, and check `normalized` in the response. Prefer a short, clear text, with your company name if it does not appear in the sender. A really long message: `"allowTwoParts": true`, billed as 2 SMS. ## Sending to your customers before verification Until your identity or business is verified, only the test SMS to your own verified number goes through. Have your account verified before integrating the API in production. --- # SMS API reference **Base URL:** `https://api.getaureusdesk.com/v1` · **Authentication:** `Authorization: Bearer adk_sms_YOUR_KEY` · **Format:** JSON, UTF-8. | Method | Route | Purpose | Details | |---|---|---|---| | `POST` | `/sms/messages` | Send an SMS (or 2 SMS), right away or on a scheduled date | [Send](https://docs.aureusprime.com/en/documentation/sms/envoyer), [Schedule](https://docs.aureusprime.com/en/documentation/sms/planifier) | | `GET` | `/sms/messages/:id` | State of a message | [Track](https://docs.aureusprime.com/en/documentation/sms/suivre) | | `DELETE` | `/sms/messages/:id` | Cancel a scheduled SMS that has not gone out yet (credits given back) | [Schedule](https://docs.aureusprime.com/en/documentation/sms/planifier) | | `GET` | `/sms/balance` | Purchased credits, free credits, low balance alert | [Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs) | | `GET` | `/sms/coverage` | Open countries, price of one SMS in credits, networks served | [Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs) | | `GET` | `/sms/price-tiers` | Volume price grid (top-up bonus) | [Balance and top-ups](https://docs.aureusprime.com/en/documentation/sms/solde-tarifs) | | `GET` | `/sms/senders` | Your senders and their status | [Senders](https://docs.aureusprime.com/en/documentation/sms/expediteurs) | | `POST` | `/sms/senders` | Request an own sender (organisations) | [Senders](https://docs.aureusprime.com/en/documentation/sms/expediteurs) | ## Message object | Field | Type | Description | |---|---|---| | `id` | string (UUID) | Message identifier (of part 1 for a 2-SMS message) | | `status` | string | `QUEUED`, `SENDING`, `SENT`, `DELIVERED`, `FAILED` or `CANCELLED` | | `to` | string | Masked number (`+237*******56`) | | `operator` | string or null | `MTN`, `ORANGE`… | | `countryIso` | string | Recipient's country (`CM`) | | `priceCredits` | number | Credits for this SMS | | `senderId` | string | Sender used | | `errorCode` | string or null | Reason for a failure | | `groupId` | string or null | 2-SMS message: identifier shared by both parts | | `part` | string or null | `"1/2"` or `"2/2"`; `null` for a single SMS | | `scheduledAt` | string or null | Scheduled sending date (ISO 8601) | | `createdAt`, `sentAt`, `deliveredAt` | string or null | Dates (ISO 8601, UTC) | On sending only: `likelyUndelivered` (operator not served today), `normalized` (text converted to the SMS alphabet), `smsCount` (1 or 2), `totalCredits`, `parts` (both parts of a 2-SMS message), and `replayed` when an `Idempotency-Key` replays an existing message. The text of a message is never returned. --- # Authentication Every call carries your API key in the `Authorization` header: ```http Authorization: Bearer adk_sms_YOUR_KEY ``` No key, or a revoked key: `401 AUTH_REQUIRED`. Suspended account: `403 ACCOUNT_SUSPENDED`. ## Your keys - A key is tied to **your SMS account**: it only sees and spends your credits. - It is shown **only once**, when it is created. Aureus Desk keeps only a fingerprint of it: it cannot be retrieved afterwards. - You can have **2 active keys at most**. Creating a third one is refused (`409 API_KEY_LIMIT`). ## Changing keys without downtime 1. Create a second key. 2. Deploy it to your servers. 3. Revoke the old one in the account area. ## Environments Today there is **only one environment, production**: every successful call to `POST /sms/messages` sends a real SMS and consumes credit. There is no test environment or test key yet. For your tests: - send to your own number; - use a key dedicated to testing, which you will revoke afterwards; - check your requests with the rejections returned before sending (`4xx`), which never debit any credit. The creation of a test environment will be announced in the [changelog](https://docs.aureusprime.com/en/reference/sms/historique). ## Good rules - Keep the key **server-side**: never in a mobile app, a web page or a code repository. - An exposed key must be revoked immediately: messages sent with it are charged to you. --- # Errors All errors have the same shape: ```json { "error": { "code": "TEXT_TWO_PARTS_REQUIRED", "message": "Ce message dépasse 160 caractères : envoyez-le en 2 SMS…", "details": { "length": 212, "max": 160 } } } ``` Rely on `code`, which is stable; `message` is a human-readable text that may change. `details` is optional. | HTTP | `code` | Case | |---|---|---| | 400 | `VALIDATION_FAILED` | Invalid request (field of the wrong type, malformed header) | | 401 | `AUTH_REQUIRED` | API key missing, invalid or revoked | | 402 | `INSUFFICIENT_CREDITS` | Not enough credits for this SMS (or these 2 SMS); nothing is queued | | 403 | `ACCOUNT_SUSPENDED` | Account suspended | | 403 | `VERIFICATION_REQUIRED` | Identity or business to be verified before sending to a third party (only the test SMS to your own verified number goes through before that) | | 404 | `NOT_FOUND` | Resource missing or outside your account | | 409 | `IDEMPOTENCY_CONFLICT` | Idempotency key already used for another recipient or another sender | | 409 | `NOT_CANCELLABLE` | Cancellation of an SMS that is not scheduled or has already gone out | | 409 | `SENDER_LIMIT_REACHED` | A sender name is already under review or approved: a single custom name per account (`details.current`, `details.status`) | | 409 | `SENDER_NAME_REFUSED` | This name has already been refused for your account (`details.reason`): suggest another one | | 409 | `API_KEY_LIMIT` | 2 active API keys at most | | 422 | `PHONE_INVALID` | Malformed number | | 422 | `PHONE_NOT_COVERED` | Country not open (today, only Cameroon is), or landline number | | 422 | `TEXT_INVALID` | Empty text, text with control characters (except line breaks), or text emptied by the conversion to the SMS alphabet | | 422 | `TEXT_TWO_PARTS_REQUIRED` | More than 160 characters: send again with `"allowTwoParts": true` to send it as 2 SMS | | 422 | `TEXT_TWO_PARTS_MAX` | Longer than 2 SMS (about 310 characters): shorten the text | | 422 | `SENDER_INVALID` | Sender in the wrong format (2 to 11 letters, digits or spaces) | | 422 | `SENDER_NOT_APPROVED` | Sender not approved yet | | 422 | `SENDER_NOT_ALLOWED` | Own sender requested by an individual | | 422 | `SCHEDULE_INVALID` | Scheduling date without a time zone, in the past, or more than 30 days ahead | | 429 | `RATE_LIMITED` | More than 10 requests per second for the same key (burst of 20): wait for the number of seconds in the `Retry-After` header, then retry with the same `Idempotency-Key` | A `4xx` rejection never debits any credit. ## Reasons for a message failure (`errorCode`) An accepted message can end in `FAILED` or `CANCELLED`. `errorCode` gives the reason, for example: | `errorCode` | Meaning | Credits | |---|---|---| | `OPERATOR_INACTIVE` | Recipient's network not served or unavailable | Given back | | `PART1_NOT_DELIVERED` | 2-SMS message: delivery of part 1 not confirmed within 15 minutes, part 2 cancelled | Part 2 given back | | `PART1_FAILED` | 2-SMS message: part 1 failed, part 2 never sent | Part 2 given back | | `SEND_INTERRUPTED` | Sending interrupted on our side | Given back | | `CANCELLED` | Scheduled SMS cancelled by you | Given back | --- # Changelog Changes to the SMS API, from the newest to the oldest. A **breaking change** (field removed, behaviour modified) is always flagged as such here, before it goes live. ## 2 November 2026 **New:** - **2-SMS message** with `"allowTwoParts": true`: up to about 310 characters, split between two words, "1/2" and "2/2" prefixes, billed per part; part 2 is only sent once part 1 has been delivered (`errorCode` `PART1_NOT_DELIVERED` if it is not delivered within 15 minutes); - `groupId` and `part` fields in the message object; `normalized`, `smsCount`, `totalCredits` and `parts` in the send response; - `GET /sms/balance` returns free credits (`promoBalance`, `promoExpiresAt`); - `GET /sms/coverage` documented: open countries and price of one SMS in credits. **Behaviour changes:** - the text is **always converted to the SMS alphabet** (ê becomes e, the curly apostrophe becomes straight, emoji and non-Latin scripts removed). The Unicode mode limited to 70 characters no longer exists: 160 characters per SMS in every case; - a text longer than 160 characters now returns `422 TEXT_TWO_PARTS_REQUIRED` (instead of `TEXT_TOO_LONG`), and `422 TEXT_TWO_PARTS_MAX` beyond 2 SMS; - balance in **credits**: 1 credit = 1 FCFA, 25 credits per SMS in Cameroon, bonus credits on large top-ups; - a single custom sender name per account: `409 SENDER_LIMIT_REACHED` and `409 SENDER_NAME_REFUSED` replace `409 CONFLICT`. ## 1 November 2026 — first public version The Aureus Desk SMS API is open, as version `v1`. **Available:** - sending SMS to MTN and Orange mobiles in Cameroon (`POST /sms/messages`), with idempotency key and sensitive messages; - scheduled sending up to 30 days ahead (`scheduledAt`) and cancellation of a scheduled SMS (`DELETE /sms/messages/:id`); - delivery tracking (`GET /sms/messages/:id`); - balance, price grid and senders (`GET /sms/balance`, `GET /sms/price-tiers`, `GET` and `POST /sms/senders`); - SMS length depending on the encoding: 160 characters in the GSM alphabet, 70 in Unicode; - rate limiting per key, with the `429 RATE_LIMITED` code; - 2 active API keys at most per account. **Not available yet:** test environment, delivery notifications by webhook. --- # Rules for AI assistants (AGENTS.md) Copy the text below into an **`AGENTS.md`** file at the root of your project (or into `CLAUDE.md`, or into your editor's rules). Your coding assistant will then call the Aureus Desk SMS API without inventing any route or field, and without exposing your key. ~~~markdown # Aureus Desk SMS API — rules for the coding assistant This project sends SMS in Cameroon with the Aureus Desk SMS API. Follow these rules on every change. ## Access - Base URL: https://api.getaureusdesk.com/v1 - Authentication: `Authorization: Bearer ` header. The key starts with `adk_sms_` and is read from the `AUREUS_SMS_API_KEY` environment variable, on the server side only. Never write it in the code, in a file tracked by git, in a mobile app or in a web page. - JSON in and out (UTF-8). ## Routes (no other route exists) - `POST /sms/messages`: body `{ "to", "text", "allowTwoParts"?, "senderId"?, "sensitive"?, "scheduledAt"? }` → `202`. Always send the `Idempotency-Key` header. - `GET /sms/messages/{id}`: state of a message. - `DELETE /sms/messages/{id}`: cancels a scheduled SMS that has not gone out yet (credits given back; both parts of a 2-SMS message). - `GET /sms/balance` → `{ "balance", "low", "promoBalance", "promoExpiresAt" }` (credits; 1 credit = 1 FCFA). - `GET /sms/coverage` → open countries and `priceCredits` of one SMS per country (25 in Cameroon today): read this price, never hard-code it. - `GET /sms/price-tiers` → `[{ "minQuantity", "unitPriceXaf" }]`. - `GET /sms/senders`; `POST /sms/senders` with `{ "name" }` (organisations, a single custom name per account). ## Rules - `to`: mobile in an open country (Cameroon today: MTN, Orange), preferably in international format, for example `+237699123456`. - `text`: 1 SMS = 160 characters in the GSM alphabet (`€ [ ] { } ^ ~ | \` count as 2). The server always converts the text (ê→e, ç→Ç, ’→', « »→") and removes emoji and non-Latin scripts; `normalized: true` flags it. Never truncate: beyond 160, `allowTwoParts: true` (2 SMS, ~310 characters max, billed twice, part 2 sent after part 1 is delivered) or shorten. - `Idempotency-Key`: stable and derived from the business object (`order-4821`, `otp--`), reused as is for every retry. - One-time code: `"sensitive": true`, sent right away, never scheduled. - `scheduledAt`: ISO 8601 with a time zone (`2026-11-02T08:00:00+01:00`), in the future, 30 days at most. - Errors: read `error.code` (stable), never `error.message`. Do not retry a `4xx`, except `429` after `Retry-After`. Retry a `5xx` or a timeout with the same `Idempotency-Key`, spacing out the attempts (for example 1 s, 5 s, 30 s); number of attempts and acceptable wait depending on the project's use case. - `senderId`: configurable (environment variable), never hard-coded; omitted as long as the name is not approved (shared sender), otherwise every request is rejected (`422 SENDER_NOT_APPROVED`). API base URL configurable too. - Statuses: `QUEUED`, `SENDING`, `SENT`, `DELIVERED`, `FAILED`, `CANCELLED`. Final: `DELIVERED`, `FAILED`, `CANCELLED`. - Numbers come back masked: link the message `id` to the business object (order, notification). Only keep a mapping to the number for a real use (tracking, complaint), and no longer than necessary. - Transactional SMS only (codes, confirmations, reminders, alerts): never marketing. ## Error codes - 400 `VALIDATION_FAILED` · 401 `AUTH_REQUIRED` · 402 `INSUFFICIENT_CREDITS` · 403 `ACCOUNT_SUSPENDED`, `VERIFICATION_REQUIRED` - 404 `NOT_FOUND` · 409 `IDEMPOTENCY_CONFLICT`, `NOT_CANCELLABLE`, `SENDER_LIMIT_REACHED`, `SENDER_NAME_REFUSED`, `API_KEY_LIMIT` - 422 `PHONE_INVALID`, `PHONE_NOT_COVERED`, `TEXT_INVALID`, `TEXT_TWO_PARTS_REQUIRED`, `TEXT_TWO_PARTS_MAX`, `SENDER_INVALID`, `SENDER_NOT_APPROVED`, `SENDER_NOT_ALLOWED`, `SCHEDULE_INVALID` - Message `errorCode`: notably `PART1_NOT_DELIVERED` (part 2 cancelled, credits given back) - 429 `RATE_LIMITED`: 10 requests/s per key (burst of 20); wait `Retry-After` seconds, same `Idempotency-Key` Full documentation as plain text: https://docs.aureusprime.com/en/llms-full.txt ~~~ ## Going further - A **skill** ready to install, with a sending function already written: [Aureus SMS skill](https://docs.aureusprime.com/en/integration-ia/sms/skill). - The whole documentation on a single plain-text page: [llms.txt and llms-full.txt](https://docs.aureusprime.com/en/integration-ia/sms/llms). --- # Aureus SMS skill A **skill** gives your coding assistant a complete method for a specific task. Create the file below in your project: - **Claude Code:** `.claude/skills/aureus-sms/SKILL.md` - **Codex:** `.codex/skills/aureus-sms/SKILL.md` (or your tool's skills location) ~~~markdown --- name: aureus-sms description: Send, schedule, cancel and track SMS in Cameroon with the Aureus Desk SMS API. Use it whenever the code must send a sign-in code, a confirmation, a reminder or an alert by SMS. --- # Sending SMS with Aureus Desk ## Before writing code 1. Check that the `AUREUS_SMS_API_KEY` environment variable exists on the server side (never on the client side). 2. Reuse the project's `aureusSms` module if it exists; otherwise, create it with the code below. ## Module to use (TypeScript, Node 18 or later) ```ts const BASE = "https://api.getaureusdesk.com/v1"; export type SmsStatus = "QUEUED" | "SENDING" | "SENT" | "DELIVERED" | "FAILED" | "CANCELLED"; export interface SmsMessage { id: string; status: SmsStatus; to: string; operator: string | null; countryIso: string; priceCredits: number; senderId: string; errorCode: string | null; groupId: string | null; part: "1/2" | "2/2" | null; scheduledAt: string | null; createdAt: string; sentAt: string | null; deliveredAt: string | null } export interface SendResult extends SmsMessage { likelyUndelivered: boolean; normalized: boolean; smsCount: 1 | 2; totalCredits: number; parts?: SmsMessage[]; replayed?: boolean } export class AureusSmsError extends Error { constructor(readonly status: number, readonly code: string, message: string) { super(message); } } async function call(method: string, path: string, body?: unknown, idempotencyKey?: string): Promise { const response = await fetch(`${BASE}${path}`, { method, headers: { Authorization: `Bearer ${process.env.AUREUS_SMS_API_KEY}`, "Content-Type": "application/json", ...(idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}), }, body: body === undefined ? undefined : JSON.stringify(body), }); const json = await response.json().catch(() => null); if (!response.ok) throw new AureusSmsError(response.status, json?.error?.code ?? "UNKNOWN", json?.error?.message ?? response.statusText); return json as T; } /** Sends an SMS. Stable `idempotencyKey` (e.g. `order-4821`): reuse it for every retry. */ export function sendSms(input: { to: string; text: string; idempotencyKey: string; allowTwoParts?: boolean; sensitive?: boolean; scheduledAt?: string; senderId?: string }) { const { idempotencyKey, ...body } = input; return call("POST", "/sms/messages", body, idempotencyKey); } export const getSms = (id: string) => call("GET", `/sms/messages/${id}`); export const cancelSms = (id: string) => call("DELETE", `/sms/messages/${id}`); export const getBalance = () => call<{ balance: number; low: boolean; promoBalance: number; promoExpiresAt: string | null }>("GET", "/sms/balance"); ``` ## Rules - 1 SMS = 160 characters in the GSM alphabet; the server always converts the text (ê→e, ’→', emoji removed) and flags it with `normalized`. Beyond 160: `allowTwoParts: true` (2 SMS billed, part 2 after part 1 is delivered) or shorten, never truncate. - Price in credits (1 credit = 1 FCFA), specific to each country: read `GET /sms/coverage` (`priceCredits`), never hard-coded; `getBalance()` before a bulk send. - One-time code: `sensitive: true`, never `scheduledAt`. - `scheduledAt`: ISO 8601 with a time zone (`+01:00`), future, 30 days at most; `cancelSms` to cancel. - Handle errors by `AureusSmsError.code`. Do not retry a `4xx`; retry a `5xx` with the same idempotency key. - Numbers come back masked: link the returned `id` to the business object (order, notification), not to the number. - Sender (`senderId`) and API base URL configurable; no `senderId` as long as the name is not approved. - Transactional SMS only; never marketing. Full reference: https://docs.aureusprime.com/en/llms-full.txt ~~~ --- # llms.txt and llms-full.txt Two addresses serve the documentation as **plain text**, easy for an agent or a coding assistant to read: | Address | Content | |---|---| | https://docs.aureusprime.com/en/llms.txt | Index: one line per page, with its summary | | https://docs.aureusprime.com/en/llms-full.txt | The whole public SMS API documentation, on a single page | They are generated from the same texts as this site: they are always up to date. ## Giving them to your assistant In a conversation, paste the address of `llms-full.txt` and ask your assistant to read it before writing code. To keep it in your project: ```bash curl -fsSL https://docs.aureusprime.com/en/llms-full.txt -o docs/aureus-sms.md ``` For permanent rules, prefer the text of the [Rules for AI assistants](https://docs.aureusprime.com/en/integration-ia/sms/assistants-ia) page.