The platform API is a JSON:API over HTTPS. Every endpoint follows the same conventions, so once you’ve made one request the rest are predictable.
Base URL
https://platform.tagbase.io/api/v1
All paths in this reference are relative to that base.
Content type
Send Content-Type: application/vnd.api+json on any request with a body — it’s
the expected media type, and if you send a different one the request is
rejected. (Omitting it is tolerated, but sending it is best practice.) Accept is
optional; responses always come back as application/vnd.api+json regardless. If
you do send Accept, use the same media type.
Content-Type: application/vnd.api+json
Request bodies are a single JSON:API document — a data object carrying a
type and an attributes map:
{
"data": {
"type": "tags",
"attributes": { "...": "..." }
}
}
Identifiers
Every resource id is a URL-safe string with a type prefix (acc_, key_,
tag_, ses_, vrf_). The prefix identifies the resource type; treat the full
string as opaque.
Errors
Errors come back as a JSON:API errors array. Each entry has an HTTP status
and a short title:
{
"errors": [
{ "status": "401", "title": "Unauthorized" }
]
}
The HTTP response status matches the status field. The statuses you’ll see:
| Status | Meaning |
|---|---|
400 |
The request body is missing or malformed (no data.attributes, or an out-of-range value). |
401 |
Missing, invalid, or revoked API key. |
404 |
The resource doesn’t exist under your account. |
422 |
The request was well-formed but could not be processed (validation failed). |
Idempotency
The API has no idempotency keys, and every POST creates a new resource each
time it’s called. Retrying a request that already succeeded — after a timeout or
a dropped connection — creates a duplicate: another batch of tags, another
subaccount, or another verification.
So retry deliberately. Treat a network-level failure (no response, a timeout) as “unknown”, not “failed”: before retrying a create, confirm on your side whether the first attempt actually landed, or accept and reconcile the possibility of a duplicate.
A response you did receive tells you what to do:
400,401,404are definitive — the same request will fail the same way, so fix the request rather than retry it.422means nothing was recorded, so retrying the identical request is safe and won’t create a duplicate. A422that keeps recurring is a problem to escalate, not a transient blip.201succeeded — don’t resend it, or you’ll create a duplicate.
What the API does not have (yet)
Keeping this explicit so you don’t design around features that aren’t there:
- No read or list endpoints. The current surface is write-only — you create
resources and read what the create response returns. There is no
GETto re-fetch a tag, session, or verification later. - No pagination or filtering — there are no list endpoints to paginate.
- No rate limiting headers or quotas are enforced at the API layer.
- No webhooks or realtime push. You learn a scan’s verdict from the response to the verification request you made, not from a callback.
When you need to retain state — a verdict, a session id — store it on your side at the moment you receive it.