SDKs & client libraries
Official SOAMTAR libraries for server languages, mobile apps, the browser, Unity and the main e-commerce platforms. They all target Sierra Leone: amounts in leones (SLE, with USD and EUR also accepted), Orange Money Sierra Leone (orange_money_sl) as the only provider, payer phones in +232 format followed by 8 digits.
Availability
The versions below are final, but the packages are not yet published on public registries (npm, Packagist, PyPI, RubyGems, Maven Central, NuGet, pub.dev…). Until they are, install them from the source repository provided by SOAMTAR support. The browser SDK is already served at https://app.so-amtar.com/sdk/soamtar.js.
How to choose?
| My profile | My recommendation |
|---|---|
| I'm just starting | Follow the Getting started guide. It's the simplest path. |
| I use a CMS | Go straight to the CMS & e-commerce plugins section below. |
| I'm a backend developer | Pick your language in the Server section. |
| I'm building a mobile app or a game | Use the libraries in the Mobile & frontend section. Your backend still creates the payment. |
Two kinds of libraries
| Server SDKs | Client SDKs (browser, mobile, Unity) | |
|---|---|---|
| Key | Secret key sk_test_… / sk_live_… | Public key pk_test_… / pk_live_… (or no key) |
| Where it runs | Your backend only | The payer's browser, phone or game |
| What it does | Creates payments (POST /v1/payments), reads them, verifies webhooks | Opens the payment_url your backend obtained from POST /v1/payments |
A client SDK never creates a payment and never holds a secret key. There is no separate sandbox host: with a sk_test_ key, payments are simulated on https://app.so-amtar.com/v1.
Server (backend)
| Language | Package | Version | Entry point |
|---|---|---|---|
| PHP / Laravel | soamtar/soamtar-php (Composer, PHP 8.2+) | 1.1.0 | Soamtar\SoamtarClient, Soamtar\Soamtar |
| Node.js / TypeScript | @soamtar/sdk (npm) | 1.1.0 | SoamtarClient |
| Python | soamtar (pip) | 1.1.0 | soamtar.SoamtarClient |
| Ruby | soamtar (gem) | 1.1.0 | Soamtar::Client |
| Java | com.soamtar:soamtar-java (Maven) | 1.1.0 | com.soamtar.sdk.SoamtarClient |
| Go | github.com/soamtar/soamtar-go-sdk | 1.1.0 | soamtar.NewClient |
| .NET / C# | Soamtar (NuGet) | 1.1.0 | Soamtar.SoamtarClient |
Mobile & frontend
| Platform | Package | Version | Entry point |
|---|---|---|---|
| Browser (JavaScript) | Script served at https://app.so-amtar.com/sdk/soamtar.js (@soamtar/browser on npm later) | 1.0.0 | SoamtarSDK |
| iOS (Swift) | SoamtarSDK (Swift Package Manager, iOS 14+) | 1.0.1 | Soamtar, SoamtarCheckoutView |
| Android (Kotlin) | com.soamtar:soamtar-android (Gradle) | 1.1.0 | com.soamtar.sdk.Soamtar |
| Flutter | soamtar_sdk (pub) | 1.0.1 | package:soamtar_sdk/soamtar_sdk.dart |
| React Native | @soamtar/react-native (npm, with react-native-webview) | 1.1.0 | SoamtarClient, SoamtarCheckout |
| Unity (games) | Assets/Soamtar folder | 1.0.1 | Soamtar.SoamtarClient |
CMS & e-commerce plugins
| Platform | Plugin | Version |
|---|---|---|
| WordPress / WooCommerce | SOAMTAR for WooCommerce (soamtar-gateway) | 1.1.0 |
| Magento 2 | soamtar/magento2-payment (module Soamtar_Payment) | 1.1.0 |
| PrestaShop 1.7.7+ | soamtar payment module | 1.1.0 |
| Drupal Commerce | soamtar/drupal-commerce (module soamtar_commerce) | 1.1.0 |
| Odoo 17 | payment_soamtar (SOAMTAR Payment Provider) | 17.0.1.1.0 |
All five plugins support native refunds from the back office (see CMS & e-commerce plugins).
Payment terminals (TPE / Smart POS)
A SOAMTAR SDK for Android payment terminals is in preparation. It relies on /v1/pos/* endpoints that are not available yet in the API: do not use it in production.
Common conventions
The server SDKs share the same surface, adapted to each language's naming style (CreateAsync in .NET, Create(ctx, …) in Go, send_test in Python/Ruby):
client.payments.create(params, idempotencyKey?) POST /v1/payments
client.payments.retrieve(id) GET /v1/payments/{id}
client.payments.list(filters) GET /v1/payments
client.payments.status(idOrReference) GET /v1/status/{idOrReference}
client.payments.verify(id) POST /v1/payments/{id}/verify
client.payouts.create / retrieve / list /v1/payouts
client.refunds.create / retrieve / list /v1/refunds
client.balance.retrieve() GET /v1/balance
client.webhooks.list / create / secret / sendTest /v1/webhooks
Webhook.constructEvent(rawBody, signatureHeader, secret)retrieveaccepts the SOAMTAR id or reference (TXN-…), not yourmerchant_ref.- Server clients refuse any key that does not start with
sk_. When no key is passed they readSOAMTAR_SECRET_KEY; the base URL comes fromSOAMTAR_API_URL(SOAMTAR_BASE_URLis still accepted as a fallback), defaulthttps://app.so-amtar.com/v1. - Every
POSTcarries anIdempotency-Keyheader: generated automatically, or the one you pass. webhooks.create:subscribed_eventsis optional and defaults topayment.success,payment.failed,payout.success,payout.failed.webhooks.sendTest()(send_test/SendTestdepending on the language) asks SOAMTAR to deliver awebhook.testevent to your endpoints.- Errors raise a SOAMTAR exception that carries the HTTP status and the API error code.
- Older method names (
webhooks.test,webhooks.all,balance.show,status.retrieve…) remain as deprecated aliases.
Optional request signing (see Authentication) is a client option:
| Language | Option |
|---|---|
| Node.js | soamtar(key, { signRequests: true }) |
| PHP | 'sign_requests' => true |
| Python | SoamtarClient(..., sign_requests=True) |
| Ruby | Soamtar::Client.new(key, sign_requests: true) |
| Go | soamtar.WithSignRequests(true) |
| Java | new SoamtarClient(null, null, Duration.ofSeconds(30), true) (signRequests constructor flag) |
| .NET | new SoamtarClient(signRequests: true) |
Webhook verification helper per language:
| Language | Helper |
|---|---|
| PHP | Soamtar\Webhook::constructEvent($rawBody, $signatureHeader, $secret) |
| Node.js | Webhook.constructEvent(rawBody, signatureHeader, secret) |
| Python | Webhook.construct_event(raw_body, signature_header, secret) |
| Ruby | Soamtar::Webhook.construct_event(raw_body, signature_header, secret) |
| Java | Webhook.constructEvent(payload, signatureHeader, secret) |
| Go | soamtar.ConstructEvent(payload, sigHeader, secret) |
| .NET | Webhook.ConstructEvent(payload, signatureHeader, secret) |
Each helper checks the X-Soamtar-Signature header (t=<unix>,v1=<hmac>, plus v2= while a secret is being rotated), recomputes HMAC-SHA256(secret, "t.payload") on the raw body, rejects timestamps older than 300 seconds, and returns the decoded event (event, created, data). See Webhooks.
Refunds
client.refunds.create({ transaction_id, amount? }) sends the money back to the payer's Orange Money number, debited from your balance. Omit amount for a full refund of what remains; partial refunds are allowed. The refund is asynchronous: the outcome arrives with refund.success / refund.failed. The key needs the can_refund scope. See Refunds.
Recommended patterns
Reuse the client
Create one client per process and reuse it instead of creating one per request:
import { SoamtarClient } from '@soamtar/sdk'
const soamtar = new SoamtarClient(process.env.SOAMTAR_SECRET_KEY)
export function pay(order: { id: string; amount: string; phone: string }) {
return soamtar.payments.create({
merchant_ref: order.id,
amount: order.amount, // "1250.00" → Le 1,250.00
currency: 'SLE',
provider: 'orange_money_sl',
phone: order.phone, // +232XXXXXXXX
})
}Retry with backoff
The SDKs do not retry on their own. If you add retries, reuse the same Idempotency-Key so a retried POST can never create a second payment:
import { randomUUID } from 'node:crypto'
async function withRetry<T>(fn: (key: string) => Promise<T>, max = 3): Promise<T> {
const idempotencyKey = randomUUID() // one key for every attempt
for (let attempt = 0; ; attempt++) {
try {
return await fn(idempotencyKey)
} catch (e: any) {
const retryable = !e.status || e.status === 429 || e.status >= 500
if (!retryable || attempt >= max) throw e
await new Promise(r => setTimeout(r, 2 ** attempt * 1000)) // 1s, 2s, 4s
}
}
}
await withRetry(key => soamtar.payments.create(params, { idempotencyKey: key }))Important
Retry network errors, 429 and 5xx with the same Idempotency-Key. Never retry other 4xx errors: fix the request first. See Idempotency.
Generating from the OpenAPI spec
For a language without an SDK, generate a typed client from the OpenAPI specification (openapi.yaml):
# TypeScript types
npx openapi-typescript ./openapi.yaml -o src/soamtar.types.ts
# Python (openapi-generator)
openapi-generator-cli generate -i ./openapi.yaml -g python -o ./soamtar-py
# Go
oapi-codegen -package soamtar ./openapi.yaml > soamtar.gen.goRequesting an SDK
Is your language missing? Email support@so-amtar.com with:
- the target language / framework;
- your expected transaction volume;
- your main use case.