SDKs & CLI
Four official clients — Node, PHP, Go, and a command-line tool — generated from the same OpenAPI spec and each wrapped with hand-rolled HMAC signing. All install straight from GitHub; no package registry accounts needed.
Pick your stack
Node / TypeScript
Repo ↗@armada/sdk
Typed resource methods, axios-powered, HMAC signing via a request interceptor.
npm i github:armadadelivery/armada-node#v0.1.0-beta.0
PHP
Repo ↗armada/sdk
Guzzle-based, Psr-7 friendly, HMAC signing via a Guzzle middleware.
composer config repositories.armada vcs https://github.com/armadadelivery/armada-php composer require armada/sdk:dev-main
Go
Repo ↗github.com/armadadelivery/sdk-go
net/http based, context-aware, zero third-party deps, RateLimit on every *Response.
go get github.com/armadadelivery/sdk-go@v0.1.0-beta.0
CLI
Repo ↗@armada/cli
Single binary (armada). Wraps the Node SDK — every command mirrors a method.
npm i -g github:armadadelivery/armada-cli#v0.1.0-beta.0
What every SDK does for you
- HMAC signing. You never compute a signature by hand — each SDK injects
x-armada-timestampandx-armada-signatureon every request via an interceptor / middleware. - Base URL defaults. Sandbox by default. Flip by passing the production
baseUrlexplicitly — hard to ship to prod by accident. - Rate-limit headers. Exposed on every successful response
(
response.rateLimitin Node,rateLimitFor($res)in PHP,resp.RateLimitin Go). Ignore them if you like; they're there when you need to back off. - Typed errors. 4xx/5xx surface with the server's error code + message so
your
catchblocks can branch.
Node / TypeScript
Typed resource methods under armada.{deliveries,branches,wallet,invoices}.
Every call returns { data, status, rateLimit }. Needs Node ≥ 18.
import { ArmadaClient } from '@armada/sdk';
const armada = new ArmadaClient({
apiKey: process.env.ARMADA_API_KEY!,
apiSecret: process.env.ARMADA_API_SECRET!,
});
// Every method returns { data, status, rateLimit }
const { data: order } = await armada.deliveries.create({
reference: 'abc-123',
payment: { amount: 5, type: 'paid' },
origin_format: 'branch_format',
origin: { branch_id: 'YOUR_BRANCH_ID' },
destination_format: 'location_format',
destination: { contact_name: 'X', contact_phone: '+965', latitude: 29.3, longitude: 47.9 },
});
// Errors come back as ArmadaError with .status, .code, .response
try {
await armada.deliveries.retry(order.id);
} catch (err) {
if (err.status === 409) console.log('Not retryable:', err.response?.message);
else throw err;
}PHP
Thin Guzzle wrapper. You build the request path + body; the SDK signs and sends. Returns a
PSR-7 ResponseInterface so you drop in any Guzzle middleware you already have.
Needs PHP ≥ 8.1.
use Armada\SDK\ArmadaClient;
$armada = new ArmadaClient([
'apiKey' => getenv('ARMADA_API_KEY'),
'apiSecret' => getenv('ARMADA_API_SECRET'),
]);
$res = $armada->postJson('/v2/deliveries', $body);
if ($res->getStatusCode() >= 400) {
$err = json_decode((string) $res->getBody(), true);
throw new RuntimeException("armada {$res->getStatusCode()}: {$err['message']}");
}
$order = json_decode((string) $res->getBody(), true);Go
net/http-based, zero third-party deps, everything takes a context.Context. DecodeJSON is a one-liner that errors on 4xx/5xx with the decoded body.
c := armada.NewClient(armada.Options{
APIKey: os.Getenv("ARMADA_API_KEY"),
APISecret: os.Getenv("ARMADA_API_SECRET"),
})
resp, err := c.PostJSON(ctx, "/v2/deliveries", body)
if err != nil { return err }
var order struct{ ID, Status string }
if err := armada.DecodeJSON(resp, &order); err != nil {
// DecodeJSON returns an error with the status + body for 4xx/5xx
return err
}CLI
armada — single binary, built on top of the Node SDK. Every command mirrors a
resource method. Credentials live in ~/.armada/config.json (mode 600) or the ARMADA_API_KEY + ARMADA_API_SECRET env vars (env takes precedence).
# first-time setup armada config set # prompts for apiKey + apiSecret # wallet armada wallet # branches armada branches list armada branches create --from-file branch.json armada branches get <id> armada branches update <id> --from-file branch.json armada branches delete <id> # deliveries armada deliveries create --from-file order.json armada deliveries get <id> armada deliveries cancel <id> --reason "customer changed mind" armada deliveries retry <id> armada deliveries estimate --from-file estimate.json # invoices armada invoices list --status paid --since 2026-01-01 --per-page 50 armada invoices get <id> # switch target armada --api-base https://api.armadadelivery.com wallet # prod armada --json wallet # stdout-only JSON (pipeable)
Versioning & upgrades
Every SDK tracks the OpenAPI spec through an automated sync — when the spec changes in the api repo, the SDK repo gets a regeneration PR within six hours. Maintainers
review, merge, and cut a new tag.
Pinning recommendation:
- Production: pin to a specific tag
(
#v0.1.0-beta.0). Bump intentionally. - Staging / internal tools: pin to a tag or track
main— your call. - Exploration: just use
main. You'll always have the latest.