Skip to main content

Developers · Guide

Authentication

Get a 5-day Bearer token from a credential with the OAuth 2.0 client-credentials grant, send it on every request, and choose the scopes a credential holds.

Every request to the API is made with an access token, and every token comes from an API credential. The API uses the OAuth 2.0 client-credentials grant: your system sends the credential’s Client ID and Client Secret to the token endpoint and gets back a Bearer token.

Get a credential

An Administrator of your organisation creates the credential under Settings > Profile and terms, on the API Access tab, and chooses its scopes. The Client Secret is shown once. See API access in the Help Centre.

Ask for a token

Send the pair to POST /oauth/token on your organisation’s own address, form-encoded, with grant_type=client_credentials. You may send the Client ID and Client Secret in the form body, or with HTTP Basic authentication instead.

Request
curl -X POST "https://your-org.backed.giving/oauth/token" \
  -d grant_type=client_credentials \
  -d client_id=your-client-id \
  -d client_secret=your-client-secret

# or, with HTTP Basic authentication:
curl -X POST "https://your-org.backed.giving/oauth/token" \
  -u your-client-id:your-client-secret \
  -d grant_type=client_credentials
Response 200
{
  "access_token": "q3Vx9LmT2sKp4Rz7Wn1YeB8cD5fG6hJ0kN_aQ-uIoPr",
  "token_type": "Bearer",
  "expires_in": 432000,
  "created_at": 1762650000
}
  • expires_in is 432000 seconds: a token lasts 5 days.
  • There is no refresh token. Each successful request issues a new token; when a request answers 401 invalid_token, ask for a new one.
  • The answer carries Cache-Control: no-store. Keep the token as you keep the secret.
  • The token endpoint takes 30 requests a minute per client_id, counted before the secret is checked. Ask for a token when you need one, not before every call.

Send the token

Send the token on every request in the Authorization header:

curl "https://your-org.backed.giving/api/v2/funding_rounds" \
  -H "Authorization: Bearer $BACKED_TOKEN"
Node.js 18 or later
const host = 'https://your-org.backed.giving';

async function token() {
  const response = await fetch(`${host}/oauth/token`, {
    method: 'POST',
    body: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: process.env.BACKED_CLIENT_ID,
      client_secret: process.env.BACKED_CLIENT_SECRET,
    }),
  });
  if (!response.ok) throw new Error(`token: ${response.status}`);
  return (await response.json()).access_token;
}

const rounds = await fetch(`${host}/api/v2/funding_rounds`, {
  headers: { Authorization: `Bearer ${await token()}` },
}).then((response) => response.json());

A missing, invalid, expired or revoked token answers 401 with invalid_token and WWW-Authenticate: Bearer error="invalid_token". Every request must use HTTPS: one sent over plain HTTP answers 403 https_required and is not processed. See Errors.

Scopes

A credential holds the scopes an Administrator ticked when they created or edited it. Every credential holds read. A write needs its own write scope, and a credential without it is answered 403 insufficient_scope.

Scopes
ScopeWhat it allows
readRead every /api/v2 resource. Every credential holds it.
read:reporting_feedRead the OData v4 reporting feed at /odata/v4.
write:registrationsCreate and edit registration entities and invite their users.
write:applicationsMove funding applications, add notes and replace tags.
write:assessmentsAssign Assessors to applications in an assessment round.
write:post_awardCreate and approve milestones, mark payment batches paid, record contracts.
write:filesUpload files to deliverables, application notes and registration entities.

Who a write acts as

A credential with a write scope acts as one Administrator, chosen under Acts as. Every write runs with that person’s permissions, Data Access Rules and approval limits, so it can do nothing they could not, and the audit log records the credential and the Administrator together. A credential with no enabled Administrator to act as is answered 403 run_as_disabled on every write. The write routes are described in Write API: registrations, applications, notes, tags and assignments and Write API: milestones, payments, contracts and files.

Rate limits

A credential may make 120 requests a minute, the API and the OData feed together. Past that, the API answers 429 rate_limited with a Retry-After header: wait that many seconds, then carry on.