Ghost
ResourcesPricingSecurity
Get started
ResourcesConsent API reference

On this page

  • Authentication
  • Base URL
  • Create a consent record
  • List consent records
  • Get a consent record
  • Withdraw consent
  • Error handling
  • Rate limits

Consent API reference

Create, list, retrieve, and withdraw consent records programmatically using the Ghost REST API and bearer-token authentication.

Last updated April 2026

Authentication

Every API request must include a valid API key in the Authorization header using the Bearer scheme:

http
Authorization: Bearer gst_your_key_here

API keys are created in Settings > API Keys. Each key has one or more scopes that control which endpoints it can access:

  • consent:read — list and retrieve consent records.
  • consent:write — create consent records and record withdrawals.

Keys are prefixed with gst_ and shown in full only once at creation time. Ghost stores a SHA-256 hash, so lost keys cannot be recovered — revoke and create a new one instead.

Base URL

All endpoints are served from:

https://ghostredact.app/api/v1

Requests must use HTTPS and include Content-Type: application/json for request bodies.

Create a consent record

POST /api/v1/consent

Scope required: consent:write

Request body

FieldTypeRequiredDescription
subject_identifierstringYesThe data subject (e.g. email address). Max 500 chars.
purposestringYesWhy consent was collected. Max 1 000 chars.
consent_atstringNoISO 8601 timestamp. Defaults to now.
collection_methodstringNoOne of: web_form, paper_form, verbal, email, api, sdk, implied, other.
expires_atstringNoISO 8601 expiry date for the consent.
client_idstringNoTarget matter UUID. Defaults to the organisation's first active matter.
collection_referencestringNoYour external reference. Max 200 chars.
notice_versionstringNoPrivacy notice version shown. Max 200 chars.
wording_versionstringNoConsent wording version. Max 200 chars.

Example request

bash
curl -X POST https://ghostredact.app/api/v1/consent \
  -H "Authorization: Bearer gst_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "subject_identifier": "user@example.com",
    "purpose": "Marketing emails",
    "consent_at": "2026-04-18T10:00:00Z",
    "collection_method": "web_form"
  }'

Example response

Returns 201 Created:

json
{
  "data": {
    "id": "cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "subject_identifier": "user@example.com",
    "purpose": "Marketing emails",
    "status": "active",
    "consent_at": "2026-04-18T10:00:00Z",
    "collection_method": "web_form",
    "collection_reference": null,
    "notice_version": null,
    "wording_version": null,
    "expires_at": null,
    "created_at": "2026-04-18T10:05:32Z"
  }
}

List consent records

GET /api/v1/consent

Scope required: consent:read

Query parameters

ParamTypeDefaultDescription
statusstring—Filter by status (e.g. active, withdrawn).
subjectstring—Case-insensitive substring match on subject_identifier. Max 200 chars.
limitinteger100Page size, 1–500.
offsetinteger0Number of records to skip.

Example request

bash
curl https://ghostredact.app/api/v1/consent?status=active&limit=10 \
  -H "Authorization: Bearer gst_your_key_here"

Example response

Returns 200 OK:

json
{
  "data": [
    {
      "id": "cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "subject_identifier": "user@example.com",
      "purpose": "Marketing emails",
      "status": "active",
      "consent_at": "2026-04-18T10:00:00Z",
      "collection_method": "web_form",
      "expires_at": null,
      "created_at": "2026-04-18T10:05:32Z"
    }
  ],
  "total": 1,
  "limit": 10,
  "offset": 0
}

Get a consent record

GET /api/v1/consent/{id}

Scope required: consent:read

Returns the full consent record including its withdrawals array.

Example request

bash
curl https://ghostredact.app/api/v1/consent/cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c \
  -H "Authorization: Bearer gst_your_key_here"

Example response

Returns 200 OK, or 404 if the record does not exist or belongs to a different organisation:

json
{
  "data": {
    "id": "cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "subject_identifier": "user@example.com",
    "purpose": "Marketing emails",
    "status": "active",
    "consent_at": "2026-04-18T10:00:00Z",
    "collection_method": "web_form",
    "collection_reference": null,
    "notice_version": null,
    "wording_version": null,
    "expires_at": null,
    "created_at": "2026-04-18T10:05:32Z",
    "withdrawals": []
  }
}

Withdraw consent

POST /api/v1/consent/{id}/withdraw

Scope required: consent:write

Marks the consent record as withdrawn and creates a withdrawal entry with a timestamp.

Request body (optional)

FieldTypeDescription
methodstringHow the withdrawal was collected. Defaults to api.
referencestringYour external reference for the withdrawal.
notesstringFree-text notes.
downstream_notifiedbooleanWhether downstream systems have been notified. Defaults to false.

Example request

bash
curl -X POST https://ghostredact.app/api/v1/consent/cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c/withdraw \
  -H "Authorization: Bearer gst_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "email",
    "notes": "User requested via support ticket"
  }'

Example response

Returns 200 OK with the withdrawal record, or 409 Conflict if the consent has already been withdrawn:

json
{
  "data": {
    "id": "wdr_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "consent_id": "cns_8f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "method": "email",
    "reference": null,
    "notes": "User requested via support ticket",
    "downstream_notified": false,
    "withdrawn_at": "2026-04-18T14:30:00Z"
  }
}

Error handling

All error responses return a JSON body with an error string:

json
{
  "error": "subject_identifier and purpose are required."
}
StatusMeaning
400Invalid or missing request parameters.
401Missing or invalid API key.
403Key lacks the required scope, or the organisation has reached its plan limit.
404Record not found or belongs to a different organisation.
409Conflict (e.g. consent already withdrawn).
413Request body exceeds the size limit.
429Rate limit exceeded — wait and retry.
500Server error — contact support if persistent.

Example: insufficient scope

bash
curl -X POST https://ghostredact.app/api/v1/consent \
  -H "Authorization: Bearer gst_read_only_key" \
  -H "Content-Type: application/json" \
  -d '{ "subject_identifier": "user@example.com", "purpose": "Analytics" }'
json
{
  "error": "Forbidden: key does not have the consent:write scope."
}

Rate limits

Each API key has a per-minute request limit (RPM) set by your plan. There is also an organisation-wide RPM cap. When either limit is hit the API returns 429 Too Many Requests:

json
{
  "error": "Rate limit exceeded. Try again in 60 seconds."
}

Wait for the current window to elapse (one minute) before retrying. If you need higher limits, contact support or upgrade your plan.

PreviousClient and matter management
© 2026 Ghost. All rights reserved.
ResourcesPrivacyTermsSecurity