Developer docs v0.1.0

Instruments

Reusable payment instruments (card, account, wallet) tokenized by NETOPIA Payments.

Concepts, behaviour and examples: Instruments guide.

GET /v1/customers/:id/instruments

List a customer's instruments

Cursor-paginated (limit, starting_after).

Authentication
Merchant API key
Effect
Read-only.

Path parameters

NameTypeRequiredDescription
idstringyesCustomer ID · 26 chars

Query parameters

NameTypeRequiredDescription
limitintegernoPage size (1–100). · ≥ 1, ≤ 100, default 20
starting_afterstringnoObject ID; return objects after it (ascending ID order). · 26 chars

Responses

StatusMeaningBody / error codes
200Success.object
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "list",
  "url": "string",
  "has_more": false,
  "data": [
    {
      "object": "instrument",
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "type": "card",
      "card": {
        "last4": "string",
        "brand": "string",
        "exp_month": 1,
        "exp_year": 1
      },
      "is_default": false,
      "enrollment_verified_at": "2026-10-25T18:00:00.000Z",
      "created_at": "2026-10-25T18:00:00.000Z"
    }
  ]
}

POST /v1/instruments

Import an instrument token (mock only)

Raw token import works only with NETOPIA_MODE=mock; remote modes return 400 instrument_enrollment_required — use hosted enrollment (POST /v1/enrollments) instead. The first instrument of a customer becomes the default; is_default: true demotes the previous default.

Authentication
Merchant API key
Effect
Attaches an instrument; may change the customer's default; emits instrument.attached.

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Request body

FieldTypeRequiredDescription
customer_idstringyesULID · 26 chars
netopia_tokenstringyes≤ 4096 chars
type"card" | "account" | "wallet"noHosted enrollment always produces card. · default "card"
card_last4stringno4 chars
card_brandstringno≤ 20 chars
card_exp_monthintegerno≥ 1, ≤ 12
card_exp_yearintegerno≥ 2000, ≤ 3000
is_defaultbooleanno
Example request
{
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "netopia_token": "string",
  "type": "card",
  "card_last4": "string",
  "card_brand": "string",
  "card_exp_month": 1,
  "card_exp_year": 2000,
  "is_default": false
}

Responses

StatusMeaningBody / error codes
201Instrument attached.Instrument
400Remote mode: use hosted enrollment.instrument_enrollment_required
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "instrument",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "type": "card",
  "card": {
    "last4": "string",
    "brand": "string",
    "exp_month": 1,
    "exp_year": 1
  },
  "is_default": false,
  "enrollment_verified_at": "2026-10-25T18:00:00.000Z",
  "created_at": "2026-10-25T18:00:00.000Z"
}

GET /v1/instruments/:id

Retrieve an instrument

Authentication
Merchant API key
Effect
Read-only.

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Responses

StatusMeaningBody / error codes
200Success.Instrument
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "instrument",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "type": "card",
  "card": {
    "last4": "string",
    "brand": "string",
    "exp_month": 1,
    "exp_year": 1
  },
  "is_default": false,
  "enrollment_verified_at": "2026-10-25T18:00:00.000Z",
  "created_at": "2026-10-25T18:00:00.000Z"
}

DELETE /v1/instruments/:id

Detach an instrument

Soft delete; past charges keep referencing it. Live subscriptions (trialing, active, past_due, paused) using it switch to the customer's oldest remaining instrument.

Authentication
Merchant API key
Effect
Detaches the instrument and re-points affected subscriptions; emits instrument.detached (with replacement_instrument_id).

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Responses

StatusMeaningBody / error codes
200Success.DeletedObject
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
409Live subscriptions use it and no replacement exists.instrument_in_use
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "string",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "deleted": true
}