Own tech
If your firm does not run Axcera, expose these read only endpoints on your own platform. Rubi polls them, upserts by id, and uses the data to prepare interviews and score trading activity.
Transport#
- HTTPS only, TLS 1.2 or later, JSON bodies in UTF-8.
- You choose the base URL, for example
https://risk.example-firm.com/rubi/v1. Every path below is appended to it. No trailing slash. - Authentication is a static secret you generate, sent as
Authorization: Bearer <api key>. Rotate it whenever you want and paste the new value in the Rubi dashboard. Rubi also sendsAccept: application/json. - Restrict the API to the Rubi egress IP ranges shown under Integrations. Each range has a copy button.
- Rubi never writes. A request without the key must not return 200.
- Timestamps are RFC 3339 in UTC (
2026-09-23T14:05:00Z). Money is a JSON number. Unknown optional fields may benullor omitted.
Pagination#
List endpoints accept these query parameters and must keep a stable order.
| Parameter | Type | Rules |
|---|---|---|
updated_since | timestamp | Return records whose updated_at is greater than or equal to this value. Omit the filter when the parameter is absent. |
cursor | string | Opaque value you returned as next_cursor. Absent on the first page. |
limit | integer | Page size. Rubi sends 5 during the live check and 200 during sync. Accept 1 to 500. Default 100 if omitted. |
The response shape is { "data": [...], "next_cursor": "..." }. next_cursor is null on the last page. Rubi also accepts the array under items, results or records, or a bare JSON array, but data is the contract to implement.
Order records by updated_at ascending, then id ascending, so a cursor never skips a row that was updated while a page was being read. Returning the same record twice is safe: Rubi upserts by id.
updated_since equal to the previous success minus 10 minutes. Implement the filter as greater than or equal to.Sync cadence#
| Resource | First run | Later runs |
|---|---|---|
| Traders | Every trader. updated_since is omitted. | updated_since with the 10 minute overlap, page size 200. |
| Accounts | Every account. updated_since is omitted. | Same overlap as traders. |
| Trades | updated_since set to 90 days ago, even on the first run. | updated_since with the 10 minute overlap. |
| Payouts | Every payout, unless the endpoint answers 404. | Same overlap as traders. A later 404 stops payout sync. |
The default interval is 5 minutes, configurable from 1 to 60 minutes in the dashboard or via the integrations API.
Errors, limits and latency#
Use the matching HTTP status and this body:
{ "error": { "code": "not_found", "message": "Unknown trader cus_18422" } }| Status | When | What Rubi does |
|---|---|---|
| 401 or 403 | Missing or rejected key, or an IP that is not allowlisted. | The live check fails. Sync stops until you fix the key or the allowlist. |
| 404 | Unknown single resource, or payouts you do not expose. | A missing trader is an error. Payouts 404 is accepted and payout sync is skipped. |
| 429 | You are throttling. | Rubi reads Retry-After in seconds (clamped from 1 to 60, otherwise waits 10) and retries. |
| 5xx or timeout | Your server failed or took more than 20 seconds. | Rubi retries with backoff. The dashboard shows the endpoint and the status. |
| 200 with invalid JSON | Body is not a JSON object with the expected fields. | Reported as an unexpected response. The check fails. |
Support at least 5 requests per second. Aim to answer within 10 seconds: the live check warns above that. The hard timeout is 20 seconds.
Live check#
Saving the connection runs these steps in order. Polling starts only when every required step passes.
GET /healthreturns 200 and{ "status": "ok" }.GET /traders?limit=1without anAuthorizationheader does not return 200. Answer 401 or 403.GET /traders?limit=5returns the list shape. Every record has non-nullidandupdated_at.- When
next_cursoris a non-empty string,GET /traders?limit=5&cursor=...loads the next page. A single page is skipped, not failed. GET /accounts?limit=5returns records withid,trader_idandupdated_at.GET /trades?limit=5returns records withid,account_id,symbol,side,open_timeandupdated_at.GET /payouts?limit=5returns records withid,trader_id,statusandupdated_at, or answers 404.
Each step shows its status, latency and a hint in the dashboard. The last error keeps the endpoint and the HTTP status.
Connect from the dashboard
- Open Integrations and choose Own tech.
- Paste the base URL and the bearer key.
- Run the live check. Fix any failed step, then save.
The same connection can be created with POST /v1/integrations using "kind": "custom_api". See the integrations endpoints.