Skip to main content

Privacy Notices API

Manage privacy notices, processing purposes, and Records of Processing Activities (RoPA) under /api/v1.0.

Privacy notices are space-scoped, versioned policy records. Each notice owns one or more processing purposes, and catalog products reference those purposes from their legal and compliance metadata. RoPA endpoints combine privacy notice mappings with product metadata, sensitivity, owners, recipients, and lawful basis values so privacy teams can review coverage and export evidence.

Endpoints Overview

MethodEndpointDescription
GET/spaces/{slug}/ropa-reportGenerate a paginated RoPA report for a space
GET/spaces/{slug}/ropa-summaryReturn RoPA summary counts for a space
GET/spaces/{slug}/ropa-exportExport the full space RoPA report as CSV
GET/spaces/{slug}/privacy-noticesList privacy notices in a space
POST/spaces/{slug}/privacy-noticesCreate a privacy notice
GET/spaces/{slug}/privacy-notices/{notice_id}Get a privacy notice
PUT/spaces/{slug}/privacy-notices/{notice_id}Update a privacy notice
DELETE/spaces/{slug}/privacy-notices/{notice_id}Delete a privacy notice
POST/spaces/{slug}/privacy-notices/{notice_id}/purposesAdd a processing purpose
PUT/spaces/{slug}/privacy-notices/{notice_id}/purposes/{purpose_id}Update a processing purpose
DELETE/spaces/{slug}/privacy-notices/{notice_id}/purposes/{purpose_id}Delete a processing purpose
GET/spaces/org/{org_slug}/ropa-reportGenerate an organization-wide RoPA report
GET/spaces/org/{org_slug}/ropa-summaryReturn organization-wide RoPA summary counts
GET/spaces/org/{org_slug}/privacy-noticesList notices aggregated across organization spaces
GET/spaces/org/{org_slug}/ropa-exportExport organization-wide RoPA as CSV

Data Model

Privacy Notice

{
"id": "62e9a747-6ebb-4b81-991b-4f9caa13a1de",
"space_id": "cc7a4f41-3923-41c0-9fd2-f1e030f5bd62",
"space_name": "Marketing Analytics",
"name": "Global Privacy Policy",
"version": "v2.1",
"status": "ACTIVE",
"content_url": "https://example.com/privacy",
"valid_from": "2026-03-01T00:00:00Z",
"valid_to": null,
"created_at": "2026-02-10T09:30:00Z",
"updated_at": "2026-03-01T11:15:00Z",
"purposes": [
{
"id": "e8027c92-9afb-49a9-bbd7-caf9e3d2946c",
"notice_id": "62e9a747-6ebb-4b81-991b-4f9caa13a1de",
"name": "Marketing Analytics",
"description": "Analyze customer behavior for campaign measurement.",
"is_essential": false,
"created_at": "2026-02-10T09:35:00Z",
"updated_at": "2026-02-10T09:35:00Z"
}
]
}
FieldTypeNotes
namestringHuman-readable notice name.
versionstringVersion label such as v1.0 or 2026.03.
statusstringDRAFT, ACTIVE, or ARCHIVED. The API stores the supplied string; clients should use the shipped status values.
content_urlstring or nullHosted policy URL. Create and update requests validate this as an external HTTP(S) URL when provided.
valid_fromdatetime or nullEffective date for this version.
valid_todatetime or nullSuperseded or retired date.
purposesarrayProcessing purposes owned by this notice.
space_namestring or nullPopulated for organization aggregation responses.

Processing Purpose

FieldTypeNotes
idUUIDPurpose identifier used by product compliance metadata.
notice_idUUIDOwning privacy notice.
namestringRequired purpose name.
descriptionstring or nullOptional description for legal or product review.
is_essentialbooleanWhether the processing is strictly necessary for the core service. Defaults to false.

Deleting a privacy notice cascades to its processing purposes.


Space RoPA Report

Generate a paginated, filterable Record of Processing Activities report for a space.

GET /api/v1.0/spaces/{slug}/ropa-report

Query Parameters

ParameterTypeDefaultDescription
limitinteger20Page size from 1 to 100.
offsetinteger0Records to skip.
searchstring-Search product name, lawful basis, or processing purpose.
lawful_basisstring-Filter by lawful basis value.
environmentstring-Filter by product environment.
sensitivitystring-Filter by product sensitivity level.
mapping_statusstringallmapped, unmapped, or all.

Response

[
{
"product_id": "0a21b71f-6b73-4a58-a1e8-7f9dd2a4f61d",
"product_name": "Customer Events",
"product_type": "table",
"product_kind": "dataset",
"product_source_id": "de0d2d90-d459-4477-bc2a-035ec3fb21b5",
"path": "warehouse.analytics.customer_events",
"environment": "production",
"space_slug": null,
"space_name": null,
"lawful_basis": "Legitimate Interest",
"retention_period": "36 months",
"data_subject_categories": ["Customers", "Prospects"],
"processing_purpose_id": "e8027c92-9afb-49a9-bbd7-caf9e3d2946c",
"processing_purpose_name": "Marketing Analytics",
"privacy_notice_id": "62e9a747-6ebb-4b81-991b-4f9caa13a1de",
"privacy_notice_name": "Global Privacy Policy",
"sensitivity": "PII",
"data_categories": ["PII"],
"recipients": ["Campaign Reporting"],
"owner_id": "a91ed407-ded8-4231-a3f5-0501a83c71a2",
"owner_name": "Alex Kim",
"has_compliance_gap": false
}
]

Pagination headers include:

HeaderMeaning
X-Total-CountTotal number of matching records.
X-PageCurrent 1-indexed page number.
X-Has-Moretrue when more results exist after the current page.

has_compliance_gap is true when product sensitivity indicates PII or PHI and the product lacks a lawful basis.


RoPA Summary

Return aggregate counts used by the RoPA dashboard.

GET /api/v1.0/spaces/{slug}/ropa-summary

Response

{
"total": 124,
"mapped": 102,
"unmapped": 22,
"missing_basis": 8,
"with_compliance_gap": 5
}

RoPA Export

Export the full space RoPA report as CSV.

GET /api/v1.0/spaces/{slug}/ropa-export

The response is text/csv with a Content-Disposition filename of ropa-report-{slug}.csv.

CSV columns:

product_name,space_slug,environment,sensitivity,lawful_basis,retention_period,data_subject_categories,processing_purpose_name,privacy_notice_name,data_categories,recipients,owner_name,has_compliance_gap

Exports include up to 10,000 records. Filters are not accepted on the export endpoint in the current API.


List Privacy Notices

GET /api/v1.0/spaces/{slug}/privacy-notices

Response

[
{
"id": "...",
"space_id": "...",
"name": "Global Privacy Policy",
"version": "v1.2",
"status": "ACTIVE",
"content_url": "https://example.com/privacy-policy",
"valid_from": "2026-01-01T00:00:00Z",
"valid_to": null,
"created_at": "2025-12-01T10:00:00Z",
"updated_at": "2026-01-15T14:30:00Z",
"purposes": [
{
"id": "...",
"notice_id": "...",
"name": "Marketing Analytics",
"description": "Analyze customer behavior for marketing campaigns",
"is_essential": false,
"created_at": "2025-12-01T10:00:00Z",
"updated_at": "2025-12-01T10:00:00Z"
}
]
}
]

Get Privacy Notice

GET /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}

Returns a single privacy notice with its purposes. Returns 404 when the notice does not belong to the space or does not exist.


Create Privacy Notice

POST /api/v1.0/spaces/{slug}/privacy-notices

Request Body

{
"name": "Global Privacy Policy",
"version": "v1.0",
"status": "DRAFT",
"content_url": "https://example.com/privacy-policy",
"valid_from": "2026-03-01T00:00:00Z"
}
FieldTypeRequiredDescription
namestringYesName of the privacy notice
versionstringYesVersion string (e.g., v1.0)
statusstringNoDRAFT (default), ACTIVE, or ARCHIVED
content_urlstringNoLink to the hosted policy text
valid_fromdatetimeNoWhen this version comes into effect
valid_todatetimeNoWhen this version was superseded

Response: Full privacy notice object with purposes.


Update Privacy Notice

PUT /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}

Accepts the same fields as creation. Only provided fields are updated (partial update).

Request Body

{
"status": "ACTIVE",
"valid_from": "2026-03-01T00:00:00Z"
}

Returns 404 when the notice does not belong to the space or does not exist.


Delete Privacy Notice

DELETE /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}

Deletes the notice and its processing purposes.

Response: {"message": "Privacy notice deleted"}


Add Processing Purpose

POST /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}/purposes

Request Body

{
"name": "Marketing Analytics",
"description": "Analyze customer behavior for marketing campaigns",
"is_essential": false
}
FieldTypeRequiredDescription
namestringYesName of the processing purpose
descriptionstringNoDetailed description
is_essentialbooleanNoWhether this processing is strictly necessary (default: false)

Response: Processing purpose object.

Returns 404 when the notice does not belong to the space or does not exist.


Update Processing Purpose

PUT /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}/purposes/{purpose_id}

Accepts name, description, and is_essential. Only provided fields are updated.

Request Body

{
"description": "Analyze customer behavior for campaign measurement and audience reporting.",
"is_essential": false
}

Returns 404 when the purpose cannot be found in the space.


Delete Processing Purpose

DELETE /api/v1.0/spaces/{slug}/privacy-notices/{notice_id}/purposes/{purpose_id}

Response: {"message": "Processing purpose deleted"}

Returns 404 when the purpose cannot be found in the space.


Organization RoPA Report

Generate a paginated RoPA report across all spaces in an organization.

GET /api/v1.0/spaces/org/{org_slug}/ropa-report

Query parameters are the same as the space RoPA report:

ParameterTypeDefaultDescription
limitinteger20Page size from 1 to 100.
offsetinteger0Records to skip.
searchstring-Search product name, lawful basis, or processing purpose.
lawful_basisstring-Filter by lawful basis value.
environmentstring-Filter by product environment.
sensitivitystring-Filter by product sensitivity level.
mapping_statusstringallmapped, unmapped, or all.

Organization RoPA records include space_slug and space_name so clients can route remediation back to the owning space.


Organization RoPA Summary

GET /api/v1.0/spaces/org/{org_slug}/ropa-summary

Returns the same shape as the space summary:

{
"total": 480,
"mapped": 433,
"unmapped": 47,
"missing_basis": 19,
"with_compliance_gap": 11
}

Organization Privacy Notices

List privacy notices aggregated across all spaces in an organization.

GET /api/v1.0/spaces/org/{org_slug}/privacy-notices

The response is the same privacy notice array shape returned by the space listing. space_name is populated when available so clients can identify the source space.

Organization privacy notice endpoints are read-only. Create, update, delete, and purpose changes are performed in the source space.


Organization RoPA Export

GET /api/v1.0/spaces/org/{org_slug}/ropa-export

The response is text/csv with a Content-Disposition filename of ropa-report-{org_slug}-all-spaces.csv. Columns match the space export.


Common Workflows

Create A Notice And Map Products

  1. Create a notice with POST /spaces/{slug}/privacy-notices.
  2. Add one or more purposes with POST /spaces/{slug}/privacy-notices/{notice_id}/purposes.
  3. Update catalog product compliance metadata with a processing_purpose_id, lawful basis, retention period, and data-subject categories through the Catalog API.
  4. Check GET /spaces/{slug}/ropa-summary for unmapped or missing-basis counts.
  5. Use GET /spaces/{slug}/ropa-report?mapping_status=unmapped to identify products that still need mapping.

Version A Notice

  1. Create the new version as DRAFT.
  2. Add or adjust purposes under the draft notice.
  3. After legal review, update the new notice to ACTIVE and set valid_from.
  4. Update the old notice to ARCHIVED and set valid_to.
  5. Move product mappings to the active notice's purposes where needed.

Export Audit Evidence

Use the space or organization export endpoint for audit packets. Because export endpoints do not accept filters, apply any narrowing in downstream tooling or use the paginated report endpoint when you need filtered JSON.