API Reference
Complete reference for the DPOKit Licence API and the WordPress REST API — authentication, endpoint details, and downloadable collection files.
API Reference
DPOKit exposes two distinct APIs:
| API | Base URL | Used by |
|---|---|---|
| Licence API | https://api.dpokit.com | WordPress plugin, customer dashboard |
| WordPress REST API | https://your-site.com/wp-json/dpo-kit/v1 | Headless front-ends, custom integrations |
Download collection files to explore both APIs immediately in Bruno or Postman:
- DPOKit Licence API — Bruno collection
- DPOKit WordPress REST API — Bruno collection
- OpenAPI 3.1 spec (Licence API)
Licence API
Authentication
The Licence API uses two authentication schemes depending on the caller.
x-licence-key (plugin-facing endpoints)
WordPress plugin requests authenticate with your licence key in the x-licence-key header:
POST https://api.dpokit.com/licence/validate
x-licence-key: pv_live_abc123def456ghi789jkl012mno345p
Content-Type: application/jsonLicence keys are in the format pv_live_<32 chars> (production) or pv_test_<32 chars> (test/staging).
Retrieve your key from the customer dashboard.
Bearer JWT (customer dashboard endpoints)
Customer dashboard endpoints require a JWT issued after magic-link login:
GET https://api.dpokit.com/customer/licences
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...No authentication (public endpoints)
GET /health and POST /checkout/session require no authentication.
Licence Check — POST /licence/validate
Checks whether a licence key is valid and active for a given site URL. The WordPress plugin calls this endpoint on activation and periodically thereafter (response cached for 12 hours).
Request
POST https://api.dpokit.com/licence/validate
x-licence-key: pv_live_abc123def456ghi789jkl012mno345p
Content-Type: application/json
{
"licence_key": "pv_live_abc123def456ghi789jkl012mno345p",
"site_url": "https://example.com"
}Response — valid licence (200)
{
"valid": true,
"tier": "pro",
"sites_allowed": 1,
"sites_used": 1,
"expires_at": "2027-03-14T00:00:00.000Z",
"message": "Licence is active."
}Response — expired licence (200)
{
"valid": false,
"tier": "pro",
"sites_allowed": 1,
"sites_used": 1,
"expires_at": "2025-03-14T00:00:00.000Z",
"message": "Licence has expired."
}Rate limiting: 60 requests per minute per IP. Responses are cached server-side for 5 minutes per key.
Licence Activation — POST /licence/activate
Records a new site activation. Call this when the administrator saves their licence key on the DPOKit settings page.
Request
POST https://api.dpokit.com/licence/activate
x-licence-key: pv_live_abc123def456ghi789jkl012mno345p
Content-Type: application/json
{
"licence_key": "pv_live_abc123def456ghi789jkl012mno345p",
"site_url": "https://example.com"
}Response — success (200)
{
"success": true,
"activation_id": 42,
"tier": "pro",
"features": ["dsar", "retention", "reporting", "advanced_integrations"]
}Response — activation limit reached (403)
{
"error": "activation_limit_reached",
"message": "This licence has reached its maximum number of activations (1 of 1 used)."
}Licence Deactivation — POST /licence/deactivate
Removes the activation for a site URL, freeing one slot. Call this on WordPress plugin deactivation or when the administrator clicks "Deactivate Licence".
Request
POST https://api.dpokit.com/licence/deactivate
x-licence-key: pv_live_abc123def456ghi789jkl012mno345p
Content-Type: application/json
{
"licence_key": "pv_live_abc123def456ghi789jkl012mno345p",
"site_url": "https://example.com"
}Response (200)
{
"success": true,
"message": "Licence deactivated for https://example.com."
}Licence Info — GET /licence/info
Returns full licence details for the authenticated customer, including activation history.
Request
GET https://api.dpokit.com/licence/info?key=pv_live_abc123def456ghi789jkl012mno345p
Authorization: Bearer <jwt>Response (200)
{
"id": "clm1abc2def3",
"key": "pv_live_…no345p",
"tier": "pro",
"status": "active",
"sites_allowed": 1,
"expires_at": "2027-03-14T00:00:00.000Z",
"activated_at": "2026-03-14T10:00:00.000Z",
"activations": [
{
"id": 42,
"site_url": "https://example.com",
"activated_at": "2026-03-14T10:00:00.000Z",
"deactivated_at": null
}
]
}Licence API Error Responses
All errors use a consistent shape:
{
"error": "licence_not_found",
"message": "No licence found matching the provided key."
}| HTTP Status | Error code | Meaning |
|---|---|---|
| 400 | invalid_request | Missing or malformed request body |
| 401 | unauthorised | Missing or invalid authentication |
| 403 | activation_limit_reached | Activation slots exhausted |
| 404 | licence_not_found | Key does not exist |
| 429 | rate_limited | Too many requests |
| 503 | service_unavailable | API or database unreachable |
WordPress REST API
The WordPress plugin registers endpoints under the dpo-kit/v1 namespace. The base URL is:
https://your-site.com/wp-json/dpo-kit/v1
For a full endpoint listing see the REST API developer guide. The sections below highlight the three most commonly used endpoints in headless setups.
Authentication
| Auth type | Header | When to use |
|---|---|---|
| Application Password | Authorization: Basic base64(user:app_pass) | Server-to-server or API clients |
| Cookie + nonce | X-WP-Nonce: <nonce> | JavaScript running on the same WordPress domain |
| None | — | Public endpoints (consent status, DSAR intake, DSAR status check) |
Generate an Application Password at Users → Profile → Application Passwords in wp-admin.
Consent Status — GET /dpo-kit/v1/consent/status
Returns the banner configuration and consent categories. Use this in headless setups to build a custom consent UI.
Auth: Public (no authentication required)
Request
GET https://example.com/wp-json/dpo-kit/v1/consent/statusResponse (200)
{
"enabled": true,
"categories": {
"functional": {
"id": "functional",
"label": "Functional",
"required": true
},
"analytics": {
"id": "analytics",
"label": "Analytics",
"required": false
},
"marketing": {
"id": "marketing",
"label": "Marketing",
"required": false
},
"personalisation": {
"id": "personalisation",
"label": "Personalisation",
"required": false
}
},
"settings": {
"position": "bottom",
"title": "We value your privacy",
"message": "We use cookies to improve your experience and for analytics.",
"accept_text": "Accept All",
"reject_text": "Reject All",
"expiry_days": 365,
"privacy_url": "https://example.com/privacy"
}
}After reading this response, submit the visitor's decision to POST /dpo-kit/v1/consent.
DSAR Intake — POST /dpo-kit/v1/dsar/intake
Submits a Data Subject Access Request from a headless front-end (React, Next.js, etc.).
Auth: Public
Spam protection: Do not include the X-PV-HP-Check header — bots that send all headers are automatically rejected.
Request
POST https://example.com/wp-json/dpo-kit/v1/dsar/intake
Content-Type: application/json
{
"request_type": "access",
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com",
"additional_info": "Please include all marketing communications."
}Valid request_type values: access, deletion, rectification, portability, objection
Response (201)
{
"id": 15,
"reference": "DSR-20260311-A1B2C3",
"deadline_date": "2026-04-10",
"message": "Your request has been received. You will receive an acknowledgement email shortly."
}The reference value should be shown to the requestor — they will need it to check their case status.
DSAR Status Check — GET /dpo-kit/v1/dsar/status
Returns the current status of a DSAR case. Both reference and email are required to prevent case enumeration.
Auth: Public
Request
GET https://example.com/wp-json/dpo-kit/v1/dsar/status?reference=DSR-20260311-A1B2C3&email=jane%40example.comResponse (200)
{
"reference": "DSR-20260311-A1B2C3",
"request_type": "access",
"status": "in_progress",
"status_label": "In Progress",
"deadline": "2026-04-10",
"submitted": "2026-03-11 09:00:00",
"completed": null
}WordPress REST API Error Responses
Errors follow the standard WordPress REST API format:
{
"code": "not_found",
"message": "No request found matching that reference number and email address.",
"data": { "status": 404 }
}| Code | HTTP Status | Meaning |
|---|---|---|
rest_forbidden | 401 / 403 | Not authenticated or insufficient permissions |
not_found | 404 | Resource not found |
invalid_email | 422 | Email address failed validation |
dsar_disabled | 503 | DSAR intake is currently disabled |
spam_detected | 400 | Honeypot triggered |
create_failed | 500 | Database write failed |
Collections & Specs
| Resource | Description | Download |
|---|---|---|
| Bruno — Licence API | All api.dpokit.com endpoints with example bodies and environments | Download |
| Bruno — WordPress REST API | Key plugin REST endpoints (consent, DSAR, scanner, retention) | Download |
| OpenAPI 3.1 — Licence API | Machine-readable spec for the Licence API; import into any OpenAPI-compatible tool | View on GitHub |
Importing into Bruno
- Download a collection file above.
- Open Bruno and click Import Collection.
- Select the downloaded
.jsonfile. - In the Environments panel, select Production or Local Development and fill in your values.
Importing into Postman
Both Bruno collection files are compatible with Postman's import. In Postman:
- Click Import → Files.
- Select the downloaded
.jsonfile. - Set environment variables (
BASE_URL,LICENCE_KEY,SITE_URL, etc.) in your Postman environment.