Getting started

Developer platform

Sign in, register apps, hold credentials, and read usage, request logs and limits at platform.tabbio.com.

Everything you own as a developer lives at platform.tabbio.com: your apps and their credentials, your API keys, who has connected to you, what you called and how it went, and the limits you are working inside. The documentation you are reading is separate and public; the platform is yours and signed in.

It moved

Credentials used to live inside the Tabbio app under Settings > Developer. They do not any more. The Tabbio app keeps only the two surfaces a person needs: the consent screen and Settings > Connected apps, where they manage what they have shared with you.

Signing in

  1. Open the platform

    Go to platform.tabbio.com. You are asked for an email and a password, or you can ask for a sign-in code by email instead.

  2. Use your Tabbio account, or make a login

    A developer is a Tabbio account. If you already use Tabbio, sign in with it and you are in. If you do not, choose Create a login and make one with your work address. Either way the account is the owner of everything you create next, so use an address your team still controls in two years.

  3. Name yourself

    The first sign-in asks for a display name, and optionally your organisation, website and a contact address. The contact address is what Tabbio writes to about a limit, a deprecation or an incident, so keep it a mailbox somebody reads.

Applications

Applications is the list of everything you have registered, with its client id, type, status, key count, connection count and requests over the last seven days.

An app carries:

  • Client id (tbo_ci_). Public. It identifies you in an authorization request and is safe in a browser bundle or a mobile binary.
  • Client secrets (tbo_cs_). Confidential clients only. A secret is shown once, at creation, and stored hashed. Nobody at Tabbio can read it back to you.
  • Redirect URIs. Matched exactly. A trailing slash, http against a registered https, or an extra query parameter is a different URI and is refused.
  • Allowed scopes. The ceiling on what the app may ask a person for. Asking for anything outside it fails with OAUTH_INVALID_SCOPE.

Rotating a secret

The Credentials tab creates a second secret alongside the first, so you deploy the new one and then delete the old one. There is no overlap window to configure and no downtime if you do it in that order. Delete the old secret as soon as the new one is live: two working secrets is twice the surface.

API keys

API keys (tbo_sk_) are for the partner API, where there is no person in the loop. They are created per app, and the API keys page lists every key across all of your apps with the app it belongs to, its scopes, when it was last used and how many requests it served in the last seven days.

FieldTypeDescription
ScopesRequired

Company scopes only. A key can never carry a user scope, so it can never read a CV that was shared with your app through consent.

ExpiryOptional

Set one for a trial or a contractor integration. An expired key answers API_KEY_INVALID, like a revoked one.

NameEditable

Rename a key at any time. The secret does not change.

RevokeImmediate

Takes effect on the next request. There is no grace period, so deploy the replacement first.

The key is shown once, in full, at creation. If you lose it, create another and revoke the old one; it cannot be shown again.

One key per environment, at least

Sharing a key between staging and production means an incident in one is an incident in both, and revoking becomes a decision instead of a reflex. A key per customer is reasonable too when you resell the integration.

Connections

A connection is one person who went through the consent screen for one of your apps. The Connections tab on an app shows what you already have access to, and nothing more.

FieldTypeDescription
Connection idAlways

The id your access and refresh tokens belong to.

Granted scopesAlways

What they actually approved, which can be less than you asked for.

CV sharedAlways

Whether they picked a CV to share, and nothing about its contents.

Connected and last usedAlways

When it started and when your app last called with it.

NameWith profile

Their display name, only when they granted the profile scope. Your app already reads it from GET /v1/me under the same consent, so the platform reveals nothing new.

There is no email address, no CV content and no browsing history here. Revoking a connection from the platform is the same act as the person revoking it in Settings > Connected apps: the tokens stop working immediately and any durable CV link dies with them. Use it when a customer offboards, not as a way to force a re-consent.

Usage

Usage is the graph of what you called and how it went, over the last 24 hours, 7 days, 30 days or 90 days. Every request is counted, including the ones that failed before your code was reached, which is the point: a 401 loop is invisible in your own logs if the token never got as far as your handler.

Each request is filed under one outcome.

FieldTypeDescription
success2xx, 3xx

It worked.

client_error4xx

Malformed, not found, or refused by a rule. Yours to fix.

auth_error401, 403

A dead credential or a missing scope. Usually one bad deployment, not a pattern.

rate_limited429

You hit a limit. See below.

server_error5xx

Ours. If it persists, mail us with a request id.

Alongside the graph: p50 and p95 latency, so a slow endpoint shows up before a customer reports it, a breakdown by app, endpoint or credential, and Export CSV for the range you are looking at when you want it in your own spreadsheet.

Request log

Logs is the individual requests, newest first, kept for 30 days. Filter by app, outcome, endpoint, status, credential or date, and open a row to see everything stored about it: method, route, status, error code, latency, which credential was used and which connection it belonged to.

The log stores route templates, never bodies, query strings, tokens or raw IP addresses. That is deliberate: a request to a durable CV link carries a live credential in its path, and a log that keeps those is a credential store nobody asked for.

Every /v1 and /oauth response carries an x-request-id header, failures included. Paste it into the log filter to find the exact request. It is also the first thing support asks for.

log-the-request-id.js
const response = await fetch(`${issuer}/v1/companies`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
if (!response.ok) {
  // Log it next to your own trace id: it is what turns "it failed at some point
  // this morning" into one row on the platform.
  console.error("tabbio request failed", {
    status: response.status,
    requestId: response.headers.get("x-request-id"),
  });
}

Limits

Limits shows the plan you are on, the numbers that apply to you, what you have spent today and when each window resets.

PlanRequests per minuteRequests per dayWho gets it
Standard30020,000Every developer account starts here. No request needed.
Elevated1,000200,000Granted on request once your integration is live.
CustomSet by TabbioSet by TabbioAgreed for a volume integration. The platform shows the numbers you were given.

Limits are per developer account, not per app or per key: every app you own draws on one budget, on every /v1 resource route. Two windows run at once, a rolling minute and a UTC day, and each answers 429 with its own code.

CodeHTTPMeaning
RATE_LIMIT_EXCEEDED429You are over the per-minute limit for your developer account. meta.retryAfter is the seconds to wait.
QUOTA_EXCEEDED429You have spent the daily quota for your developer account. meta.retryAfter counts down to the next UTC midnight.
DEVELOPER_ACCOUNT_SUSPENDED403The account is suspended, so every app it owns is refused. Mail developers@tabbio.com.

Read where you stand from the response headers rather than guessing.

HeaderWhat it carries
x-ratelimit-limitRequests allowed in the current minute.
x-ratelimit-remainingRequests left in the current minute.
x-ratelimit-resetEpoch seconds at which the minute window resets.
x-quota-limitRequests allowed in the current UTC day.
x-quota-remainingRequests left today.
x-quota-resetEpoch seconds at the next UTC midnight.
x-request-idOn every /v1 and /oauth response, failures included. The platform's request log is keyed on it, and support asks for it first.

To ask for more, mail developers@tabbio.com from the contact address on your account with what you call, how often, and why the volume is what it is. Errors and rate limits has the per-surface burst tiers that sit underneath these, and the backoff to write.

Account settings

Settings holds your display name, organisation, website and contact address, a password change, and sign out everywhere for when a laptop goes missing. Deleting the Tabbio account itself is done in the Tabbio app, and it takes your apps with it, so transfer anything a customer depends on first.

What next