Request logs
Every API request your organisation made in the last 31 days, with its answer and the credential behind it. Find a failing request by its ID, filter by status, method, caller, path and time, in the dashboard or the API.
FurniOps keeps a log of every API request your organisation makes: who called what, and what it
answered. Use it to debug an integration from the server's side, to find the request behind a
request_id a user reported, or to see what a key has been doing.
Read it in the dashboard under Developers › Logs, or with
GET /v1/request-logs. It needs
request_logs:read, which owners, admins and developers hold, and which an API key can hold.
What is logged
Every request one of your credentials made that reached a route, including the ones FurniOps
refused (a missing permission, a rate limit, a bad FurniOps-Mode header):
{
"object": "request_log",
"id": "req_034aa2WBnMgynuvLmz3Pq8",
"method": "POST",
"path": "/v1/sources/src_034XqBaL2mRLTZPXyRbaUc/runs",
"route": "/v1/sources/{id}/runs",
"query": null,
"status": 429,
"error_code": "quota_exceeded",
"duration_ms": 12,
"actor": { "kind": "api_key", "id": "key_034XqBaL2mRLTZPXyRbaUb" },
"livemode": true,
"api_version": "2026-10-04",
"idempotency_key": "nightly-run-2026-10-06",
"ip": "203.0.113.0/24",
"user_agent": "node",
"created_at": "2026-10-06T09:12:44Z"
}
| Field | Meaning |
|---|---|
id | The request's ID: the Request-Id header of its answer, and the request_id of an error. |
method, path, query | What was asked. |
route | The route it matched (/v1/sources/{id}/runs), for grouping. |
status, error_code | The answer's status, and the problem's code when it failed. |
duration_ms | How long FurniOps took to answer. |
actor | Who made it: an API key (key_…), a member (usr_…), an OAuth app (its client ID), an AI agent, or FurniOps staff through support access. |
livemode | The request's mode. |
api_version | The API version it was answered in. |
idempotency_key | The Idempotency-Key it sent, if any. |
ip, user_agent | Where it came from: the address cut to its /24 or /48, never the full address. |
Bodies and credentials are never logged: neither what you sent nor what FurniOps answered.
Not logged:
- a
401: a request with no usable credential belongs to no organisation; - reading the request logs themselves, so looking never adds to them;
HEADandOPTIONSrequests.
A request appears within seconds. The log is a debugging aid, not a ledger: under extreme load a few entries may be dropped rather than slow your requests. For a record of changes, use the audit log.
How long
Requests are kept 31 days, then deleted.
Each mode apart
Logs belong to a mode. A test key reads the sandbox's requests, a live key the live ones; the dashboard's Logs show the mode the dashboard is in.
Filter
| Filter | Query parameter | Example |
|---|---|---|
| Status class | status | 2xx, 4xx or 5xx |
| Method | method | POST |
| Caller | actor | key_034XqBaL2mRLTZPXyRbaUb, usr_…, or a client ID |
| Path prefix | path | /v1/webhook-endpoints |
| Time | since, until | since is included, until is not |
The list is newest first and pages with limit (up to 100), starting_after and ending_before,
like every list. In the dashboard the filters live in the URL, so a filtered
view can be shared, and a request opens in a side sheet with its request, answer and caller.
With the SDK:
// Every refused request of the last hour, newest first, in the key's mode.
const since = new Date(Date.now() - 60 * 60 * 1000).toISOString();
for await (const log of furniops.requestLogs.list({ status: "4xx", since })) {
console.log(log.created_at, log.method, log.path, log.status, log.error_code, log.actor.id);
}Find one request
Every answer carries a Request-Id header, and every error a request_id. Log it in your client,
then look it up:
// One request, by the `Request-Id` your client logged (or an error's `request_id`).
const log = await furniops.requestLogs.get("req_034aa2WBnMgynuvLmz3Pq8");
console.log(log.route, log.status, `${log.duration_ms} ms`, log.idempotency_key);GET /v1/request-logs/{id} returns the newest request with that ID. Quote the same
ID to FurniOps support.
Usage and quotas
What FurniOps meters, how a month is counted, reading usage with GET /v1/usage, the 80% and 100% threshold events, and what a spent quota refuses.
The Workbench
The dashboard's developer drawer. Send real API requests with your session in test or live mode, copy them as curl, keep this tab's history, and watch webhook health, without creating a key.