JamiDev

Introduction

Sell digital products in ETB with hosted checkout pages, benefits, webhooks and an API — settled through ArifPay.

Documentation Index

Fetch the complete documentation index at: https://dev.jami.bio/llms.txt

Use this file to discover all available pages before exploring further. For every page's raw markdown source, append .md to its URL (e.g. https://dev.jami.bio/docs/quickstart.md), or fetch the whole docs set in one call at https://dev.jami.bio/llms-full.txt.

JamiDev is Jami's product-and-payments layer for developers. You create products, share a checkout link (or embed checkout on your own site), and JamiDev handles the payment through local Ethiopian gateways, grants benefits like license keys, notifies your backend with signed webhooks, and emails receipts — all settled in ETB.

AI agent integration prompt

Paste the prompt below into Claude Code, Cursor, Windsurf, Codex or another coding agent to scaffold a full JamiDev integration — sandbox setup, checkout, webhook verification and going live.

AI Agent Integration Prompt
# Goal — ship your first JamiDev checkout end-to-end

You are integrating JamiDev (https://dev.jami.bio/docs) into my project. Take me from zero
to a working checkout: product, checkout session, payment, webhook, fulfilled order.

## My application context

<my_stack>
Stack: [framework + language, e.g. Next.js 15 + TypeScript]
Surface: [web | backend-only | mobile webview]
Use case: [one-time digital product | subscription | donation]
Database: [Postgres | MySQL | Mongo]
</my_stack>

## Steps

1. **Enable Developer Mode & create a sandbox org** — requires a KYC-verified Jami account.
   In the dashboard: Settings → Developer Mode, then switch to a sandbox organization
   (simulated payments, nothing real moves).

2. **Create a product** — Store → Products → New product. Pick a pricing model (`fixed`,
   `pwyw` or `free` — locked after creation). Publish it and copy the product id.

3. **Get an API token** — Developer → API Tokens. Save it as `JAMI_TOKEN`
   (`jamidev_test_…` in sandbox, `jamidev_live_…` in production).

4. **Install the SDK and create a checkout**

```bash
npm install jami-sdk
```

```ts
import { Jami } from 'jami-sdk';

const jami = new Jami({ token: process.env.JAMI_TOKEN! });

const checkout = await jami.createCheckout({
  productId: '<product id>',
  customer: { email: 'buyer@example.com', phone: '251900000001' }, // magic sandbox success number
  gateway: 'telebirr', // 'telebirr' | 'mpesa' | 'cbe'
});
```

Free products resolve instantly (`orderId` present). Paid products return `mode: 'redirect'`
(send the buyer to `checkoutUrl`) or `mode: 'direct'` (buyer confirms on their phone — poll next).

5. **Wait for payment**

```ts
if (!('orderId' in checkout)) {
  const status = await jami.waitForCheckout(checkout.sessionId);
  // status.status: 'completed' | 'expired', status.orderId
}
```

6. **Register a webhook and verify deliveries** — Automation → Webhooks → add your endpoint
   URL, save the returned secret as `JAMI_WEBHOOK_SECRET`. Subscribe to `order.created`,
   `order.completed`, `benefit.granted`, `checkout.session.expired`.

```ts
import { JamiSignatureError } from 'jami-sdk';

const event = await jami.webhooks.verify({
  payload: rawBody, // exactly as received, do not JSON.parse first
  signature: req.headers['x-jamidev-signature'],
  secret: process.env.JAMI_WEBHOOK_SECRET!,
});
// event.type: 'order.created' | 'order.completed' | 'benefit.granted' | 'checkout.session.expired'
```

Respond `2xx` within 10 seconds. Handle idempotently — retries and manual resends can
redeliver the same `event.id`.

7. **List orders (fallback / reconciliation)**

```ts
const { items, total } = await jami.listOrders({ status: 'paid', page: 1, limit: 20 });
```

8. **Go live** — Settings → Environment → switch to production, register production
   webhook endpoints (subscriptions are per-organization), and issue a fresh `jamidev_live_`
   token.

## Failure modes

- Missing/invalid token → `401`, with `.hint` set when the token was minted for the org's
  other environment (re-issue it).
- Validation error → `400`, message names the offending field.
- `POST /checkout` limited to 20 requests / 5 minutes / IP → `429`.
- Webhook signature mismatch, malformed header, or stale timestamp (>300s) → throws
  `JamiSignatureError`; treat the delivery as untrusted.

## Sources of truth (cross-check before shipping)

- https://dev.jami.bio/llms-full.txt — full docs in one fetch
- https://dev.jami.bio/openapi.json — machine-readable REST spec
- /docs/api — raw REST reference (checkout, orders)
- /docs/sdk — typed SDK reference and error types
- /docs/webhooks — event payloads and signature verification

Core concepts

ConceptWhat it is
OrganizationAn isolated workspace: its own products, customers, checkout links, API tokens, webhooks and balance. You can own several and switch between them from the dashboard header.
EnvironmentEvery organization is either sandbox (simulated payments, nothing real moves) or production (live ArifPay charges). Switchable both ways in Settings.
ProductA sellable item with a pricing model — fixed, pwyw (pay-what-you-want) or free. The pricing model is locked after creation.
Checkout sessionA short-lived (30 min) attempt to buy one product. Snapshots the price and metadata at creation, so later product edits never affect in-flight checkouts.
OrderA completed, paid checkout. Idempotent — a session can only ever produce one order, no matter how many times payment notifications replay.
BenefitSomething granted automatically on purchase, e.g. a generated license key.
Checkout linkA long-lived shareable URL (/jamidev/c/…) that can offer one or several products, carry metadata onto orders, and redirect buyers back to your site.

Money

  • All API amounts are integer ETB minor units (santim). 10000 = 100.00 ETB.
  • Buyers pay exactly the listed price — nothing is added at checkout. A 100 ETB product charges the buyer 100 ETB.
  • Taxes are deducted when the seller withdraws: 30% government tax + 5% Jami usage fee (a 100 ETB balance pays out 65 ETB). The dashboard's balance breakdown shows this estimate.
  • Amounts are always computed server-side from the trusted price configuration. For fixed products any client-supplied amount is ignored; for pwyw the amount must be an integer at or above the product's minimum.

Payment methods

Checkout supports Telebirr, M-Pesa and CBE Birr via ArifPay direct transfer — the buyer stays on the checkout page and confirms the payment on their phone. No card data ever touches Jami.

Sign in with Jami

Beyond payments, Jami is an OAuth 2.1 / OpenID Connect provider. You can put a "Sign in with Jami" button in your own product and authenticate Jami users without building an account system — v1 is identity only (sub, name, picture, email), with resource scopes to follow. See Sign in with Jami.

What's coming

An official client SDK (@jami/jamidev) is planned — until then, the REST API is small and stable enough to call directly.

On this page