The Fetchit API is a JSON over HTTPS interface to the services behind the desktop application. It is what a phone system reports calls into, and what a partner reads call history back out of.
Everything here is written against the live implementation. If a page and the server disagree, the server is right and the page is a bug worth reporting.
Base address
All endpoints live under one host, and the versioned surface is everything below /api/v1.
https://www.fetchitdata.cloud/api/v1The version lives in the path, never in a header. A breaking change to a resource arrives as /api/v2/... beside the old one, and /api/v1 keeps meaning what it meant. Additive changes, a new optional body field or a new property on a response object, land in place, so a client must ignore properties it does not recognise rather than reject them.
Routes under /api/auth, /api/crm and the older unversioned paths exist and are in use, but they serve the desktop application and the browser extension rather than integrators. They are not part of the documented surface and may change without a version bump.
How a request is shaped
Every call is the same four things.
| Part | Rule |
|---|---|
| Method | POST for anything that writes, GET for anything that reads. |
| Credential | A Client-ID and Client-Secret header pair, or a bearer token. See Authentication. |
| Body | application/json, UTF-8, on every method that takes one. |
| Response | application/json, always, including on every error. |
There is one credential scheme for the whole API. What authenticates one endpoint authenticates all of them, and the only thing that differs between endpoints is which scopes the key has to hold.
The response envelope
Every response, at every status code, is an object with a success boolean.
{
"success": true,
"...": "the endpoint's own properties, at the top level"
}{
"success": false,
"error": "403 Forbidden",
"message": "The provided API key may not report call_recorded."
}error restates the HTTP status. message is a sentence written for the person reading it in a terminal, and where a refusal has a fix, such as a scope the key is missing, the message names it. Match on the status code and on success, not on the text of message.
Status codes
| Code | Meaning |
|---|---|
200 OK | The request succeeded. |
201 Created | The request succeeded and created something: a key, a call record. |
400 Bad Request | The body is malformed, or failed validation. message lists the offending fields. |
401 Unauthorized | No live credential authenticated the request. |
403 Forbidden | The credential is valid but is not permitted this act, or is federated the wrong way for this endpoint. |
404 Not Found | The named resource does not exist, or the credential may not know that it does. |
503 Service Unavailable | A transient database failure. Carries Retry-After, and the same request is safe to send again. |
500 Internal Server Error | An unhandled fault. Report it with the trace id. |
A 401 means fix the credential. A 403 means the credential is fine and the grant is not, so rotating a key will not help.
Trace ids
Every request is logged before it is answered, and every response carries the id of that log row.
X-Trace-ID: cm1f8q0a70000abcd1234wxyzKeep it. It is the fastest way to have a specific request looked at, and it is present on failures as well as successes, including the 500 that has no other detail in it.
Where to go next
- Getting started walks a first request end to end: getting a credential, calling an endpoint, and reading what comes back.
- Authentication is the full specification of the credential: the headers, the scope model, federation, minting and rotation.