Project

opensms

0.0
The project is in a healthy, maintained state
Send SMS and OTPs, run batches, look up numbers, and manage contacts, templates, webhooks, numbers, sender IDs, suppressions and wallet through the OpenSMS API. Zero runtime dependencies.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 5.0
~> 13.0
 Project Readme

opensms SDKs

Official client libraries for opensms: prepaid SMS for Africa. Send messages and batches, run OTP, look up numbers, manage contacts, templates, webhooks, numbers and sender IDs, and read your wallet and analytics, all with one API key.

This is a spec-driven monorepo: every client wraps the same API-key surface, defined once in spec/SURFACE.md and spec/DESIGN.md, extracted from the live backend and checked by calling every operation with a real key. All nine clients cover the same 18 resources and 83 methods, and all pass the same live scenario in spec/CONFORMANCE.md.

Language Package Registry Version
TypeScript / JavaScript @opensms/sdk npm 0.1.1
Python opensms PyPI 0.1.1
Go github.com/opensms-io/opensms-go pkg.go.dev 0.1.1
.NET (C#) Opensms NuGet 0.1.1
Java io.opensms:opensms-java Maven Central 0.1.1
Rust opensms crates.io 0.1.1
Ruby opensms RubyGems 0.1.1
PHP opensms/opensms-php Packagist 0.1.1
Swift OpensmsSDK SwiftPM (opensms-swift) 0.1.1

Quickstart

TypeScript

import { Opensms } from '@opensms/sdk';

const opensms = new Opensms({ apiKey: process.env.OPENSMS_API_KEY! });
const message = await opensms.messages.send({ to: '+254712345678', text: 'Your code is 482913' });
console.log(message.id, message.status);

Python

import os

from opensms import Opensms

opensms = Opensms(api_key=os.environ["OPENSMS_API_KEY"])
message = opensms.messages.send(to="+254712345678", text="Your code is 482913")
print(message.id, message.status)

Every other language follows the same shape in its own idiom; see each package README.

What every client does the same way

  • Keys: sk_test_... keys talk to your sandbox, sk_live_... keys to live traffic. The key alone selects the workspace and environment.
  • Retries: on 429 and 5xx, honouring Retry-After, only for requests that are safe to repeat. POSTs carry an Idempotency-Key (generated once per call and reused on every retry). OTP verify and sender ID creation are never retried.
  • Errors: RFC 9457 problem responses become one OpensmsError type with status, title, detail, type and code when the API sends one.
  • Pagination: cursor lists expose items and next_cursor, plus an iterator that walks every page.
  • Webhooks: a helper verifies X-OpenSMS-Signature (t=<unix>,v1=<hex>, HMAC-SHA256 of "<t>.<raw body>" keyed with your whsec_... secret, 300 s tolerance by default). The test vector in DESIGN.md is shared by all nine clients.

Layout

spec/
  SURFACE.md       the API-key surface: resources, methods, wire fields, live status, drift
  DESIGN.md        the client contract every language implements
  CONFORMANCE.md   the live scenario and the mock-transport test list
  openapi.json     the customer API contract this was extracted from
packages/<lang>/   one client per language, each with unit tests and a live conformance suite

Testing

Each package has two suites: mock-transport unit tests that need no network, and a live conformance suite that runs the CONFORMANCE.md scenario against a real API. The live suite is skipped, never failed, when OPENSMS_BASE_URL or OPENSMS_API_KEY is unset. Point it at a sandbox workspace with an all-scope sk_test_ key; the local stack guide shows how to run one on your machine.

Known API behaviour the clients follow

The clients follow what the API actually does, even where it differs from the OpenAPI document. The full list is in SURFACE.md; the ones you are most likely to meet: insufficient scope answers 401 on messages and OTP but 403 elsewhere, most errors have no code field, and a raw text/csv batch upload cannot carry the dedupe flag (clients switch to multipart).

License

MIT, see LICENSE.