Posteering

Quickstart

Integrate the One API end to end — onboard, authenticate, and make your first product call with real, copy-paste requests.

This is the fastest path from nothing to a live product call. Every request below is real and callable against the sandbox. You onboard once through the One API and reach every product you enable from a single signed surface.

Base URL: https://one.posteering.com/api/v1/one. All examples target the sandbox.

Register and get your credentials

POST /partners creates your partner identity and issues two credentials at sign-up — a JWT on-ramp and a durable HMAC root — both resolving the same partner. Each signing secret is returned once; store both securely.

curl -X POST https://one.posteering.com/api/v1/one/partners \\
  -H "Content-Type: application/json" \\
  -d '{
    "organization_name": "Posteering Treasury",
    "email": "dev@posteeringtreasury.com"
  }'
{
  "partner": {
    "id": "ptr_9c70...",
    "organization_name": "Posteering Treasury",
    "email": "dev@posteeringtreasury.com",
    "created_at": "2026-06-13T18:00:00Z"
  },
  "credential": { "id": "crd_2f1a...", "grade": "jwt", "secret": "eyJhbGci..." },
  "hmac_credential": {
    "id": "crd_8d3b...",
    "grade": "hmac",
    "key_id": "oak_3f9c1a7e5b2d4860c8e1f0a2",
    "secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0f9e8d7c6b5a49382"
  }
}

Both secrets are shown once

The JWT secret (your bearer token) and the HMAC key_id + secret appear in this response only and are never retrievable again. The HMAC root does not expire and is your recoverable credential — an expired JWT is always re-mintable via the root with POST /credentials.

Select products and provision

POST /onboard does everything register does and records your product selection, self-provisioning the products that allow it — in one call.

curl -X POST https://one.posteering.com/api/v1/one/onboard \\
  -H "Content-Type: application/json" \\
  -d '{
    "organization_name": "Posteering Treasury",
    "email": "dev@posteeringtreasury.com",
    "entitlements": ["ledger", "bankrail-gateway"],
    "context_reference": "posteering-treasury-prod"
  }'

The result names what was provisioned now versus what awaits approval. It carries no secret — you obtain or re-mint credentials through POST /partners and POST /credentials.

{
  "partner_id": "ptr_9c70...",
  "context_id": "ctx_5a21...",
  "entitlements": ["ledger", "bankrail-gateway"],
  "provisioned": [{ "product": "ledger" }],
  "pending": ["bankrail-gateway"],
  "warnings": []
}

Self-serve vs approval-required

Self-serve products (e.g. ledger) are provisioned immediately and appear in provisioned. Payment rails (e.g. bankrail-gateway) are recorded in pending and become reachable only after an operator approves them. When entitlements include bankrail-gateway, a bankrail classification is required.

Make your first product call

With a credential in hand, you reach a product through passthrough. You sign only your One-API leg; the gateway threads the product's own credential for you.

curl -X POST \\
  https://one.posteering.com/api/v1/one/products/ledger/passthrough/accounts \\
  -H "Content-Type: application/json" \\
  -H "One-Api-Hmac-Key-Id: key_live_..." \\
  -H "One-Api-Hmac-Timestamp: 2026-06-28T10:00:00Z" \\
  -H "One-Api-Hmac-Nonce: 9f2c..." \\
  -H "One-Api-Hmac-Signed-Headers: one-context" \\
  -H "One-Api-Hmac-Signature: <hex-hmac-sha256>" \\
  -H "One-Context: posteering-treasury-prod" \\
  -d '{ "class": "asset", "currencies": ["NGN"] }'

The path after passthrough/ is the product's own route, carried verbatim — here, Ledger's /accounts. The product's response returns unchanged, with its own status code and body.

Don't hand-build the signature

Copy a ready-made signer — curl, JavaScript, Python, Go, or Postman — from Authentication. Each is self-contained and verified against the gateway's own verifier, so a signature it produces is accepted by construction.

In Node

Grab the self-contained signOneApiRequest from Authentication (the JavaScript tab), then call it and send the exact bytes you signed:

// signOneApiRequest — copy it from Authentication (the JavaScript tab).

const body = JSON.stringify({ class: 'asset', currencies: ['NGN'] });
const bodyBytes = Buffer.from(body, 'utf8');

// Sign the consumer leg. Bind the value of any header you want covered
// (here, One-Context) by listing it in signHeaders and supplying its value
// in headerValues.
const { headers } = signOneApiRequest({
  method: 'POST',
  path: '/api/v1/one/products/ledger/passthrough/accounts',
  keyId: process.env.ONE_API_KEY_ID,
  secret: process.env.ONE_API_SECRET,
  bodyBytes,
  signHeaders: ['one-api-hmac-timestamp', 'one-api-hmac-nonce', 'one-context'],
  headerValues: { 'one-context': 'posteering-treasury-prod' },
});

const res = await fetch(
  'https://one.posteering.com/api/v1/one/products/ledger/passthrough/accounts',
  {
    method: 'POST',
    headers: {
      ...headers,
      'Content-Type': 'application/json',
      'One-Context': 'posteering-treasury-prod',
    },
    body,
  },
);
const account = await res.json();

Body is signed as raw bytes

Sign the exact bytes you send. Pass the request body to the signer as bodyBytes (a Buffer) and send those same bytes — don't re-serialize between signing and sending, or the hashes won't match.

What you can call

Once entitled, every product route is reachable through the same passthrough pattern:

  • /products/ledger/passthrough/{path} — accounts, transactions, holds, export
  • /products/bankrail-gateway/passthrough/{path} — virtual accounts, payouts, callbacks

You can also use the One API's own money operations directly — /collections/pool, /payouts — and manage sub-accounts at /partners/me/subaccounts.

Next

On this page