Developer center
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_…(orAuthorization: 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-keyheader, 1 to 255 characters, on everyPOST,PATCHandDELETE- Money
- Integer minor units plus an ISO 4217 currency:
12800+SGDis 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
fetchorcurlis the SDK; the quickstart has no dependencies
Read in this order
| Page | What you get |
|---|---|
| Quickstart | Create, confirm and read back one test payment from your own machine, in curl or Node, with nothing installed. |
| Integration guide | The minimum production integration: checkout, outcome by webhook, fulfilment evidence, sellers and payouts. |
| Environments | Test and Live as two sets of objects, what a key can reach, and the seeded demo. |
| Idempotency and retries | How to retry safely, what a conflict looks like, and the rate limits. |
| Verify a webhook | Ed25519 verification in Node and Python, and the delivery contract. |
| Integration architecture | Public system boundaries, the payment path and security guarantees, with an interactive diagram. |
| API reference | Every 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.