Skip to content

Enterprise API keys ​

A workspace API key belongs to one workspace and starts with rpe_. Admins and owners manage keys in the dashboard (Developers) or with these endpoints from a dashboard session. A key can never list, create or revoke keys itself, so a leaked key cannot make itself permanent. The rules for using a key are in Enterprise overview.

The three routes share a budget of 60 calls a minute per user. A workspace can have 10 active keys.

Endpoints ​

MethodPathEndpointAuth
GET/v1/enterprise/api-keysList API keysadmin, dashboard only
POST/v1/enterprise/api-keysCreate an API keyadmin, dashboard only
DELETE/v1/enterprise/api-keys/:idRevoke an API keyadmin, dashboard only

List API keys ​

GET/v1/enterprise/api-keys

Active keys, newest first. Only a short preview of each key is shown.

  • Auth: Dashboard session only. API keys, workspace or personal, get 403 KEY_NOT_ALLOWED.
  • Role: admin or owner.
  • Rate limit: 60 a minute per user for this route, plus the shared 300 a minute.
  • Idempotency: Not needed. Reading has no side effects.

Example request ​

bash
curl https://api.rekberpay.com/v1/enterprise/api-keys \
  -b cookies.txt \
  -H "X-Enterprise-Account: $WORKSPACE_ID"
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/api-keys', {
    headers: {
        Cookie: process.env.REKBERPAY_SESSION_COOKIE, // '__Host-rekber_session=...' from POST /v1/auth/login
        'X-Enterprise-Account': process.env.WORKSPACE_ID,
    },
});
const data = await res.json();
python
import os

import requests

session = requests.Session()
# The session cookie from POST /v1/auth/login
session.cookies.set("__Host-rekber_session", os.environ["REKBERPAY_SESSION"], domain="api.rekberpay.com")
resp = session.get(
    "https://api.rekberpay.com/v1/enterprise/api-keys",
    headers={
        "X-Enterprise-Account": os.environ["WORKSPACE_ID"],
    },
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/api-keys');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIEJAR => 'cookies.txt',
    CURLOPT_COOKIEFILE => 'cookies.txt',
    CURLOPT_HTTPHEADER => [
        'X-Enterprise-Account: ' . getenv('WORKSPACE_ID'),
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

Example response ​

200 OK

json
{
    "success": true,
    "data": {
        "items": [
            {
                "id": "44444443-4444-4444-8444-444444444444",
                "label": "BI read-only",
                "scopes": [
                    "read"
                ],
                "key_preview": "rpe_q8Zt…",
                "created_by": {
                    "id": "33333333-3333-4333-8333-333333333333",
                    "name": "Dimas Hidayat"
                },
                "last_used_at": null,
                "created_at": "2026-10-13T14:33:15.359Z",
                "status": "active"
            },
            {
                "id": "22222223-2222-4222-8222-222222222222",
                "label": "ERP sync",
                "scopes": [
                    "read",
                    "write"
                ],
                "key_preview": "rpe_q8Zt…",
                "created_by": {
                    "id": "33333333-3333-4333-8333-333333333333",
                    "name": "Dimas Hidayat"
                },
                "last_used_at": null,
                "created_at": "2026-10-13T14:33:15.354Z",
                "status": "inactive"
            }
        ],
        "limit": 10
    }
}

status is active, or inactive when the key is not revoked but no longer works because the member who created it left the workspace (or was invited again later). Removing a member revokes their keys; revoke an inactive key to free its slot.

Errors ​

StatusCodeCause
401UNAUTHORIZED, SESSION_EXPIRED, INVALID_TOKENNo session or key, the session expired, or the key is wrong or revoked
400INVALID_ACCOUNTX-Enterprise-Account is not a UUID
403NO_WORKSPACEYou are not an active member of that workspace, or the key belongs to another one
403FORBIDDENYour role is below admin
403KEY_NOT_ALLOWEDCalled with an API key instead of a dashboard session
429RATE_LIMITEDOver the rate limit. Wait for Retry-After seconds

A real KEY_NOT_ALLOWED answer:

403 Forbidden

json
{
    "success": false,
    "error": {
        "code": "KEY_NOT_ALLOWED",
        "message": "Workspace API keys cannot call this route. Sign in to the dashboard instead."
    }
}

Create an API key ​

POST/v1/enterprise/api-keys

Creates a key and returns the plaintext in key once. Only its SHA-256 hash is stored, so a lost key cannot be recovered: revoke it and create a new one. A read key can call every GET and acts as a viewer. A read and write key acts with the role of the admin who created it, and stops working if that person leaves the workspace.

  • Auth: Dashboard session only. API keys, workspace or personal, get 403 KEY_NOT_ALLOWED.
  • Role: admin or owner.
  • Rate limit: 60 a minute per user for this route, plus the shared 300 a minute.
  • Idempotency: Not supported on purpose: the plaintext key is never stored in the replay cache. A double submit at most creates a second key that you can revoke.

Body (JSON) ​

NameTypeRequiredDescription
labelstringYes2 to 60 characters
scopesstring[]Yes["read"] or ["read", "write"]

Example request ​

bash
curl -X POST https://api.rekberpay.com/v1/enterprise/api-keys \
  -b cookies.txt \
  -H "X-CSRF-Token: $CSRF_TOKEN" \
  -H "X-Enterprise-Account: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "ERP sync",
    "scopes": [
      "read",
      "write"
    ]
  }'
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/api-keys', {
    method: 'POST',
    headers: {
        Cookie: process.env.REKBERPAY_SESSION_COOKIE, // '__Host-rekber_session=...' from POST /v1/auth/login
        'X-CSRF-Token': process.env.REKBERPAY_CSRF_TOKEN,
        'X-Enterprise-Account': process.env.WORKSPACE_ID,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        label: "ERP sync",
        scopes: [
            "read",
            "write"
        ]
    }),
});
const data = await res.json();
python
import os

import requests

session = requests.Session()
# The session cookie from POST /v1/auth/login
session.cookies.set("__Host-rekber_session", os.environ["REKBERPAY_SESSION"], domain="api.rekberpay.com")
resp = session.post(
    "https://api.rekberpay.com/v1/enterprise/api-keys",
    headers={
        "X-CSRF-Token": os.environ["REKBERPAY_CSRF_TOKEN"],
        "X-Enterprise-Account": os.environ["WORKSPACE_ID"],
    },
    json={
        "label": "ERP sync",
        "scopes": [
            "read",
            "write",
        ],
    },
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/api-keys');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIEJAR => 'cookies.txt',
    CURLOPT_COOKIEFILE => 'cookies.txt',
    CURLOPT_HTTPHEADER => [
        'X-CSRF-Token: ' . getenv('REKBERPAY_CSRF_TOKEN'),
        'X-Enterprise-Account: ' . getenv('WORKSPACE_ID'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'label' => 'ERP sync',
        'scopes' => [
            'read',
            'write',
        ],
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

Example response ​

201 Created

json
{
    "success": true,
    "data": {
        "id": "22222223-2222-4222-8222-222222222222",
        "label": "ERP sync",
        "scopes": [
            "read",
            "write"
        ],
        "key_preview": "rpe_q8Zt…",
        "created_by": {
            "id": "33333333-3333-4333-8333-333333333333",
            "name": null
        },
        "last_used_at": null,
        "created_at": "2026-10-13T14:33:15.355Z",
        "status": "active",
        "key": "rpe_q8Zt3VnK1mW0xPe7Rk2LsY5bHd9JcAf4GuN6oTiQ1vE"
    }
}

Errors ​

StatusCodeCause
400INVALID_BODYLabel or scopes missing or not valid
409KEY_LIMITThe workspace already has 10 active keys
401UNAUTHORIZED, SESSION_EXPIRED, INVALID_TOKENNo session or key, the session expired, or the key is wrong or revoked
400INVALID_ACCOUNTX-Enterprise-Account is not a UUID
403NO_WORKSPACEYou are not an active member of that workspace, or the key belongs to another one
403FORBIDDENYour role is below admin
403KEY_NOT_ALLOWEDCalled with an API key instead of a dashboard session
403CSRF_FAILEDSession call without the matching X-CSRF-Token header
429RATE_LIMITEDOver the rate limit. Wait for Retry-After seconds

A real INVALID_BODY answer:

400 Bad Request

json
{
    "success": false,
    "error": {
        "code": "INVALID_BODY",
        "message": "Invalid request.",
        "details": {
            "formErrors": [],
            "fieldErrors": {
                "label": [
                    "Too small: expected string to have >=2 characters"
                ],
                "scopes": [
                    "Too small: expected array to have >=1 items"
                ]
            }
        }
    }
}

Revoke an API key ​

DELETE/v1/enterprise/api-keys/:id

The key stops working at once. api_key.revoked is recorded in the event feed.

  • Auth: Dashboard session only. API keys, workspace or personal, get 403 KEY_NOT_ALLOWED.
  • Role: admin or owner.
  • Rate limit: 60 a minute per user for this route, plus the shared 300 a minute.
  • Idempotency: Send an Idempotency-Key header (UUID v4). A retry with the same key and body returns the first answer with Idempotent-Replay: true.

Path parameters ​

NameTypeDescription
idUUIDThe key ID from the list

Example request ​

bash
curl -X DELETE https://api.rekberpay.com/v1/enterprise/api-keys/55555553-5555-4555-8555-555555555555 \
  -b cookies.txt \
  -H "X-CSRF-Token: $CSRF_TOKEN" \
  -H "X-Enterprise-Account: $WORKSPACE_ID" \
  -H "Idempotency-Key: 66666663-6666-4666-8666-666666666666"
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/api-keys/55555553-5555-4555-8555-555555555555', {
    method: 'DELETE',
    headers: {
        Cookie: process.env.REKBERPAY_SESSION_COOKIE, // '__Host-rekber_session=...' from POST /v1/auth/login
        'X-CSRF-Token': process.env.REKBERPAY_CSRF_TOKEN,
        'X-Enterprise-Account': process.env.WORKSPACE_ID,
        'Idempotency-Key': '66666663-6666-4666-8666-666666666666',
    },
});
const data = await res.json();
python
import os

import requests

session = requests.Session()
# The session cookie from POST /v1/auth/login
session.cookies.set("__Host-rekber_session", os.environ["REKBERPAY_SESSION"], domain="api.rekberpay.com")
resp = session.delete(
    "https://api.rekberpay.com/v1/enterprise/api-keys/55555553-5555-4555-8555-555555555555",
    headers={
        "X-CSRF-Token": os.environ["REKBERPAY_CSRF_TOKEN"],
        "X-Enterprise-Account": os.environ["WORKSPACE_ID"],
        "Idempotency-Key": "66666663-6666-4666-8666-666666666666",
    },
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/api-keys/55555553-5555-4555-8555-555555555555');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIEJAR => 'cookies.txt',
    CURLOPT_COOKIEFILE => 'cookies.txt',
    CURLOPT_HTTPHEADER => [
        'X-CSRF-Token: ' . getenv('REKBERPAY_CSRF_TOKEN'),
        'X-Enterprise-Account: ' . getenv('WORKSPACE_ID'),
        'Idempotency-Key: 66666663-6666-4666-8666-666666666666',
    ],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

Example response ​

200 OK

json
{
    "success": true,
    "data": {
        "id": "55555553-5555-4555-8555-555555555555",
        "revoked": true
    }
}

Errors ​

StatusCodeCause
404NOT_FOUNDNo active key with this ID
401UNAUTHORIZED, SESSION_EXPIRED, INVALID_TOKENNo session or key, the session expired, or the key is wrong or revoked
400INVALID_ACCOUNTX-Enterprise-Account is not a UUID
403NO_WORKSPACEYou are not an active member of that workspace, or the key belongs to another one
403FORBIDDENYour role is below admin
403KEY_NOT_ALLOWEDCalled with an API key instead of a dashboard session
403CSRF_FAILEDSession call without the matching X-CSRF-Token header
429RATE_LIMITEDOver the rate limit. Wait for Retry-After seconds

Escrow, payment services and B2B deals for Indonesian businesses.