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)
---
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<T>(method: string, path: string, body?: unknown, idempotencyKey?: string): Promise<T> {
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<SendResult>("POST", "/sms/messages", body, idempotencyKey);
}
export const getSms = (id: string) => call<SmsMessage>("GET", `/sms/messages/${id}`);
export const cancelSms = (id: string) => call<SmsMessage>("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