JouloDocs

Accounts

Create a concept account (customer + connection) and list your accounts with their status.

Accounts

An account is the administrative and legal anchor: the EAN, the address, the machtiging, the sessions, and the payout all hang off it. You create it as a concept — it exists and is attributed to you, but until the customer signs their machtiging it doesn't count toward anything.

Create an account

POST /v1/accounts — scope cpo:accounts:write

curl -X POST https://api.joulo.nl/functions/v1/api/v1/accounts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "particulier",
    "display_name": "Jan de Vries",
    "cpo_external_ref": "CUST-100482",
    "payout_handler": "joulo_pays_customer",
    "iban": "NL91ABNA0417164300",
    "person": {
      "full_name": "Jan de Vries",
      "email": "[email protected]",
      "phone": "+31612345678"
    },
    "connection": {
      "ean_code": "871685920000123456",
      "street": "Dorpsstraat",
      "house_number": "1",
      "postal_code": "6971AB",
      "city": "Brummen"
    }
  }'
{
  "ok": true,
  "account_id": "60092124-c768-4191-9c9d-55ef3fc49999",
  "connection_id": "2eca20d8-06ed-4354-a80d-c8c840a1640d",
  "location_id": "…",
  "ean_validation_status": "matched",
  "iban_stored": true,
  "mandate_status": "pending",
  "account": {
    "id": "60092124-…",
    "type": "particulier",
    "display_name": "Jan de Vries",
    "payout_handler": "joulo_pays_customer",
    "cpo_external_ref": "CUST-100482",
    "created_at": "2026-07-20T12:00:00Z"
  }
}

Body

FieldRequiredDescription
typenoparticulier (default), zakelijk, or vve.
display_namenoHuman-readable name for the account.
cpo_external_refrecommendedYour customer number. Used as the idempotency key and to address later session pushes.
payout_handlernojoulo_pays_customer (default) — Joulo pays the customer directly. via_cpo_invoicing — the payout settles through you, and Joulo does not pay the customer directly.
ibanfor payoutThe customer's IBAN (15–34 chars, spaces ignored). Required before a joulo_pays_customer account can become ERE-eligible; not needed for via_cpo_invoicing. Stored encrypted. You can send it here or add it later by re-posting with the same cpo_external_ref.
person.full_nameyesThe natural person who will sign the machtiging.
person.emailnoSignatory email.
person.phonenoSignatory phone.
connection.ean_codeyes18-digit EAN of the connection.
connection.street house_number postal_code cityyesAddress, validated against the EAN.
connection.house_number_additionnoAddition (e.g. A).

Idempotent. Re-posting with the same cpo_external_ref returns the existing account ("idempotent": true) instead of creating a duplicate. A re-post that includes iban stores it on the existing account, so you can add or correct the IBAN after creation.

iban_stored in the response tells you whether the IBAN was saved (false if you sent none, or if storage failed and you should retry).

EAN exclusivity

An EAN can be booked by exactly one party. If the EAN is already registered (on your side or elsewhere), you get 409 ean_in_use. The address is checked against the EAN; a clear mismatch returns 422 ean_address_mismatch.

Errors

HTTPerror
400invalid_type, invalid_payout_handler, invalid_iban, person_required, invalid_ean, address_required
404account_not_found (for a different CPO's account)
409ean_in_use
422ean_address_mismatch

List accounts

GET /v1/accounts — scope cpo:accounts:read

Paginated with ?limit (default 50, max 200) and ?offset. Returns each account with its signatory and per-connection registration + mandate state — so you can track a customer from concept to signed to registered.

{
  "accounts": [
    {
      "id": "60092124-…",
      "type": "particulier",
      "display_name": "Jan de Vries",
      "payout_handler": "joulo_pays_customer",
      "cpo_external_ref": "CUST-100482",
      "created_at": "2026-07-20T12:00:00Z",
      "signatory": { "full_name": "Jan de Vries", "email": "[email protected]" },
      "connections": [
        {
          "connection_id": "2eca20d8-…",
          "ean_code": "871685920000123456",
          "registration_status": "concept",
          "ean_validation_status": "matched",
          "mandate_status": "pending",
          "mandate_valid_from": null
        }
      ]
    }
  ],
  "limit": 50,
  "offset": 0,
  "count": 1
}

mandate_status is pending until the customer signs, then active. registration_status moves conceptingediend once signed and submitted for review.