Traders
Profiles Rubi matches to interviews. id is your stable customer id. Rubi never invents a second id for the same person.
https://risk.example-firm.com/rubi/v1 with no trailing slash. GET /traders is then requested as https://risk.example-firm.com/rubi/v1/traders.Shared rules for authentication, pagination, errors and the live check are on the Own tech overview.
Every call, including GET /health, sends Authorization: Bearer <api key> and Accept: application/json. The key is the secret you paste in the dashboard. Rubi never sends a body: every endpoint is GET.
GET/traders
Returns { data, next_cursor }
Paginated list. Rubi calls this with limit=5 during the live check and limit=200 during sync.
| Query | Required | Rules |
|---|---|---|
updated_since | no | RFC 3339. Return rows with updated_at greater than or equal to this instant. Omitted on the first backfill. |
cursor | no | The next_cursor from the previous page. Ignore it when absent. |
limit | no | 1 to 500. Rubi sends 200 in production syncs. |
Each object in data:
| Field | Type | Description |
|---|---|---|
id | string | Required, stable, unique. Numbers are accepted and stored as strings. The live check fails if this is missing or null. |
updated_at | timestamp | Required. RFC 3339 UTC. Drives incremental sync and cursor order. |
email | string | null | Used to match an interview created with the same email. |
first_name, last_name | string | null | Preferred name fields. |
full_name | string | null | Accepted instead of first and last name. Rubi splits on the first space. |
country | string | null | ISO 3166-1 alpha-2, for example GB. |
phone | string | null | E.164 when you have it. |
registered_at | timestamp | null | When the trader opened an account with you. created_at is accepted as an alias. |
kyc_status | enum | null | One of not_started, pending, verified, failed. |
tags | string[] | Free labels. Omit or send an empty array when you have none. |
metadata | object | null | Stored as-is on the trader. Do not put secrets here. |
{
"data": [
{
"id": "cus_18422",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Doe",
"country": "GB",
"phone": "+447700900123",
"registered_at": "2026-03-02T09:12:44Z",
"kyc_status": "verified",
"tags": ["vip"],
"metadata": { "plan": "funded" },
"updated_at": "2026-09-20T08:00:00Z"
}
],
"next_cursor": "eyJpZCI6ImN1c18xODQyMiJ9"
}curl "https://risk.example-firm.com/rubi/v1/traders?updated_since=2026-09-23T09:50:00Z&limit=200" \
-H "Authorization: Bearer $PROVIDER_KEY" \
-H "Accept: application/json"GET/traders/{id}
Returns Trader
One trader, the same object as a list item, without the data envelope. Answer 404 with the error body when the id is unknown. Rubi uses the list endpoint for sync. Implement the detail endpoint so support and your own tools can fetch one customer the same way.
{ "error": { "code": "not_found", "message": "Unknown trader cus_18422" } }What the live check asserts#
GET /traders?limit=1 without the bearer token must not return 200. Then GET /traders?limit=5 must return a list where every object has id and updated_at. If next_cursor is a non-empty string, the following request with that cursor must succeed.