Skip to content

Quickstart

From API client to your first simulated transaction.

This walks through the shortest path from a fresh API client to a settled test-mode transaction: create a client, mint a token, set up a card product and cardholder, issue a card, and drive a simulated spend against it. Every request below is plain REST over https://api.rigid.fi — no client library required.

Create an API client

In the console, open API clients and create a new client. The client secret is shown exactly once at creation time — store it before leaving the screen. Create an org-wide client (not one pinned to a single programme): this walkthrough's final transactions-list step requires org-wide access.

Mint a token

Exchange the client ID and secret for a bearer token using the client_credentials grant:

curl -X POST https://api.rigid.fi/v1/oauth/token \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -d 'grant_type=client_credentials'
{
  "access_token": "eyJhbGciOiJFUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 1800
}

The token is valid for 30 minutes. See the token endpoint reference and the Authentication guide for the full credential and rate-limit rules.

Create a card product

A card product is the template cards get issued from — network, currency and form factor. iin selects a test-mode issuer identification number:

curl -X POST https://api.rigid.fi/v1/card-products \
  -H "Authorization: Bearer $RIGID_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "programme_id": "<programme-id>",
    "name": "Employee expense card",
    "network": "visa",
    "currency": "USD",
    "form_factor": "virtual",
    "iin": "999901"
  }'

Reference: Create a card product.

Create a cardholder

curl -X POST https://api.rigid.fi/v1/cardholders \
  -H "Authorization: Bearer $RIGID_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "programme_id": "<programme-id>",
    "full_name": "Ada Lovelace",
    "email": "[email protected]",
    "country": "GB"
  }'

Creating a cardholder does not itself clear them to hold a card. Under a KYC-enabled programme, issuance normally waits for a passed verification; where a programme has verified a cardholder out of band, a console admin can record that as an attestation (POST /v1/cardholders/{id}/attestation) from the console's cardholder list. Attestation is an admin-only override — no API client, org-wide or programme-pinned, may call it. The response's kyc_complete field tells you whether that requirement is met — it is true once the cardholder has either passed KYC (kyc_state: "passed") or been attested by a console admin, and card issuance requires it whenever the programme's kyc module is enabled. Reference: Create a cardholder.

Issue a card

curl -X POST https://api.rigid.fi/v1/cards \
  -H "Authorization: Bearer $RIGID_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "card_product_id": "<card-product-id>",
    "cardholder_id": "<cardholder-id>"
  }'

Reference: Issue a card.

Simulate a spend

Test mode drives a simulated authorization over the same wire path a real network would use. This call is deliberately not idempotency-keyed — each accepted request is its own distinct transaction, so no Idempotency-Key header is sent:

curl -X POST https://api.rigid.fi/v1/simulated-spends \
  -H "Authorization: Bearer $RIGID_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "card_id": "<card-id>",
    "amount": { "amount": "42.50", "currency": "USD" },
    "mcc": "5411",
    "merchant_name": "Corner Grocer",
    "channel": "ecommerce"
  }'

The response is 202 Accepted with a correlation handle and the wire identity — it is an acknowledgement, not the decision:

{
  "simulation_id": "0198e2c1-9f3a-7c42-b8d1-6a2f5c0e77b3",
  "accepted_at": "2026-08-07T12:00:00Z",
  "stan": "123456",
  "rrn": "000000418027"
}

stan and rrn are the identifiers the message carried over the wire — useful for correlating against the transaction later. They are null only when the simulator leg failed before a message was built.

The decision itself is not here. Read it with GET /v1/simulated-spends/{id} using the simulation_id above, or receive it asynchronously as an authorization.decided webhook event. Reference: Simulate a spend.

Read the transaction

Once the authorization has decided, list transactions to see the result:

curl "https://api.rigid.fi/v1/transactions?limit=5" \
  -H "Authorization: Bearer $RIGID_API_TOKEN"

Filter with ?state=approved (or declined, partial, reversed, pending) and paginate with cursor. Reference: List transactions.