TAGBASE

Verifications

Every scan of your tags, with its status and the tag behind it.

View as Markdown

A verification is one scan of one of your tags. Each carries the outcome of the check, the state of the tamper seal, the country the scan came from, and the tag and product behind it. This API reads the same list the dashboard’s verifications page shows. It is read only; scans come from phones.

Every request needs an API key. A key is limited to the verifications of its own team.

Use cases

  • Pull scans into a BI tool. Fetch the list once a night with filter[from] set to yesterday, and load the rows into your warehouse next to your sales data.
  • Alert on invalid. Poll with filter[status]=invalid and page a colleague when a new row appears. An invalid scan is a copied tag or a broken one, and either is worth a look the same day.
  • Count scans per product. Request filter[product_id] for each product and read meta.total_count, or group the rows you pulled by the product relationship.

Fields

A verification is a JSON:API resource of type verifications.

Field Type Notes
id string vrf_-prefixed. The same id the dashboard’s verification URLs carry.
status string pending, valid, or invalid. See below.
tamper_status string or null sealed, resealed, open, or invalid. null when the tag has no seal.
country string or null Where the scan came from, as an ISO 3166-1 alpha-2 code such as AT, read from the phone’s IP address. null when the address gave no country.
inserted_at string When the tag was tapped, as an ISO 8601 timestamp in UTC.

The tag relationship names the tag that was scanned, {"data": {"type": "tags", "id": "tag_…"}}, and the product relationship names its product, {"data": {"type": "products", "id": "prd_…"}}. Both ids match the Tags and Products endpoints, so you can join scans to the records you already hold.

Statuses match the dashboard

pending is the first tap, which the dashboard lists as Scanned; the verification stays open until the second tap that proves the tag is live. valid is a second tap that confirmed a genuine tag. invalid is a scan that failed the check, for example a copied tag replaying an old tap. The dashboard’s what the statuses mean has the full description.

One row per scan session

When a second tap follows a first tap within the session window, the list shows one row with the final status. When no second tap follows, the row shows as pending.

Team members’ own scans

When a signed-in member of your team taps a tag, the scan is in this list, the same as on the dashboard’s verifications page. The dashboard statistics leave those scans out, so a count from this API can be higher than the statistics show.

List verifications

GET /api/verifications

Lists the verifications of the team, newest first. Paging follows the shared pagination rules.

Query parameters

Parameter Type Notes
filter[status] string Only scans with this status: pending, valid, or invalid.
filter[product_id] string Only scans of this product, prd_….
filter[from] date Only scans on or after this day, YYYY-MM-DD, in UTC.
filter[to] date Only scans on or before this day, YYYY-MM-DD, in UTC.
page integer The page, counting from 1. Defaults to 1.
page_size integer Verifications per page. Defaults to 10, maximum 100.

Both dates are inclusive, so filter[from]=2026-09-01&filter[to]=2026-09-30 covers the whole of September. The API ignores a date it cannot parse.

curl "https://verify.tagbase.io/api/verifications?filter[status]=valid&filter[from]=2026-09-01&filter[to]=2026-09-30&page_size=100" \
  -H "Authorization: Bearer $TAGBASE_API_KEY" \
  -H "Accept: application/vnd.api+json"

Response: 200 OK

A data array of verifications, each in the shape of Retrieve a verification, plus a meta object that describes the page:

{
  "data": [
    {
      "type": "verifications",
      "id": "vrf_TZB4HkNVeLVSLEgoYWkbC",
      "attributes": {
        "status": "valid",
        "tamper_status": "sealed",
        "country": "AT",
        "inserted_at": "2026-09-09T13:44:46.140127Z"
      },
      "relationships": {
        "tag": { "data": { "type": "tags", "id": "tag_TKWk9WD8BiXrurBwjeZ5NW" } },
        "product": { "data": { "type": "products", "id": "prd_4fm3xUcsDEUK77WDBMed6U" } }
      }
    }
  ],
  "meta": { "total_count": 1, "page": 1, "page_size": 100 }
}

meta.total_count counts the rows that match your filters, so a request with filter[product_id] and page_size=1 is a cheap way to count the scans of one product.

Errors

Status When
401 Missing, invalid, or revoked key.

Retrieve a verification

GET /api/verifications/:id
curl https://verify.tagbase.io/api/verifications/vrf_TZB4HkNVeLVSLEgoYWkbC \
  -H "Authorization: Bearer $TAGBASE_API_KEY" \
  -H "Accept: application/vnd.api+json"

Response: 200 OK

{
  "data": {
    "type": "verifications",
    "id": "vrf_TZB4HkNVeLVSLEgoYWkbC",
    "attributes": {
      "status": "valid",
      "tamper_status": "sealed",
      "country": "AT",
      "inserted_at": "2026-09-09T13:44:46.140127Z"
    },
    "relationships": {
      "tag": { "data": { "type": "tags", "id": "tag_TKWk9WD8BiXrurBwjeZ5NW" } },
      "product": { "data": { "type": "products", "id": "prd_4fm3xUcsDEUK77WDBMed6U" } }
    }
  }
}

Errors

Status When
401 Missing, invalid, or revoked key.
404 No such verification in your team. A verification of another team and a malformed id get the same answer.

The same URL also answers without a key. Without an Authorization header, GET /api/verifications/:id is the endpoint the browser client on your own domain calls after a scan. It answers in the customer’s vocabulary, with valid_with_warnings and messages, and it shows a first tap only to the phone that made it. Send the key and you get the team shape described here instead. A wrong or revoked key answers 401; the API does not fall back to the public answer.

Next: the Tags and Products endpoints read the records the tag and product relationships point at.