ReferenceReference by module

Privacy API

Every Privacy action (7) and data model (1): endpoints, scopes, input, preconditions, events and examples.

Personal-data requests — export or erase a customer’s data, with a record kept.

Module code privacy · 7 actions · 1 data models · 6 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: privacy (everything), privacy:read (read only) or privacy:<capability>.

Resources

ResourceTableList and readPOSTPATCHDELETE
privacy_requestsprivacy_request/api/v1/privacy_requests

Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.

Actions

ActionNeedsWhat it does
privacy.approve_erasureprivacy:approveApprove and erase
privacy.cancel_erasureprivacy:writeWithdraw erasure request
privacy.export_dataprivacy:exportExport personal data
privacy.purge_exportsprivacy:manageApply the export retention policy
privacy.reject_erasureprivacy:approveReject erasure request
privacy.request_erasureprivacy:writeRequest deletion of personal data
privacy.request_my_erasureprivacy:writeAsk to delete my data

privacy.approve_erasure

Approve and erase — Approves an erasure request. The customer’s name, contact details, identities and saved addresses are scrubbed.

Needs privacy:approve · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/privacy_requests/actions/approve_erasure
API key or OAuth token · privacy:approve
  • Canonical address: POST /api/v1/actions/privacy.approve_erasure

Input

FieldTypeRequiredNotes
iduuidyesRequest
notestringNote · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
request_not_foundThe erasure request must exist in this workspace.
request_not_pendingOnly a pending request can be decided.
self_approvalThe person who asked cannot approve, unless the workspace allows it.

Events it publishes: privacy.erasure_approved

What it writes: privacy_request (update) — Marks the request approved and carried out

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/approve_erasure \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"id":"ID_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.erasure_approved"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.approveErasure({
  id: "ID_ID"
})
era privacy_requests approve_erasure \
  --id "ID_ID"
tools/call
{
  "name": "era__privacy__approve_erasure",
  "arguments": {
    "id": "ID_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:approve · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 request_not_found, request_not_pending, self_approval · 429 slow down

privacy.cancel_erasure

Withdraw erasure request — Withdraws a pending erasure request (the customer changed their mind, or it was opened by mistake).

Needs privacy:write · removes or cannot be undone

POSThttps://app.getera.io/api/v1/privacy_requests/actions/cancel_erasure
API key or OAuth token · privacy:write
  • Canonical address: POST /api/v1/actions/privacy.cancel_erasure

Input

FieldTypeRequiredNotes
iduuidyesRequest
notestringNote · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
request_not_foundThe erasure request must exist in this workspace.
request_not_pendingOnly a pending request can be withdrawn.

Events it publishes: privacy.erasure_cancelled

What it writes: privacy_request (update) — Marks the request cancelled

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/cancel_erasure \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"id":"ID_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.erasure_cancelled"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.cancelErasure({
  id: "ID_ID"
})
era privacy_requests cancel_erasure \
  --id "ID_ID"
tools/call
{
  "name": "era__privacy__cancel_erasure",
  "arguments": {
    "id": "ID_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 request_not_found, request_not_pending · 429 slow down

privacy.export_data

Export personal data — Collects every row this workspace holds about a customer into one downloadable file, and records that it did.

Needs privacy:export · reaches outside (sends, publishes or charges)

POSThttps://app.getera.io/api/v1/privacy_requests/actions/export_data
API key or OAuth token · privacy:export
  • Canonical address: POST /api/v1/actions/privacy.export_data

Input

FieldTypeRequiredNotes
customer_iduuidyesCustomer
reasonstringWhy (e.g. the request’s reference) · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
customer_not_foundThe customer must exist in this workspace.

Events it publishes: privacy.exported

What it writes: privacy_request (insert) — A completed export in the register, with the collected rows

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/export_data \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"customer_id":"CUSTOMER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.exported"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.exportData({
  customer_id: "CUSTOMER_ID"
})
era privacy_requests export_data \
  --customer-id "CUSTOMER_ID"
tools/call
{
  "name": "era__privacy__export_data",
  "arguments": {
    "customer_id": "CUSTOMER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:export · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 customer_not_found · 429 slow down

privacy.purge_exports

Apply the export retention policy — Deletes the collected data of exports past the retention window. The register row and its counts stay.

Needs privacy:manage · removes or cannot be undone

POSThttps://app.getera.io/api/v1/privacy_requests/actions/purge_exports
API key or OAuth token · privacy:manage
  • Canonical address: POST /api/v1/actions/privacy.purge_exports

Input

This action takes no input.

Events it publishes: privacy.exports_purged

What it writes: privacy_request (update) — Clears export_payload on expired exports

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/purge_exports \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.exports_purged"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.purgeExports()
era privacy_requests purge_exports
tools/call
{
  "name": "era__privacy__purge_exports",
  "arguments": {}
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 429 slow down

privacy.reject_erasure

Reject erasure request — Declines an erasure request, with the reason (e.g. an open contract or a legal hold).

Needs privacy:approve · changes data

POSThttps://app.getera.io/api/v1/privacy_requests/actions/reject_erasure
API key or OAuth token · privacy:approve
  • Canonical address: POST /api/v1/actions/privacy.reject_erasure

Input

FieldTypeRequiredNotes
iduuidyesRequest
notestringyesReason · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
request_not_foundThe erasure request must exist in this workspace.
request_not_pendingOnly a pending request can be decided.

Events it publishes: privacy.erasure_rejected

What it writes: privacy_request (update) — Marks the request rejected

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/reject_erasure \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"id":"ID_ID","note":"Reason"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.erasure_rejected"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.rejectErasure({
  id: "ID_ID",
  note: "Reason"
})
era privacy_requests reject_erasure \
  --id "ID_ID" \
  --note "Reason"
tools/call
{
  "name": "era__privacy__reject_erasure",
  "arguments": {
    "id": "ID_ID",
    "note": "Reason"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:approve · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 request_not_found, request_not_pending · 429 slow down

privacy.request_erasure

Request deletion of personal data — Opens an erasure request for a customer. Nothing is deleted until it is approved.

Needs privacy:write · changes data

POSThttps://app.getera.io/api/v1/privacy_requests/actions/request_erasure
API key or OAuth token · privacy:write
  • Canonical address: POST /api/v1/actions/privacy.request_erasure

Input

FieldTypeRequiredNotes
customer_iduuidyesCustomer
reasonstringWhy (e.g. the request’s reference) · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
customer_not_foundThe customer must exist in this workspace.
already_anonymizedA customer whose data was already erased cannot be erased again.
erasure_already_openOne open erasure request per customer.

Events it publishes: privacy.erasure_requested

What it writes: privacy_request (insert) — A pending erasure in the register

curl -X POST https://app.getera.io/api/v1/privacy_requests/actions/request_erasure \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"customer_id":"CUSTOMER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "privacy.erasure_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.privacyRequests.requestErasure({
  customer_id: "CUSTOMER_ID"
})
era privacy_requests request_erasure \
  --customer-id "CUSTOMER_ID"
tools/call
{
  "name": "era__privacy__request_erasure",
  "arguments": {
    "customer_id": "CUSTOMER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold privacy:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 customer_not_found, already_anonymized, erasure_already_open · 429 slow down

privacy.request_my_erasure

Ask to delete my data — A signed-in customer asks the business to erase their personal data. Nothing is deleted until it is approved.

Needs privacy:write · changes data · Also callable from a published site (customer)

A website action: your site calls it through the site API (/api/site/v1/{siteId}, e.g. with @getera/storefront). With an API key or a token it is refused (403 site_only).
POSThttps://app.getera.io/api/v1/privacy_requests/actions/request_my_erasure
API key or OAuth token · privacy:write
  • Canonical address: POST /api/v1/actions/privacy.request_my_erasure

Input

FieldTypeRequiredNotes
reasonstringWhy · max 500

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
erasure_already_openOne open erasure request per customer.

Events it publishes: privacy.erasure_requested

What it writes: privacy_request (insert) — A pending erasure in the register

Errors: 401 no or expired credential · 403 the credential does not hold privacy:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 erasure_already_open · 429 slow down

Data models

PrivacyRequest

Table privacy_request · Resource privacy_requests

  • GET /api/v1/privacy_requests
  • GET /api/v1/privacy_requests/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
customer_idstring (uuid) · uuid
subject_labelstring · text
kindstring · textexport, erase
statusstring · textpending, completed, rejected, cancelled
reasonstring · textyes
requested_bystring (uuid) · uuidyesapp_user
requested_atstring (date-time) · timestamptz
decided_bystring (uuid) · uuidyesapp_user
decided_atstring (date-time) · timestamptzyes
decision_notestring · textyes
completed_atstring (date-time) · timestamptzyes
export_summaryobject · jsonbyes
export_expires_atstring (date-time) · timestamptzyes
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Events

Workflows and webhooks react to these events.

EventWhat happensPayload
privacy.erasure_approvedAn erasure was approved; the owners of the data scrub it.id, customerId
privacy.erasure_cancelledAn erasure request was withdrawn.id, customerId
privacy.erasure_rejectedAn erasure request was declined.id, customerId
privacy.erasure_requestedAn erasure request was opened.id, customerId
privacy.exportedA customer’s personal data was exported.id, customerId, tables, rows
privacy.exports_purgedExpired exports were cleared.removed
Was this page helpful?