App SDK and OpenAPI
A typed client for the public and account endpoints, Python helpers and the OpenAPI description.
The API is plain HTTPS and JSON, so any HTTP library works. To save you the boilerplate there's a small typed TypeScript client below, and an OpenAPI 3.1 description you can generate a client from in any language.
Official packages on npm and PyPI are on the way. Until they're published, copy the client below into your project: it has no dependencies and covers every documented endpoint you'll need first.
TypeScript
autopayke.ts
// autopayke.ts: a small typed client for the AutoPayKe API. // No dependencies; Node 18+, Deno, Bun and edge runtimes. export type Envelope<T> = { ok: true; data: T } | { ok: false; error: string; code: string };
export class AutoPayKeError extends Error {
constructor(public code: string, message: string, public status: number) {
super(message);
this.name = "AutoPayKeError";
}
}
export type FeeProduct =
| "cashout" | "wallet_to_wallet" | "card_topup"
| "bank_topup" | "mobile_money_topup" | "payment_link_card";
export type FeeQuote = {
product: FeeProduct;
currency: string;
amount: string;
fees: { code: string; label: string; amount: string; currency: string }[];
totalFee: string;
total: string;
placeholder: boolean;
settingsVersion: string | null;
};
export class AutoPayKe {
constructor(
private opts: {
baseUrl?: string;
/** Returns the current access token for account endpoints. */
token?: () => string | Promise<string>;
} = {},
) {}
private async request<T>(method: string, path: string, body?: unknown, idempotencyKey?: string): Promise<T> {
const headers: Record<string, string> = {};
if (this.opts.token) headers.Authorization = `Bearer ${await this.opts.token()}`;
if (body !== undefined) headers["Content-Type"] = "application/json";
if (idempotencyKey) headers["Idempotency-Key"] = idempotencyKey;
const res = await fetch(`${this.opts.baseUrl ?? "https://api.autopayke.com"}${path}`, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
});
const json = (await res.json()) as Envelope<T>;
if (!json.ok) throw new AutoPayKeError(json.code, json.error, res.status);
return json.data;
}
// Public
capabilities(q: { country?: string; direction?: "collection" | "payout" } = {}) {
return this.request<any>("GET", `/api/v1/capabilities?${new URLSearchParams(q as Record<string, string>)}`);
}
publishedFees() {
return this.request<any>("GET", "/api/v1/fees/published");
}
quote(q: { product: FeeProduct; amount: string; currency: string; country?: string }) {
return this.request<FeeQuote>("GET", `/api/v1/fees/quote?${new URLSearchParams(q)}`);
}
paymentLink(code: string) {
return this.request<any>("GET", `/api/v1/p/${code}`);
}
payPaymentLink(code: string, body: { method: "card" | "mobile_money" | "bank"; country: string; phone?: string; idempotencyKey?: string }) {
return this.request<any>("POST", `/api/v1/p/${code}/pay`, body);
}
// Account (needs token)
balance() {
return this.request<any>("GET", "/api/v1/balance");
}
fundingOptions() {
return this.request<any>("GET", "/api/v1/funding/options");
}
topUpMobileMoney(body: { amount: string; phone: string; operator?: string }, idempotencyKey?: string) {
return this.request<any>("POST", "/api/v1/funding/mobile-money", body, idempotencyKey);
}
topUp(id: string) {
return this.request<any>("GET", `/api/v1/funding/${id}`);
}
createPaymentRequest(body: { amount: string; allowedMethods: ("card" | "mobile_money" | "bank")[]; description?: string; expiresInDays?: number }) {
return this.request<any>("POST", "/api/v1/payment-requests", body);
}
paymentRequests() {
return this.request<any>("GET", "/api/v1/payment-requests");
}
payoutAccounts() {
return this.request<any>("GET", "/api/v1/wallet/destinations");
}
}Use it
example.ts
import { AutoPayKe, AutoPayKeError } from "./autopayke";
const ap = new AutoPayKe({ token: () => process.env.AUTOPAYKE_TOKEN! });
const quote = await ap.quote({ product: "cashout", amount: "40", currency: "USDC" });
console.log("Fee:", Number(quote.totalFee) / 1e6, "USDC");
try {
const topup = await ap.topUpMobileMoney(
{ amount: "1500", phone: "+254712345678", operator: "Safaricom" },
"topup-2026-11-03-0001",
);
console.log(topup.stepRequired);
} catch (e) {
if (e instanceof AutoPayKeError && e.code === "RATE_LIMIT") {
// back off and retry with the same idempotency key
}
}Python
autopayke.py
import os
import requests
class AutoPayKeError(Exception):
def __init__(self, code, message, status):
super().__init__(message)
self.code, self.status = code, status
class AutoPayKe:
def __init__(self, token=None, base_url="https://api.autopayke.com"):
self.base_url = base_url
self.session = requests.Session()
if token:
self.session.headers["Authorization"] = f"Bearer {token}"
def _call(self, method, path, idempotency_key=None, **kw):
headers = {"Idempotency-Key": idempotency_key} if idempotency_key else {}
res = self.session.request(method, self.base_url + path, headers=headers, timeout=30, **kw)
body = res.json()
if not body["ok"]:
raise AutoPayKeError(body["code"], body["error"], res.status_code)
return body["data"]
def quote(self, product, amount, currency):
return self._call("GET", "/api/v1/fees/quote",
params={"product": product, "amount": amount, "currency": currency})
def capabilities(self, country=None, direction=None):
params = {k: v for k, v in {"country": country, "direction": direction}.items() if v}
return self._call("GET", "/api/v1/capabilities", params=params)
def balance(self):
return self._call("GET", "/api/v1/balance")
def top_up_mobile_money(self, amount, phone, operator=None, idempotency_key=None):
return self._call("POST", "/api/v1/funding/mobile-money", idempotency_key,
json={"amount": amount, "phone": phone, "operator": operator})
ap = AutoPayKe(token=os.environ.get("AUTOPAYKE_TOKEN"))
print(ap.quote("cashout", "40", "USDC")["totalFee"])OpenAPI
Every documented endpoint, parameter and example as OpenAPI 3.1. Import it into Postman or Insomnia, or generate a client with openapi-generator for Go, Java, PHP, C#, Ruby and more.
npx @openapitools/openapi-generator-cli generate \
-i https://www.autopayke.com/openapi.json \
-g go -o ./autopayke-go