Reference

API reference

Generated from the Tabbio API source, so an endpoint listed here exists and an endpoint that exists is listed here. Version 2.0.0.

Base URL

Every request goes to https://server.tabbio.com. The consent screen is the one exception: it is a browser page on https://app.tabbio.com/oauth/authorize, because a person has to see it.

Point a standard OAuth client at https://server.tabbio.com/.well-known/oauth-authorization-server and every endpoint below is configured for you.

Response envelope

Every JSON response carries the same three keys. Read data on success and error on failure. meta holds paging information on list endpoints and is null elsewhere.

Success
{
  "data": { "id": "usr_2f8a", "name": "Sara Ahmed" },
  "error": null,
  "meta": null
}
Failure
{
  "data": null,
  "error": {
    "code": "OAUTH_INSUFFICIENT_SCOPE",
    "message": "This token does not carry the cv:read scope."
  },
  "meta": null
}

Four things are deliberately not wrapped: POST /oauth/token and POST /oauth/introspect, which answer the flat bodies RFC 6749 and RFC 7662 define, the discovery document, where RFC 8414 does, and the PDF endpoints, which stream a file. POST /oauth/revoke keeps the envelope, because RFC 7009 specifies no success body of its own. The field tables on the endpoint pages already show the unwrapped shape, so what you read there is what sits inside data.

Pagination

Every list endpoint is page based. Pass page (1 based, defaults to 1) and pageSize (1 to 100, defaults to 25). There are no cursors anywhere in this API.

A page
{
  "data": [ /* one page of records */ ],
  "error": null,
  "meta": { "page": 1, "pageSize": 25, "total": 63, "totalPages": 3 }
}

Stop when page reaches totalPages, or when a page comes back shorter than pageSize. Records are ordered newest first, so a job posted while you are paging shifts later records by one; if you are reconciling rather than browsing, key on the record id rather than the position.

Authentication

Both schemes are HTTP bearer tokens. Which one you use depends on whether a person is involved.

User access token

A user access token (`tbo_at_...`) obtained through Sign in with Tabbio. Send it as `Authorization: Bearer <token>`.

Request header
Authorization: Bearer tbo_at_5Kd9xQ2mVr7tN0pLzY4bHwR3jS8cF1gU

API key

A server-to-server API key (`tbo_sk_...`) created in Tabbio under Settings, Developer. Send it as `Authorization: Bearer <key>`. Available scopes: `companies:read`, `companies:write`, `jobs:read`, `jobs:write`, `candidates:read`.

Request header
Authorization: Bearer tbo_sk_9Fh3xK7mQr2tV0nLzB6yWd4Sc8Jg1Up5Rt7

Every credential is prefixed, which is what lets a secret scanner recognise one in a commit.

PrefixCredentialNotes
tbo_ci_Client idPublic. Safe to ship in a browser or a mobile app.
tbo_cs_Client secretServer side only. Shown once when you create or rotate it.
tbo_sk_API keyServer side only. Carries company scopes, never user scopes.
tbo_ac_Authorization codeSingle use, valid for 10 minutes.
tbo_at_Access tokenValid for one hour.
tbo_rt_Refresh tokenValid for 90 days and rotated on every use.

Scopes

A user grants scopes on the consent screen. They may grant fewer than you asked for, so read the scope field on the token response rather than assuming you got what you requested.

ScopeGrants
profileName, username, headline, language and public profile link. The photo is only shared if the user allows it.
emailThe verified email address on the Tabbio account.
cv:readThe CV the user chose to share, kept up to date automatically, as structured data and as a PDF.
cv:contactPhone number, full address, date of birth, nationality and similar personal details from that CV.

API keys carry company scopes instead. They are chosen when you create the key and never change.

ScopeGrants
companies:readList and read the companies your app manages.
companies:writeCreate company pages and update their details.
jobs:readList and read jobs at those companies.
jobs:writeCreate, publish, update, close and archive jobs.
candidates:readList applicants and read one application in full.

Errors

The code is stable and safe to branch on. The message is written for a human reading a log and can change at any time.

CodeHTTPMeaning
OAUTH_INVALID_REQUEST400A required parameter is missing or malformed.
OAUTH_INVALID_CLIENT401Unknown client id, or client authentication failed.
OAUTH_INVALID_GRANT400The code or refresh token is expired, already used, issued to another client, or the PKCE verifier does not match.
OAUTH_INVALID_SCOPE400You asked for a scope the app is not allowed to request, or tried to widen a grant on refresh.
OAUTH_UNAUTHORIZED_CLIENT400The app may not use this grant type.
OAUTH_UNSUPPORTED_GRANT_TYPE400Only authorization_code and refresh_token exist.
OAUTH_ACCESS_DENIED403The user declined on the consent screen.
OAUTH_INVALID_TOKEN401The access token is missing, expired, or revoked.
OAUTH_INSUFFICIENT_SCOPE403The token is valid but the user did not grant the scope this endpoint needs.
API_KEY_INVALID401The API key is missing, expired, or revoked.
API_KEY_INSUFFICIENT_SCOPE403The key is valid but does not carry the scope this endpoint needs.
COMPANY_NOT_MANAGED_BY_APP403The company, job or application belongs to a company your app did not create.
PUBLIC_API_VALIDATION_ERROR400The body failed validation, or a job did not satisfy the publish contract. The message names the field.
JOB_NOT_FOUND404No job with this id.
APPLICATION_NOT_FOUND404No application with this id.
CV_NOT_FOUND404The account has no CV to share yet.
CV_LINK_NOT_FOUND404The durable CV link is unknown, was revoked, or the user disconnected the app.
CONNECTION_NOT_FOUND404The connection behind this token is gone.
DEVELOPER_PLATFORM_DISABLED404The developer platform is switched off for this deployment.
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.

The errors guide covers what to do about each one.

Rate limits

Over the limit answers 429. Back off and retry: a burst limit clears within seconds. Partner API calls are counted against your app, so every key you own shares one budget; user token calls are counted against the connection; and the OAuth endpoints are counted against your client id, falling back to the client IP when a request names no client.

SurfaceBurstSustainedCounted against
/oauth/token, /oauth/revoke, /oauth/introspect20 requests per 10 seconds1200 per hourYour client id, falling back to the client IP
/v1/* with an API key20 requests per second3000 per minuteYour app
/v1/me* with an access token20 requests per second3000 per minuteThe connection
GET /v1/cv-links/{token}60 requests per second2000 per minuteClient IP

Versioning

The partner API is versioned in the path. Everything under /v1 keeps its shape: fields are added, never removed or retyped, and a new field can appear in a response at any time, so parse leniently. A change that would break a client ships as /v2 alongside /v1.

This page describes version 2.0.0 of the document. https://server.tabbio.com/v1/openapi.json serves the live version, which is what an SDK generator or a coding agent should read.

OAuth endpoints are not versioned, because they implement published standards rather than a Tabbio shape.

Endpoints