Skip to main content

Developer center

In one sentence

Pehmen is one JSON REST API under /v1 with environment-bound keys, idempotency on replayable mutations, cursor-paginated lists, one error envelope, and a signed webhook feed you verify against a public key.

Written for the engineer wiring a checkout, a payout run or a back office to Pehmen.

Base URL
https://pehmen-api.huper.technology
Auth
x-api-key: pehmen_test_… (or Authorization: Bearer), minted on Settings → API keys
Workspace
x-pehmen-organization: <workspace id>, shown on the overview and the Quickstart screen
Environment
x-pehmen-environment: test; a key can only name its own
Mutations
idempotency-key header, 1 to 255 characters, on every POST, PATCH and DELETE
Money
Integer minor units plus an ISO 4217 currency: 12800 + SGD is SGD 128.00
Version
Every response carries pehmen-version: 2026-08-01
Machine reference
OpenAPI 3.1, generated from the live route table at boot
SDKs
None. The API is small enough that fetch or curl is the SDK; the quickstart has no dependencies

Read in this order​

PageWhat you get
QuickstartCreate, confirm and read back one test payment from your own machine, in curl or Node, with nothing installed.
Integration guideThe minimum production integration: checkout, outcome by webhook, fulfilment evidence, sellers and payouts.
EnvironmentsTest and Live as two sets of objects, what a key can reach, and the seeded demo.
Idempotency and retriesHow to retry safely, what a conflict looks like, and the rate limits.
Verify a webhookEd25519 verification in Node and Python, and the delivery contract.
Integration architecturePublic system boundaries, the payment path and security guarantees, with an interactive diagram.
API referenceEvery public integration header, endpoint, scope, event and error code.

The shape of a call​

curl -sS -X POST "https://pehmen-api.huper.technology/v1/payment-intents" \
-H "x-api-key: pehmen_test_YOUR_KEY_HERE" \
-H "x-pehmen-organization: YOUR_WORKSPACE_ID" \
-H "x-pehmen-environment: test" \
-H "idempotency-key: order-8812-create" \
-H "content-type: application/json" \
-d '{ "merchant_payment_ref": "pay-8812",
"order": { "merchant_order_ref": "order-8812", "amount_minor": 12800, "currency": "SGD",
"category": "event_ticket", "channel": "web_checkout", "seller_ref": "organizer-41" },
"payment_method": { "family": "CARD" } }'

The response is the payment intent in status CREATED. Nothing is routed until you confirm it, and confirming is where the Gate decides and the router records its trace. Every response, including errors, carries a request-id header minted by the server; quote it when you ask for help.

What the API will refuse, by design​

  • A replayable mutation without the required idempotency-key: 400 idempotency_key_required.
  • A key naming the other environment: 403 environment_mismatch.
  • A key calling anything that needs a person with a fresh second factor (approve, release, publish, mint keys, manage the team, request Live): 403 forbidden, with a message saying that keys cannot step up.
  • An object from another workspace: 404, indistinguishable from one that does not exist.
  • An amount that is not a positive integer, or a JSON number that was already rounded: refused rather than paid.

Where the dashboard fits​

The public integration API contains the operations available to environment-bound API keys. Actions that require a person to be present stay in the dashboard and are intentionally absent from the public OpenAPI document.