Skip to main content

Developers · Reference

Contracts

Contracts and their recorded statuses. 3 operations: parameters, request body and answers, with examples.

GET /api/v2/contracts

List contracts.

Every contract of the Organisation in ascending id order, at most 50 a page.

  • Operation ID: listContracts
  • Authentication: A Bearer token from a credential holding the read scope.
  • Also served at /funding_system/api/v2/contracts, the documented product’s alias path.
Example request
curl "https://your-org.backed.giving/api/v2/contracts" \
  -H "Authorization: Bearer $BACKED_TOKEN"

Parameters

Parameters of GET /api/v2/contracts
NameInRequiredTypeDescription
limitqueryNointegerResults per page (default 50, at most 50; a larger value is read as 50). Not an integer, or below 1: 400. Example: 50.
gtqueryNointegerReturn records with an id greater than this value. Page forward by passing the last id you received. Example: 1287.
ltqueryNointegerReturn records with an id less than this value.

200 response

A JSON array of contracts.

Fields of Contract
FieldTypeRequiredNotes
idintegerYes
created_atstringYes
updated_atstringYes
titlestringYes
amountstring | nullYes
contract_start_datestring | nullYes
contract_end_datestring | nullYes
statestringYesOne of draft, sent, partially_signed, declined, signed, completed, withdrawing, withdrawn, terminating, terminated.
contract_typestringYesOne of standard, variation.
registration_entityobjectYes
lock_versionintegerYes
Example 200 response
[
  {
    "id": 640,
    "created_at": "2026-03-02T21:15:04.000Z",
    "updated_at": "2026-06-18T03:40:11.000Z",
    "title": "Funding agreement: Te Awa river restoration",
    "amount": "24500.0",
    "contract_start_date": "2026-08-01",
    "contract_end_date": "2027-07-31",
    "state": "signed",
    "contract_type": "standard",
    "registration_entity": {
      "id": 311,
      "name": "Te Awa Restoration Trust"
    },
    "lock_version": 1
  }
]

400 response

A query parameter is invalid, or a write’s body is not a JSON object.

Example 400 response
{
  "error": "invalid_request",
  "error_description": "limit is invalid"
}

401 response

The token is missing, invalid, expired or revoked, of another Organisation, or API access is not Full. Ask for a new token.

Headers: WWW-Authenticate.

Example 401 response
{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired"
}

403 response

The request was sent over plain HTTP and was not processed.

Example 403 response
{
  "error": "https_required"
}

404 response

An unknown host or path, or an id that is unknown, deleted or of another Organisation.

Example 404 response
{
  "error": "not_found"
}

429 response

A rate limit was exceeded: 120 requests a minute per credential, 30 token requests a minute per client_id.

Headers: Retry-After.

Example 429 response
{
  "error": "rate_limited",
  "error_description": "Too many requests"
}

500 response

An unexpected server error.

Example 500 response
{
  "error": "server_error"
}

503 response

The Organisation’s API access cannot be determined, or a dependency is unavailable. Retry after the given seconds.

Headers: Retry-After.

Example 503 response
{
  "error": "temporarily_unavailable"
}

GET /api/v2/contracts/{id}

Get one contract.

The same object as the list item.

  • Operation ID: getContract
  • Authentication: A Bearer token from a credential holding the read scope.
  • Also served at /funding_system/api/v2/contracts/{id}, the documented product’s alias path.
Example request
curl "https://your-org.backed.giving/api/v2/contracts/42" \
  -H "Authorization: Bearer $BACKED_TOKEN"

Parameters

Parameters of GET /api/v2/contracts/{id}
NameInRequiredTypeDescription
idpathYesintegerThe record id. Anything but a positive integer is 404. Example: 42.

200 response

The contract.

Fields of Contract
FieldTypeRequiredNotes
idintegerYes
created_atstringYes
updated_atstringYes
titlestringYes
amountstring | nullYes
contract_start_datestring | nullYes
contract_end_datestring | nullYes
statestringYesOne of draft, sent, partially_signed, declined, signed, completed, withdrawing, withdrawn, terminating, terminated.
contract_typestringYesOne of standard, variation.
registration_entityobjectYes
lock_versionintegerYes
Example 200 response
{
  "id": 640,
  "created_at": "2026-03-02T21:15:04.000Z",
  "updated_at": "2026-06-18T03:40:11.000Z",
  "title": "Funding agreement: Te Awa river restoration",
  "amount": "24500.0",
  "contract_start_date": "2026-08-01",
  "contract_end_date": "2027-07-31",
  "state": "signed",
  "contract_type": "standard",
  "registration_entity": {
    "id": 311,
    "name": "Te Awa Restoration Trust"
  },
  "lock_version": 1
}

401 response

The token is missing, invalid, expired or revoked, of another Organisation, or API access is not Full. Ask for a new token.

Headers: WWW-Authenticate.

Example 401 response
{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired"
}

403 response

The request was sent over plain HTTP and was not processed.

Example 403 response
{
  "error": "https_required"
}

404 response

An unknown host or path, or an id that is unknown, deleted or of another Organisation.

Example 404 response
{
  "error": "not_found"
}

429 response

A rate limit was exceeded: 120 requests a minute per credential, 30 token requests a minute per client_id.

Headers: Retry-After.

Example 429 response
{
  "error": "rate_limited",
  "error_description": "Too many requests"
}

500 response

An unexpected server error.

Example 500 response
{
  "error": "server_error"
}

503 response

The Organisation’s API access cannot be determined, or a dependency is unavailable. Retry after the given seconds.

Headers: Retry-After.

Example 503 response
{
  "error": "temporarily_unavailable"
}

POST /api/v2/contracts/{id}/status

Record a contract executed or terminated.

executed is the Administrator’s counter-signature (contracts.counter_sign); terminated is Terminate Contract (contracts.terminate) and needs a reason. Needs the Contracts module.

  • Operation ID: recordContractStatus
  • Authentication: A Bearer token from a credential holding the write:post_award scope. Runs as the credential’s Administrator, and needs an Idempotency-Key header.
Example request
curl -X POST "https://your-org.backed.giving/api/v2/contracts/42/status" \
  -H "Authorization: Bearer $BACKED_TOKEN" \
  -H "Idempotency-Key: 7d1f0c2e-5b8a-4f3e-9c61-2a4b8e9d0f13" \
  -H "Content-Type: application/json" \
  -d '{"status":"executed"}'

Parameters

Parameters of POST /api/v2/contracts/{id}/status
NameInRequiredTypeDescription
idpathYesintegerThe record id. Anything but a positive integer is 404. Example: 42.
Idempotency-KeyheaderYesstringA key of 1 to 255 characters, unique per write. A retry with the same key, method, path and body within 24 hours answers the first response again (with Idempotent-Replayed: true) and writes nothing. Example: 7d1f0c2e-5b8a-4f3e-9c61-2a4b8e9d0f13.

Request body

application/json, the ContractStatusChange schema. The status to record: executed (the Administrator’s counter-signature) or terminated (with a reason). Any other value is 409 invalid_transition.

Fields of the ContractStatusChange body
FieldTypeRequiredNotes
statusstringYes
reasonstringNo
Example request body
{
  "status": "executed"
}

200 response

The contract as the single read answers it.

Headers: Idempotent-Replayed.

Fields of Contract
FieldTypeRequiredNotes
idintegerYes
created_atstringYes
updated_atstringYes
titlestringYes
amountstring | nullYes
contract_start_datestring | nullYes
contract_end_datestring | nullYes
statestringYesOne of draft, sent, partially_signed, declined, signed, completed, withdrawing, withdrawn, terminating, terminated.
contract_typestringYesOne of standard, variation.
registration_entityobjectYes
lock_versionintegerYes
Example 200 response
{
  "id": 640,
  "created_at": "2026-03-02T21:15:04.000Z",
  "updated_at": "2026-06-18T03:40:11.000Z",
  "title": "Funding agreement: Te Awa river restoration",
  "amount": "24500.0",
  "contract_start_date": "2026-08-01",
  "contract_end_date": "2027-07-31",
  "state": "signed",
  "contract_type": "standard",
  "registration_entity": {
    "id": 311,
    "name": "Te Awa Restoration Trust"
  },
  "lock_version": 1
}

400 response

idempotency_key_required: The write has no Idempotency-Key header of 1 to 255 characters. invalid_request: A query parameter is invalid, or a write’s body is not a JSON object.

Example 400 response: idempotency_key_required
{
  "error": "idempotency_key_required",
  "error_description": "A write needs an Idempotency-Key header of 1 to 255 characters"
}
Example 400 response: invalid_request
{
  "error": "invalid_request",
  "error_description": "limit is invalid"
}

401 response

The token is missing, invalid, expired or revoked, of another Organisation, or API access is not Full. Ask for a new token.

Headers: WWW-Authenticate.

Example 401 response
{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired"
}

403 response

https_required: The request was sent over plain HTTP and was not processed. insufficient_scope: The credential does not hold the scope the route needs. run_as_disabled: The credential has no run-as Administrator, or that person is no longer one. forbidden: The run-as Administrator lacks the permission, or the record is outside their Data Access Rules.

Headers: WWW-Authenticate.

Example 403 response: https_required
{
  "error": "https_required"
}
Example 403 response: insufficient_scope
{
  "error": "insufficient_scope",
  "error_description": "This credential lacks the write:applications scope"
}
Example 403 response: run_as_disabled
{
  "error": "run_as_disabled",
  "error_description": "This credential has no enabled run-as Administrator"
}
Example 403 response: forbidden
{
  "error": "forbidden",
  "error_description": "The run-as Administrator may not do this to this record"
}

404 response

not_found: An unknown host or path, or an id that is unknown, deleted or of another Organisation. module_disabled: The Organisation has the module this route belongs to turned off.

Example 404 response: not_found
{
  "error": "not_found"
}
Example 404 response: module_disabled
{
  "error": "module_disabled",
  "error_description": "This module is not enabled for the Organisation"
}

409 response

idempotency_in_progress: The first request with this Idempotency-Key has not finished. Nothing was written; retry after the given seconds. invalid_transition: The move is not open from where the record stands; current_status says where that is. invalid_state: The record is not in a state that admits this write.

Headers: Retry-After.

Example 409 response: idempotency_in_progress
{
  "error": "idempotency_in_progress",
  "error_description": "The first request with this Idempotency-Key has not finished. If this persists it stopped part-way: check whether the record exists before writing again with a new key"
}
Example 409 response: invalid_transition
{
  "error": "invalid_transition",
  "error_description": "The record cannot make this move from approved",
  "current_status": "approved"
}
Example 409 response: invalid_state
{
  "error": "invalid_state",
  "error_description": "The target does not take files in its current state"
}

413 response

The body, or the declared file, is larger than the limit that applies.

Example 413 response
{
  "error": "payload_too_large",
  "error_description": "The request body is too large"
}

415 response

The body is not application/json, or the target does not accept the file’s content type.

Example 415 response
{
  "error": "unsupported_media_type",
  "error_description": "The request body must be application/json"
}

422 response

idempotency_key_reused: The Idempotency-Key was used in the last 24 hours for a different method, path or body. unknown_field: The body has a property the route does not document; the first is named. validation_failed: Body values the product’s own form would refuse; fields names each.

Example 422 response: idempotency_key_reused
{
  "error": "idempotency_key_reused",
  "error_description": "This Idempotency-Key was used for a different request"
}
Example 422 response: unknown_field
{
  "error": "unknown_field",
  "error_description": "bank_account_number is not a writable field"
}
Example 422 response: validation_failed
{
  "error": "validation_failed",
  "error_description": "Invalid fields: due_date",
  "fields": [
    "due_date"
  ]
}

429 response

A rate limit was exceeded: 120 requests a minute per credential, 30 token requests a minute per client_id.

Headers: Retry-After.

Example 429 response
{
  "error": "rate_limited",
  "error_description": "Too many requests"
}

500 response

An unexpected server error.

Example 500 response
{
  "error": "server_error"
}

503 response

The Organisation’s API access cannot be determined, or a dependency is unavailable. Retry after the given seconds.

Headers: Retry-After.

Example 503 response
{
  "error": "temporarily_unavailable"
}