API Reference

Complete reference for the DPOKit Licence API and the WordPress REST API — authentication, endpoint details, and downloadable collection files.

7 min read

API Reference

DPOKit exposes two distinct APIs:

APIBase URLUsed by
Licence APIhttps://api.dpokit.comWordPress plugin, customer dashboard
WordPress REST APIhttps://your-site.com/wp-json/dpo-kit/v1Headless front-ends, custom integrations

Download collection files to explore both APIs immediately in Bruno or Postman:


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/json

Licence 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 StatusError codeMeaning
400invalid_requestMissing or malformed request body
401unauthorisedMissing or invalid authentication
403activation_limit_reachedActivation slots exhausted
404licence_not_foundKey does not exist
429rate_limitedToo many requests
503service_unavailableAPI 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 typeHeaderWhen to use
Application PasswordAuthorization: Basic base64(user:app_pass)Server-to-server or API clients
Cookie + nonceX-WP-Nonce: <nonce>JavaScript running on the same WordPress domain
NonePublic 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/status

Response (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.com

Response (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 }
}
CodeHTTP StatusMeaning
rest_forbidden401 / 403Not authenticated or insufficient permissions
not_found404Resource not found
invalid_email422Email address failed validation
dsar_disabled503DSAR intake is currently disabled
spam_detected400Honeypot triggered
create_failed500Database write failed

Collections & Specs

ResourceDescriptionDownload
Bruno — Licence APIAll api.dpokit.com endpoints with example bodies and environmentsDownload
Bruno — WordPress REST APIKey plugin REST endpoints (consent, DSAR, scanner, retention)Download
OpenAPI 3.1 — Licence APIMachine-readable spec for the Licence API; import into any OpenAPI-compatible toolView on GitHub

Importing into Bruno

  1. Download a collection file above.
  2. Open Bruno and click Import Collection.
  3. Select the downloaded .json file.
  4. 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:

  1. Click ImportFiles.
  2. Select the downloaded .json file.
  3. Set environment variables (BASE_URL, LICENCE_KEY, SITE_URL, etc.) in your Postman environment.