PoLI endpoints
What is PoLI?
PoLI (Person of Legal Interest) is a concept established under EU Battery Regulation 2023/1542. Certain entities — market surveillance authorities, customs authorities, the European Commission, and other bodies with a statutory right of access — are entitled to view non-public fields in a Digital Product Passport that are not accessible to the general public.
These restricted fields may include detailed supply chain traceability data, raw material sourcing documentation, and internal test results that manufacturers are required to record but not required to publish openly.
The Traceable PoLI API allows qualifying entities to formally request and receive access to these restricted fields through a structured, audited workflow.
To use these endpoints, your organisation must have a registered Traceable account with PoLI access enabled. Contact support@traceable.digital to register as a PoLI entity.
POST /api/poli/access
Submit an access request from a PoLI entity to view restricted DPP fields for a specific product.
Authentication
Required. Include your API key as a bearer token:
Authorization: Bearer trc_live_{your_key}
Request body
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
productSlug | string | Yes | The slug of the product whose restricted fields you are requesting access to |
requestingEntity | string | Yes | Full legal name of the requesting authority or organisation |
legalBasis | string | Yes | Citation of the specific legal provision granting the right of access (e.g., article number and regulation) |
contactEmail | string | Yes | Email address for correspondence about this request. Must be a valid email. |
jurisdiction | string | Yes | ISO 3166-1 alpha-2 country code of the requesting authority's jurisdiction (e.g., DE, NL, FR) |
Example request body:
{
"productSlug": "swiftvolt-48v-100ah-ev-pack",
"requestingEntity": "Netherlands Authority for Consumers and Markets (ACM)",
"legalBasis": "EU Battery Regulation 2023/1542, Article 74(1) — Market Surveillance Authorities",
"contactEmail": "dpp-access@acm.nl",
"jurisdiction": "NL"
}
Response — 201 Created
{
"requestId": "poli_req_01HXYZ9KP2MNTV3QW8JBDCF4A",
"status": "pending",
"estimatedReviewTime": "72 hours"
}
| Field | Type | Description |
|---|---|---|
requestId | string | Unique identifier for this access request. Store this — you will need it to check status via /api/poli/verify. |
status | string | Always pending on creation |
estimatedReviewTime | string | Indicative time for the manufacturer to review and action the request |
Response — 400 Bad Request
Returned when the request body fails validation:
{
"error": "Request body validation failed",
"code": "VALIDATION_ERROR",
"details": {
"fields": {
"jurisdiction": "Must be a valid ISO 3166-1 alpha-2 country code",
"contactEmail": "Must be a valid email address"
}
}
}
Response — 401 Unauthorized
{
"error": "Authentication required",
"code": "UNAUTHORIZED",
"details": {}
}
Response — 404 Not Found
{
"error": "Product not found",
"code": "PRODUCT_NOT_FOUND",
"details": {}
}
Response — 409 Conflict
Returned if a pending access request from the same entity already exists for this product:
{
"error": "An active access request already exists for this product",
"code": "DUPLICATE_REQUEST",
"details": {
"existingRequestId": "poli_req_01HABC..."
}
}
Examples
curl
curl -X POST https://app.traceable.digital/api/poli/access \
-H "Authorization: Bearer ${TRACEABLE_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"productSlug": "swiftvolt-48v-100ah-ev-pack",
"requestingEntity": "Netherlands Authority for Consumers and Markets (ACM)",
"legalBasis": "EU Battery Regulation 2023/1542, Article 74(1) — Market Surveillance Authorities",
"contactEmail": "dpp-access@acm.nl",
"jurisdiction": "NL"
}'
JavaScript (Node.js)
interface PoliAccessRequest {
productSlug: string;
requestingEntity: string;
legalBasis: string;
contactEmail: string;
jurisdiction: string;
}
interface PoliAccessResponse {
requestId: string;
status: 'pending';
estimatedReviewTime: string;
}
async function submitPoliAccessRequest(
request: PoliAccessRequest
): Promise<PoliAccessResponse> {
const apiKey = process.env.TRACEABLE_API_KEY;
if (!apiKey) {
throw new Error('TRACEABLE_API_KEY environment variable is not set');
}
const response = await fetch('https://app.traceable.digital/api/poli/access', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (response.status === 409) {
const data = await response.json();
throw new Error(
`Duplicate request. Existing request ID: ${data.details?.existingRequestId}`
);
}
if (response.status === 401) {
throw new Error('Invalid or missing API key');
}
if (response.status === 404) {
throw new Error(`Product not found: ${request.productSlug}`);
}
if (!response.ok) {
const data = await response.json().catch(() => ({}));
throw new Error(`PoLI access request failed: ${data.error ?? response.statusText}`);
}
return response.json() as Promise<PoliAccessResponse>;
}
// Usage
const result = await submitPoliAccessRequest({
productSlug: 'swiftvolt-48v-100ah-ev-pack',
requestingEntity: 'Netherlands Authority for Consumers and Markets (ACM)',
legalBasis: 'EU Battery Regulation 2023/1542, Article 74(1) — Market Surveillance Authorities',
contactEmail: 'dpp-access@acm.nl',
jurisdiction: 'NL',
});
console.log(`Request submitted: ${result.requestId}`);
// Store result.requestId for subsequent status checks
GET /api/poli/verify
Check the status of a previously submitted PoLI access request. If the request has been approved, this endpoint returns a short-lived access token and the restricted field data.
Authentication
Required. Must be the same API key that was used to submit the original request.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
requestId | string | Yes | The requestId returned by POST /api/poli/access |
Response — 200 OK
{
"requestId": "poli_req_01HXYZ9KP2MNTV3QW8JBDCF4A",
"status": "approved",
"accessToken": "pat_eyJhbGciOiJIUzI1NiJ9...",
"accessTokenExpiresAt": "2025-04-08T12:00:00Z",
"restrictedFields": {
"supplyChain": {
"rawMaterialSources": [
{
"material": "Cobalt",
"country": "DRC",
"mineOperator": "Glencore PLC",
"dueDiligenceAuditDate": "2024-09-01",
"auditBody": "RCS Global"
}
],
"internalAuditReportUrl": "https://storage.traceable.digital/docs/swiftvolt-audit-2024.pdf"
},
"testResults": {
"safetyTestingBody": "UL Solutions",
"safetyStandard": "IEC 62619:2022",
"testReportReference": "UL-2024-87341-R",
"passedAt": "2024-11-12T00:00:00Z"
}
}
}
| Field | Type | Description |
|---|---|---|
requestId | string | The request identifier |
status | string | pending — awaiting manufacturer review; approved — access granted; rejected — access denied by manufacturer |
accessToken | string | null | Short-lived token (valid for 24 hours) for accessing restricted fields. Present only when status is approved. |
accessTokenExpiresAt | string | null | ISO 8601 expiry time for the access token. Null when not approved. |
restrictedFields | object | null | The restricted DPP field data. Present only when status is approved. Structure varies by battery category. |
Pending example:
{
"requestId": "poli_req_01HXYZ9KP2MNTV3QW8JBDCF4A",
"status": "pending",
"accessToken": null,
"accessTokenExpiresAt": null,
"restrictedFields": null
}
Rejected example:
{
"requestId": "poli_req_01HXYZ9KP2MNTV3QW8JBDCF4A",
"status": "rejected",
"accessToken": null,
"accessTokenExpiresAt": null,
"restrictedFields": null
}
Rejection reasons are communicated out-of-band to the contactEmail specified in the original request, not via the API response.
Response — 401 Unauthorized
Returned if the API key used to verify does not match the key that submitted the request:
{
"error": "Access denied: this request was submitted by a different API key",
"code": "FORBIDDEN",
"details": {}
}
Response — 404 Not Found
{
"error": "Access request not found",
"code": "REQUEST_NOT_FOUND",
"details": {}
}
Access token usage
The accessToken returned when a request is approved is a short-lived JWT valid for 24 hours. After expiry, call GET /api/poli/verify again — a new token will be issued as long as the approval remains active.
Use the token in subsequent DPP requests to access restricted fields:
curl "https://app.traceable.digital/api/dpp/swiftvolt-48v-100ah-ev-pack?accessToken=pat_eyJ..." \
-H "Authorization: Bearer ${TRACEABLE_API_KEY}"
The full restricted field data is also returned directly in the restrictedFields object of the verify response, so for many use cases you do not need to make a separate DPP request.