Label API reference
Label API reference
label.js calls this API for you; you don't need to call it yourself. This reference is for reading the Network tab and debugging. Base URL: https://cdn.disclarion.com (permanent). Server-to-server access with an API key is not available yet.
Script files
| URL | What | Cached |
|---|---|---|
/v1/label.js | Latest 1.x release. The snippet URL; it never changes. Never use integrity on it: its content changes with each release. | 5 minutes |
/v1/label-1.1.0.js | One exact release (label-X.Y.Z.js), for pinning with SRI. Never changes. | 1 year (immutable) |
/v1/versions.json | Every release with its integrity hash and release date; latest is the version /v1/label.js serves. | 5 minutes |
A breaking change would ship only under a new path (/v2/label.js); /v1/label.js stays served.
POST /v1/labels: register or look up the marked items on a page
Sent as a simple CORS request (no preflight, no cookies). Up to 50 items and 64 KB per request. Repeating a request never creates a second record: a page view of known content creates nothing new.
POST https://cdn.disclarion.com/v1/labels
Content-Type: text/plain;charset=UTF-8
{
"site": "site_YOUR_SITE_CODE",
"page_url": "https://www.example.com/products/linen-shirt",
"client": "label.js/1.1.0",
"items": [
{ "ref": "0", "content_type": "text", "ai_involvement": "generated",
"hash_scheme": "t1", "content_hash": "<64 hex characters>", "provider": "openai", "model_name": "gpt-5" },
{ "ref": "1", "content_type": "image", "ai_involvement": "generated",
"candidates": ["https://www.example.com/images/spring-hero.png", "https://www.example.com/images/spring-hero-800.png"],
"current_src": "https://www.example.com/images/spring-hero-800.png", "model_name": "gpt-image-1" }
]
}The label.js 1.0 shape, a single source_url instead of candidates and current_src, is still accepted (1.1 also sends it for an image with more than 32 addresses).
Text items carry a fingerprint (t1: SHA-256 of the normalized text, computed in the browser). Images carry candidates, every address the <img> can show (its src, srcset and lazy-load attributes, and the <source> elements of its <picture>), and current_src, the one the browser shows; our server computes the fingerprint from the downloaded file. The response (status 200 whenever the request itself is acceptable) has one entry per item:
{
"site": { "hostname": "www.example.com", "state": "active" },
"items": [
{ "ref": "0", "status": "pending", "label_id": "7c1e4a52-…", "render": true,
"verify_url": "https://www.disclarion.com/verify/7c1e4a52-…" },
{ "ref": "1", "status": "pending", "label_id": null, "verify_url": null,
"render": true, "retry_after_ms": 4000 }
]
}| Field | Values |
|---|---|
site.state | active, or inactive when the account's subscription has ended: known items still show, nothing new is registered. |
status | verified (our server found it on the page), pending (registered, not checked yet; a new image has label_id: null until our server has downloaded it), failed (checked, not found; still drawn), not_registered (no record, see reason). |
render | true: label.js draws the label. false: it draws nothing for this item. |
reason | With not_registered: subscription_inactive, verification_lost (verification has failed for 30+ days), new_item_limit, page_churn, too_short, image_unsupported, invalid_item. |
retry_after_ms | With pending items that have no link yet: label.js asks again after this delay, at most twice. |
Errors for the whole request have this shape, and label.js logs the error code in the console:
{ "detail": { "error": "origin_not_allowed", "message": "…", "retryable": false } }| HTTP | error | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed request, or a page address that isn't https. |
| 403 | origin_not_allowed | The page's hostname isn't the site's hostname. |
| 403 | page_url_not_on_hostname | The page address isn't on the site's hostname. |
| 403 | site_not_verified | The site's hostname isn't verified. |
| 403 | site_disabled | The site is disabled. |
| 404 | site_not_found | Unknown site code. |
| 413 | too_many_items | More than 50 items or a body over 64 KB. |
| 415 | unsupported_media_type | Not a JSON body. |
| 429 | rate_limited | Too many requests; see the Retry-After header. |
| 503 | unavailable | The site isn't activated yet (early access), or the service is temporarily unavailable. |
Successful responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers. Limits: 60 requests per minute per visitor IP, 600 per minute per site, 200 new items per site per hour, and our server fetches at most 60 of your pages per site per hour for checks.
GET /v1/labels/{label_id}: the public record behind a verify link
No authentication. Returns the record's status, content_type, ai_involvement, hostname, page_url, first_seen_at, verified_at, verification_method, provider, model_name, hash_scheme and content_hash. It never returns your account, project, site code or the image address. Unknown ids get 404 label_not_found. The verify page at https://www.disclarion.com/verify/{label_id} shows this record.