Documentation
Quickstart: your first payment with the API
With a practice agent key you can check the connection with GET /v1/me, request a payment with POST /v1/spends and read the result: a rule-based refusal comes back as a normal response, not as an error.
Before you start
- A practice agent key (
np_test_agent_…). It is created in the console, under API keys, when your access opens. It is shown only once. - An agent with rules: the maximum amount per payment and the allowed destinations.
- An HTTP client. The examples use curl and the base address that
openapi.jsonpublishes.
Step 1: check the connection
GET /v1/me tells you who you are for the API: the key, the agent and the environment. If it answers 200, the key works.
curl https://api.nouronpass.com/v1/me \
-H "Authorization: Bearer $NOURON_API_KEY"A 401 with invalid_api_key or missing_api_key means the key is misspelled or does not arrive; see the errors page.
Step 2: request a payment
POST /v1/spends requests a payment. amount is the MAXIMUM the agent accepts to pay; the vendor sets the final amount. The Idempotency-Key header is required: if you repeat the call with the same key, it is not paid twice.
curl -X POST https://api.nouronpass.com/v1/spends \
-H "Authorization: Bearer $NOURON_API_KEY" \
-H "Idempotency-Key: 7c1f0a52-3e9d-4c1b-9b3e-a41d0b6f2c11" \
-H "Content-Type: application/json" \
-d '{
"amount": "5.00",
"destination": "registry.npmjs.org",
"resource": {
"url": "https://registry.npmjs.org/-/pro/private-packages/month",
"method": "GET"
}
}'Each new attempt uses a new idempotency key; a retry of the same call uses the same one.
Step 3: read the result
The response is a payment with a status. Decide by status, decline_reason and next_action, never by the text of message.
{ "id": "spd_9a2f1a7c0d4e5b3a8c6d7e0f1a2b3c4d", "status": "settled", "amount": "5.00", "amount_settled": "4.80", "destination": "registry.npmjs.org", "decline_reason": null, "next_action": { "code": "none" }}| Status | What it means |
|---|---|
| `pending_approval` | It is above the owner's threshold and waits for approval. Do not retry: check it with GET /v1/spends/{id}. |
| `approved` | It passed the rules and has allowance reserved; it has not been sent yet. |
| `processing` | It was sent and there is no result yet. Check again later. |
| `settled` | Paid. It carries the purchase result and the signed receipt. |
| `declined` | A rule stopped it. It is a decision, not an error: read decline_reason. |
| `failed` | It was approved but the payment failed; no money moved. A new attempt needs a new idempotency key. |
| `expired` | Nobody approved in time and the payment expired. |
| `cancelled` | The agent cancelled it before it was sent. |
A rule-based refusal is not an error
When an owner rule stops a payment, the API answers HTTP 201 with a payment whose status is declined and a stable reason in decline_reason. That way curl -f does not break and a model does not mistake it for a failure.
If something fails
A real error (malformed JSON, invalid key, missing resource) arrives with an HTTP 4xx or 5xx status and the same envelope in every case. Read these fields:
error.code: the stable code. Decide by it.error.retry:nodo not retry,as_isretry the same request with the same idempotency key,after_fixingfix whatmessageandparamsay first.error.outcome_unknown: if true, the payment may have been made; do not retry with another key, check the payment.request_id: give it to support if you need help.
{ "ok": false, "status": 400, "request_id": "req_3z6y1wUd", "error": { "type": "invalid_request_error", "code": "invalid_amount_format", "message": "«abc» no es un monto válido. Usa un número positivo como texto con hasta 6 decimales, por ejemplo \"4.80\".", "param": "amount", "retry": "after_fixing", "retry_after_ms": null, "outcome_unknown": false }}Next steps
- Errors: every code and what to do.
- Events and webhooks: learn about changes without polling.
- Versioning: what may change without notice and what may not.
- Limits: how many requests and of what size.