Keys
Router keys on a token's credit account, each with its own spending limit.
A router key (rf_ai_...) lets an agent call the RFS Router and spend one account's credit. Give each agent its own key, so you can limit or revoke one alone. Secret keys for this API are made on the dashboard, not here. See Router keys.
List router keys
Send the project's secret key as Authorization: Bearer rf_sk_..., from a server.
curl https://relayfor.si/api/project/v1/keys \ -H "Authorization: Bearer $RELAYFOR_SECRET_KEY"Query
accountstringOnly this account's keys: acc_... or its token's mint.
limitinteger1 to 100; default 20.
cursorstringnext_cursor from the page before.
Answer
Answers 200 with RouterKeyList.
{ "data": [ { "id": "key_5128eNz6OrSZ3e1e", "name": "agent-1", "hint": "rf_ai_K7mQ…", "account": "acc_arqp1qhbpvjhzifE", "limit": { "limit_usd": "5", "reset": "daily", "spent_usd": "1.204112", "reserved_usd": "0.02", "remaining_usd": "3.775888", "resets_at": "2026-10-08T00:00:00.000Z" }, "created_at": "2026-10-07T09:20:11.000Z", "last_used_at": "2026-10-07T14:02:58.000Z", "revoked_at": null } ], "next_cursor": null}Its fields
dataobject[]RequiredThe items, newest first.
idstringRequiredThe key's id: key_ and 16 characters.
namestringRequiredWhat uses it, such as the agent's name.
hintstringRequiredThe key's first characters: enough to tell keys apart.
accountstringRequiredThe account it spends: acc_...
limitobject | nullRequiredIts spending limit and what this period used of it; null for none.
limit_usdstringRequiredDollars it may spend each period.
reset"daily" | "weekly" | "monthly"RequiredWhen the limit starts over, at 00:00 UTC.
spent_usdstringRequiredCharged to its calls that started this period.
reserved_usdstringRequiredHeld by its calls of this period still open.
remaining_usdstringRequiredWhat it may still start this period.
resets_atstringRequired00:00 UTC; a week starts on Monday.
created_atstringRequiredWhen it was made, in UTC.
last_used_atstring | nullRequiredWhen it last started a call; null if never.
revoked_atstring | nullRequiredWhen it was revoked; null while it works.
next_cursorstring | nullRequiredPass it as cursor for the next page; null on the last page.
Errors
A 429 or 503 answer carries Retry-After: wait that many seconds, then send the same request again.
Make a router key
The answer carries the key itself (rf_ai_...), and gives it again to a retry with the same Idempotency-Key. Give it to an agent's OpenAI or Anthropic SDK with base URL https://relayfor.si/api/v1. Up to 100 keys per account.
Send the project's secret key as Authorization: Bearer rf_sk_..., from a server.
Send an Idempotency-Key (any unique string, a UUID): a retry with the same key and body gets the first answer back for 24 hours, a secret it carried included.
curl -X POST https://relayfor.si/api/project/v1/keys \ -H "Authorization: Bearer $RELAYFOR_SECRET_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "account": "acc_arqp1qhbpvjhzifE", "name": "agent-1", "limit": { "usd": "5", "reset": "daily" } }'Body
accountstringRequiredThe account it spends: acc_..., or its token's mint.
namestringRequired1 to 48 characters, for people.
limitobject | nullA spending limit; none when left out (the account's balance still holds).
usdstring | numberRequiredDollars per period, like "5" or "12.50".
reset"daily" | "weekly" | "monthly"RequiredWhen it starts over, at 00:00 UTC.
Answer
Answers 201 with NewRouterKey.
{ "id": "key_5128eNz6OrSZ3e1e", "name": "agent-1", "hint": "rf_ai_K7mQ…", "account": "acc_arqp1qhbpvjhzifE", "limit": { "limit_usd": "5", "reset": "daily", "spent_usd": "0", "reserved_usd": "0", "remaining_usd": "5", "resets_at": "2026-10-08T00:00:00.000Z" }, "created_at": "2026-10-07T09:20:11.000Z", "last_used_at": null, "revoked_at": null, "key": "rf_ai_K7mQx2vR9pLw4Tn8Hd3Ys6Bc1Fz5Jg0Ku7Ea2"}Its fields
idstringRequiredThe key's id: key_ and 16 characters.
namestringRequiredWhat uses it, such as the agent's name.
hintstringRequiredThe key's first characters: enough to tell keys apart.
accountstringRequiredThe account it spends: acc_...
limitobject | nullRequiredIts spending limit and what this period used of it; null for none.
limit_usdstringRequiredDollars it may spend each period.
reset"daily" | "weekly" | "monthly"RequiredWhen the limit starts over, at 00:00 UTC.
spent_usdstringRequiredCharged to its calls that started this period.
reserved_usdstringRequiredHeld by its calls of this period still open.
remaining_usdstringRequiredWhat it may still start this period.
resets_atstringRequired00:00 UTC; a week starts on Monday.
created_atstringRequiredWhen it was made, in UTC.
last_used_atstring | nullRequiredWhen it last started a call; null if never.
revoked_atstring | nullRequiredWhen it was revoked; null while it works.
keystring | nullRequiredThe key itself, rf_ai_...: shown in this answer, and again to a retry with the same Idempotency-Key within 24 hours. Null only if it can't be given back: then revoke that key and make another.
Errors
- 400invalid_request
- 400missing_idempotency_key
- 401unauthorized
- 404not_found
- 409idempotency_in_progress
- 413payload_too_large
- 415unsupported_media_type
- 422idempotency_mismatch
- 422too_many_keys
- 429rate_limited
- 500internal
- 503unavailable
A 409, 429, or 503 answer carries Retry-After: wait that many seconds, then send the same request again.
Get a router key
Send the project's secret key as Authorization: Bearer rf_sk_..., from a server.
curl https://relayfor.si/api/project/v1/keys/key_5128eNz6OrSZ3e1e \ -H "Authorization: Bearer $RELAYFOR_SECRET_KEY"Path
idstringRequiredThe key's id: key_...
Answer
Answers 200 with RouterKey.
{ "id": "key_5128eNz6OrSZ3e1e", "name": "agent-1", "hint": "rf_ai_K7mQ…", "account": "acc_arqp1qhbpvjhzifE", "limit": { "limit_usd": "5", "reset": "daily", "spent_usd": "1.204112", "reserved_usd": "0.02", "remaining_usd": "3.775888", "resets_at": "2026-10-08T00:00:00.000Z" }, "created_at": "2026-10-07T09:20:11.000Z", "last_used_at": "2026-10-07T14:02:58.000Z", "revoked_at": null}Its fields
idstringRequiredThe key's id: key_ and 16 characters.
namestringRequiredWhat uses it, such as the agent's name.
hintstringRequiredThe key's first characters: enough to tell keys apart.
accountstringRequiredThe account it spends: acc_...
limitobject | nullRequiredIts spending limit and what this period used of it; null for none.
limit_usdstringRequiredDollars it may spend each period.
reset"daily" | "weekly" | "monthly"RequiredWhen the limit starts over, at 00:00 UTC.
spent_usdstringRequiredCharged to its calls that started this period.
reserved_usdstringRequiredHeld by its calls of this period still open.
remaining_usdstringRequiredWhat it may still start this period.
resets_atstringRequired00:00 UTC; a week starts on Monday.
created_atstringRequiredWhen it was made, in UTC.
last_used_atstring | nullRequiredWhen it last started a call; null if never.
revoked_atstring | nullRequiredWhen it was revoked; null while it works.
Errors
A 429 or 503 answer carries Retry-After: wait that many seconds, then send the same request again.
Change a router key
A limit set mid-period counts what the key's calls already spent and hold in it.
Send the project's secret key as Authorization: Bearer rf_sk_..., from a server.
curl -X PATCH https://relayfor.si/api/project/v1/keys/key_5128eNz6OrSZ3e1e \ -H "Authorization: Bearer $RELAYFOR_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "limit": { "usd": "10", "reset": "daily" } }'Path
idstringRequiredThe key's id: key_...
Body
namestring1 to 48 characters, for people.
limitobject | nullA new limit, or null to remove it.
usdstring | numberRequiredDollars per period, like "5" or "12.50".
reset"daily" | "weekly" | "monthly"RequiredWhen it starts over, at 00:00 UTC.
Answer
Answers 200 with RouterKey.
{ "id": "key_5128eNz6OrSZ3e1e", "name": "agent-1", "hint": "rf_ai_K7mQ…", "account": "acc_arqp1qhbpvjhzifE", "limit": { "limit_usd": "10", "reset": "daily", "spent_usd": "1.204112", "reserved_usd": "0.02", "remaining_usd": "8.775888", "resets_at": "2026-10-08T00:00:00.000Z" }, "created_at": "2026-10-07T09:20:11.000Z", "last_used_at": "2026-10-07T14:02:58.000Z", "revoked_at": null}Its fields
idstringRequiredThe key's id: key_ and 16 characters.
namestringRequiredWhat uses it, such as the agent's name.
hintstringRequiredThe key's first characters: enough to tell keys apart.
accountstringRequiredThe account it spends: acc_...
limitobject | nullRequiredIts spending limit and what this period used of it; null for none.
limit_usdstringRequiredDollars it may spend each period.
reset"daily" | "weekly" | "monthly"RequiredWhen the limit starts over, at 00:00 UTC.
spent_usdstringRequiredCharged to its calls that started this period.
reserved_usdstringRequiredHeld by its calls of this period still open.
remaining_usdstringRequiredWhat it may still start this period.
resets_atstringRequired00:00 UTC; a week starts on Monday.
created_atstringRequiredWhen it was made, in UTC.
last_used_atstring | nullRequiredWhen it last started a call; null if never.
revoked_atstring | nullRequiredWhen it was revoked; null while it works.
Errors
- 400invalid_request
- 401unauthorized
- 404not_found
- 413payload_too_large
- 415unsupported_media_type
- 429rate_limited
- 500internal
- 503unavailable
A 429 or 503 answer carries Retry-After: wait that many seconds, then send the same request again.
Revoke a router key
Send the project's secret key as Authorization: Bearer rf_sk_..., from a server.
curl -X DELETE https://relayfor.si/api/project/v1/keys/key_5128eNz6OrSZ3e1e \ -H "Authorization: Bearer $RELAYFOR_SECRET_KEY"Path
idstringRequiredThe key's id: key_...
Answer
Answers 200 with RouterKey.
{ "id": "key_5128eNz6OrSZ3e1e", "name": "agent-1", "hint": "rf_ai_K7mQ…", "account": "acc_arqp1qhbpvjhzifE", "limit": { "limit_usd": "5", "reset": "daily", "spent_usd": "1.204112", "reserved_usd": "0.02", "remaining_usd": "3.775888", "resets_at": "2026-10-08T00:00:00.000Z" }, "created_at": "2026-10-07T09:20:11.000Z", "last_used_at": "2026-10-07T14:02:58.000Z", "revoked_at": "2026-10-07T15:00:00.000Z"}Its fields
idstringRequiredThe key's id: key_ and 16 characters.
namestringRequiredWhat uses it, such as the agent's name.
hintstringRequiredThe key's first characters: enough to tell keys apart.
accountstringRequiredThe account it spends: acc_...
limitobject | nullRequiredIts spending limit and what this period used of it; null for none.
limit_usdstringRequiredDollars it may spend each period.
reset"daily" | "weekly" | "monthly"RequiredWhen the limit starts over, at 00:00 UTC.
spent_usdstringRequiredCharged to its calls that started this period.
reserved_usdstringRequiredHeld by its calls of this period still open.
remaining_usdstringRequiredWhat it may still start this period.
resets_atstringRequired00:00 UTC; a week starts on Monday.
created_atstringRequiredWhen it was made, in UTC.
last_used_atstring | nullRequiredWhen it last started a call; null if never.
revoked_atstring | nullRequiredWhen it was revoked; null while it works.
Errors
A 429 or 503 answer carries Retry-After: wait that many seconds, then send the same request again.