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.json publishes.

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.

Check the key
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.

Request a payment
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.

Response (abridged)
{  "id": "spd_9a2f1a7c0d4e5b3a8c6d7e0f1a2b3c4d",  "status": "settled",  "amount": "5.00",  "amount_settled": "4.80",  "destination": "registry.npmjs.org",  "decline_reason": null,  "next_action": {    "code": "none"  }}
Status
StatusWhat 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: no do not retry, as_is retry the same request with the same idempotency key, after_fixing fix what message and param say 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.
An error (400)
{  "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