Political advertisement data API for media and publisher partners
https://polads.eu/api/v1All endpoints require partner Bearer token authentication
GET /advertisement-full/{PAID}
1,000 requests per minute
GET /advertisement/{PAID}
1,000 requests per minute
Rate limit is enforced per partner token across all endpoints
Pro plan, re-checked on every request
The partner API is part of the Pro plan, on reads as well as writes. There is no separate API add-on to buy. The plan is read on every single request rather than recorded when the token is created, so a lapsed subscription stops access on the very next call with 403 PRO_PLAN_REQUIRED, and renewing restores it just as immediately.
Scopes
Every partner token can read. Reporting engagement metrics additionally needs the metrics:write scope. Scopes are chosen when the token is minted and cannot be edited afterwards: to change them, revoke the token and mint a new one.
Partner tokens only
These endpoints reject an SSP token with 401, and the SSP endpoint rejects a partner token the same way. The two tiers are separate credentials, not two permission levels on one.
GET /advertisement/{PAID} resolves the notice through the same visibility rule as the public register. A notice that is not yet confirmed, that its publisher has not yet signed off, or whose publication start date is still in the future returns 404 here exactly as it does on the register. The same applies to the SSP endpoint.
The full-record endpoint is deliberately different
GET /advertisement-full/{PAID} is scoped to your own notices, so it answers for a notice that has not reached its start date yet. You are the publisher who has to examine that notice before it runs, so withholding it from you would defeat the point.
/advertisement-full/{PAID}Scoped to your own notices. Another publisher's PA-ID, a self-published notice with no publisher, and an identifier that does not exist all return the same 404, and the response does not tell them apart.
⚠️ GDPR-Sensitive Data Warning
This endpoint returns ALL fields including emails, phone numbers, and full addresses. Only use this endpoint if you have a legitimate business need and proper data processing agreements in place.
curl -X GET "https://polads.eu/api/v1/advertisement-full/ABC12" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Advertiser Fields:
companyName, legalName, firstName, lastName, email, phone, streetAddress, postalCode, city, country
Campaign Fields:
name, totalValue, medium, isOngoing, startDate, endDate
Advertisers & Controllers:
All fields including emails, phones, and full addresses
/advertisement/{PAID}/metricsThis endpoint needs a key with the Read and write scope. The partner API is included in the Pro plan.
You can only report metrics for notices published through your own account.
The notice belongs to a different publisher. Nothing is written.
curl -X PUT "https://polads.eu/api/v1/advertisement/ABC12/metrics" \
-H "Authorization: Bearer YOUR_PARTNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"viewsCount": 15000, "engagementsCount": 320}'Basic Information
Compliance & Funding
Targeting
Legal & Metadata
// Get single ad
const response = await fetch('https://polads.eu/api/v1/advertisement/PAID-0000001');
const data = await response.json();401 INVALID_TOKEN
No active token matches the Bearer credential, or the token has been revoked. A missing or malformed Authorization header also answers 401, but only the metrics endpoint labels it with this code. An SSP token on a partner endpoint answers the same way.
GET /advertisement/{PAID}GET /advertisement-full/{PAID}{
"error": "Invalid or revoked partner API token. This endpoint only accepts partner tokens, not SSP tokens.",
"code": "INVALID_TOKEN"
}PUT /advertisement/{PAID}/metrics{
"error": "Invalid or revoked partner API token.",
"code": "INVALID_TOKEN"
}PUT /advertisement/{PAID}/metrics{
"error": "Missing or invalid Authorization header. Expected: Bearer <token>",
"code": "INVALID_TOKEN"
}GET /advertisement/{PAID}GET /advertisement-full/{PAID}{
"error": "Missing or invalid Authorization header. Expected: Bearer <token>"
}403 PRO_PLAN_REQUIRED
The token is valid and its publisher is not on the Pro plan. This is checked before the scope, so a read-only token belonging to a non-Pro publisher reports the plan rather than the scope.
GET /advertisement/{PAID}GET /advertisement-full/{PAID}PUT /advertisement/{PAID}/metrics{
"error": "The Pro plan is required to use the partner API.",
"code": "PRO_PLAN_REQUIRED"
}403 INSUFFICIENT_SCOPE
The token is valid and Pro, and lacks the metrics:write scope needed to report metrics.
PUT /advertisement/{PAID}/metrics{
"error": "This token is not authorised to write metrics. Required scope: metrics:write.",
"code": "INSUFFICIENT_SCOPE"
}403 FORBIDDEN
The notice belongs to a different publisher. Nothing is written.
PUT /advertisement/{PAID}/metrics{
"error": "This advertisement belongs to a different publisher.",
"code": "FORBIDDEN"
}400 INVALID_METRICS
The request body is not valid JSON, or the two counts are missing, negative or not whole numbers. The response lists what failed.
PUT /advertisement/{PAID}/metrics{
"error": "Invalid engagement metrics",
"code": "INVALID_METRICS",
"issues": [
{
"path": "viewsCount",
"message": "Too small: expected number to be >=0"
}
]
}PUT /advertisement/{PAID}/metrics{
"error": "Invalid request body",
"code": "INVALID_METRICS"
}409 METRICS_NOT_APPLICABLE
The notice is outside the scope engagement metrics are defined for. Annex II note 15 covers an online or native notice that used targeting or ad-delivery techniques and has started running. Nothing is written.
PUT /advertisement/{PAID}/metrics{
"error": "Engagement metrics do not apply to this notice",
"code": "METRICS_NOT_APPLICABLE"
}404 NOT_FOUND
No notice matches that PA-ID, or it is not visible to you yet. See the section above before assuming the identifier is wrong.
PUT /advertisement/{PAID}/metrics{
"error": "Advertisement not found",
"code": "NOT_FOUND"
}GET /advertisement/{PAID}{
"error": "Advertisement not found"
}GET /advertisement-full/{PAID}{
"error": "Advertisement not found or not yet confirmed"
}429 RATE_LIMITED
The per-token limit was exceeded. The response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.
PUT /advertisement/{PAID}/metrics{
"error": "Rate limit exceeded",
"code": "RATE_LIMITED",
"limit": 1000,
"remaining": 0,
"reset": "2026-05-14T15:14:00.000Z"
}GET /advertisement/{PAID}GET /advertisement-full/{PAID}{
"error": "Rate limit exceeded",
"limit": 1000,
"remaining": 0,
"reset": "2026-05-14T15:14:00.000Z"
}This is API version v1, and every response says so in an X-API-Version header. Breaking changes ship under a new path rather than changing this one. A v1 endpoint will not be switched off without a Deprecation header at least 90 days beforehand, following RFC 8594.
Machine-readable specification
The full OpenAPI 3.1 document is served at /api/docs. Point Postman, Swagger UI or a client generator straight at it rather than transcribing this page.
https://polads.eu/api/docs