tessio-eu Stats API

The Stats API from tessio-eu — 5 operation(s) for stats.

Operations 5

GET /v1/stats/summary Outcomes, rates and time to result for a period, beside the period before it #
GET /v1/stats/timeseries One metric over time, with zeros for empty buckets #
GET /v1/stats/failures Failed presentations by reason category #
GET /v1/stats/funnel How far the checks of a period got #
GET /v1/stats/breakdown Outcomes grouped by a column #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/tessio-eu:tessio-eu-stats-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

tessio-eu-stats-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Tessio.Cloud Stats API
  version: 0.1.0
  license:
    name: Proprietary
  description: 'The Tessio.Cloud integration API: start an age check, read its result, manage the webhook and read your stats. Every operation takes an API key (`tk_…`) as a Bearer token. This is the public part of the full description, generated from it; the guides are at https://tessio.eu/docs/.'
servers:
- url: https://api.tessio.eu
security:
- bearerAuth: []
tags:
- name: Stats
paths:
  /v1/stats/summary:
    get:
      tags:
      - Stats
      summary: Outcomes, rates and time to result for a period, beside the period before it
      description: Exactly the days asked for, and the period of equal length just before them, so a client can show a change without a second request. Rates are over the checks that ended (passed, under age, failed, expired), so a check still pending moves no rate; each is null when nothing ended. `p50Seconds` and `p95Seconds` run from creation to completion, over completed checks only. `retention` says from which day the plan keeps every check. Under a project's key, over its project; under an organisation's key, over every project in it, or one with `project_id`. UTC days. Any key may call it, of either scope; each key spends its own budget.
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/rangeFrom'
      - $ref: '#/components/parameters/rangeTo'
      - $ref: '#/components/parameters/statsMode'
      - $ref: '#/components/parameters/statsProject'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgeCheckStatsSummary'
        '400':
          $ref: '#/components/responses/InvalidStatsRequest'
        '401':
          description: No key, or one that is unknown or revoked
        '403':
          $ref: '#/components/responses/PlanFeatureUnavailable'
        '429':
          description: 'rate_limited: this key''s budget is spent.'
          headers:
            Retry-After:
              description: Seconds until a request can succeed
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1StatsSummary
      x-operation-id-source: derived
  /v1/stats/timeseries:
    get:
      tags:
      - Stats
      summary: One metric over time, with zeros for empty buckets
      description: One point per bucket from `from` to `to`, a bucket with no checks included as zero, so a chart never has to fill gaps. The granularity follows the range as on the Stats page, except that a range of two days or less is cut into hours, labelled `YYYY-MM-DDTHH:00Z` and ending at the current hour. Weeks and months are UTC calendar steps. `pass_rate` is null for a bucket where nothing ended. Under a project's key, over its project; under an organisation's key, over every project in it, or one with `project_id`. UTC days. Any key may call it, of either scope; each key spends its own budget.
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/rangeFrom'
      - $ref: '#/components/parameters/rangeTo'
      - $ref: '#/components/parameters/statsMode'
      - $ref: '#/components/parameters/statsMetric'
      - $ref: '#/components/parameters/statsProject'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgeCheckStatsSeries'
        '400':
          $ref: '#/components/responses/InvalidStatsRequest'
        '401':
          description: No key, or one that is unknown or revoked
        '403':
          $ref: '#/components/responses/PlanFeatureUnavailable'
        '429':
          description: 'rate_limited: this key''s budget is spent.'
          headers:
            Retry-After:
              description: Seconds until a request can succeed
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1StatsTimeseries
      x-operation-id-source: derived
  /v1/stats/failures:
    get:
      tags:
      - Stats
      summary: Failed presentations by reason category
      description: 'Every refused presentation in the period, counted by the category of its reason, read from the check timelines. A check can be refused more than once before it ends, so this counts attempts, not checks. The plan keeps timelines for less time than checks: before `retention.eventsFrom` the counts are partial. `group_by` splits each category further. Under a project''s key, over its project; under an organisation''s key, over every project in it, or one with `project_id`. UTC days. Any key may call it, of either scope; each key spends its own budget.'
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/rangeFrom'
      - $ref: '#/components/parameters/rangeTo'
      - $ref: '#/components/parameters/statsMode'
      - $ref: '#/components/parameters/statsFailureGroup'
      - $ref: '#/components/parameters/statsProject'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgeCheckStatsFailures'
        '400':
          $ref: '#/components/responses/InvalidStatsRequest'
        '401':
          description: No key, or one that is unknown or revoked
        '403':
          $ref: '#/components/responses/PlanFeatureUnavailable'
        '429':
          description: 'rate_limited: this key''s budget is spent.'
          headers:
            Retry-After:
              description: Seconds until a request can succeed
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1StatsFailures
      x-operation-id-source: derived
  /v1/stats/funnel:
    get:
      tags:
      - Stats
      summary: How far the checks of a period got
      description: '`created`, then `responseReceived` (a wallet''s response was judged: refused, answered or held for a browser that never came back), then `completed` (an answer about age came out). The sandbox answers without a wallet, so its checks reach `completed` without `responseReceived`. A held presentation is read from the timeline, so before `retention.eventsFrom` it is not counted. `eudiw` counts the checks that offered an EUDIW request, as their own or as a further one, and of those the ones where a wallet fetched a signed EUDIW request: the step only that profile has. An AV request travels inside its link, so nothing is fetched there and the step does not exist. Under a project''s key, over its project; under an organisation''s key, over every project in it, or one with `project_id`. UTC days. Any key may call it, of either scope; each key spends its own budget.'
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/rangeFrom'
      - $ref: '#/components/parameters/rangeTo'
      - $ref: '#/components/parameters/statsMode'
      - $ref: '#/components/parameters/statsProject'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgeCheckStatsFunnel'
        '400':
          $ref: '#/components/responses/InvalidStatsRequest'
        '401':
          description: No key, or one that is unknown or revoked
        '403':
          $ref: '#/components/responses/PlanFeatureUnavailable'
        '429':
          description: 'rate_limited: this key''s budget is spent.'
          headers:
            Retry-After:
              description: Seconds until a request can succeed
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1StatsFunnel
      x-operation-id-source: derived
  /v1/stats/breakdown:
    get:
      tags:
      - Stats
      summary: Outcomes grouped by a column
      description: The same outcome counts as the summary, over exactly the days asked for, one row per value of `group_by`, largest first. `project` and `api_key` rows carry the name as `label`. A deleted key's checks lose their key, so they join the row whose `key` is null. `key` is null for checks with no value in that column, such as a check nothing answered, which has no method. Under a project's key, over its project; under an organisation's key, over every project in it, or one with `project_id`. UTC days. Any key may call it, of either scope; each key spends its own budget.
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/rangeFrom'
      - $ref: '#/components/parameters/rangeTo'
      - $ref: '#/components/parameters/statsMode'
      - $ref: '#/components/parameters/statsBreakdownGroup'
      - $ref: '#/components/parameters/statsProject'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgeCheckStatsBreakdown'
        '400':
          $ref: '#/components/responses/InvalidStatsRequest'
        '401':
          description: No key, or one that is unknown or revoked
        '403':
          $ref: '#/components/responses/PlanFeatureUnavailable'
        '429':
          description: 'rate_limited: this key''s budget is spent.'
          headers:
            Retry-After:
              description: Seconds until a request can succeed
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      operationId: getV1StatsBreakdown
      x-operation-id-source: derived
components:
  parameters:
    rangeFrom:
      name: from
      in: query
      description: 'The first day, inclusive. A start further back than two years is refused rather than narrowed, so an answer never covers a shorter range than the one asked for.


        Omitting both `from` and `to` gives the default window, the last 30 days. Omitting only `from` is a half-written request and is refused.'
      schema:
        type: string
        format: date
    statsProject:
      name: project_id
      in: query
      description: Only this project of the org. A project of another org is refused exactly as one that does not exist, `invalid_project_id`. Under a project's key, only that project may be named.
      schema:
        type: string
        format: uuid
    statsMetric:
      name: metric
      in: query
      description: What each point counts. Defaults to `checks`, every check created in the bucket.
      schema:
        type: string
        enum:
        - checks
        - expired
        - failed
        - pass_rate
        - passed
        - under_age
        default: checks
    statsMode:
      name: mode
      in: query
      description: Live checks, test checks or both. Defaults to `live` at org scope (an organisation's key included), which is what a customer's own numbers are, and to the project's own mode at project scope (a project's key included), so a test project reads its checks.
      schema:
        type: string
        enum:
        - all
        - live
        - test
    rangeTo:
      name: to
      in: query
      description: The last day, inclusive. Defaults to today, and an end in the future is pulled back to today, so a preset like "this year" does not draw empty months that read as an outage.
      schema:
        type: string
        format: date
    statsFailureGroup:
      name: group_by
      in: query
      description: 'Split each category further. `method` is the profile (`av` or `eudiw`) of the request the attempt came through: one of the check''s further requests, or the check''s own, which it carries from creation, for an attempt through it or recorded before attempts named their request. For a check from before profiles were recorded it is the method; what answered a check is written only when it ends, which most refused checks never do. Omit for one row per category.'
      schema:
        type: string
        enum:
        - method
    statsBreakdownGroup:
      name: group_by
      in: query
      required: true
      description: The column to group by.
      schema:
        type: string
        enum:
        - api_key
        - format
        - method
        - mode
        - project
        - transport
  schemas:
    StatsRetention:
      type: object
      description: 'The first UTC day the purge has left whole, from what it recorded it may have deleted: after an upgrade the longer plan does not bring back days the shorter one already took. It may understate, never overstate: a day it calls whole is. A range that starts earlier counts only what is still held, so read the older days as partial, not as "no checks". Null where no purge has run for the org, so nothing was deleted.'
      properties:
        recordsFrom:
          type:
          - string
          - 'null'
          format: date
          description: 'For the checks: every read.'
        eventsFrom:
          type:
          - string
          - 'null'
          format: date
          description: 'For what is read from each check''s timeline: failures, the funnel''s step for a fetched request under `eudiw`, held presentations (part of the funnel''s `responseReceived`) and `noAnswer`, which leaves out a check whose presentation was held.'
    StatsFailureRow:
      type: object
      properties:
        category:
          type: string
          enum:
          - credential_expired
          - credential_revoked
          - invalid_presentation
          - issuer_untrusted
          - other
          - trust_list_expired
          - wallet_declined
          - wallet_error
          description: Why the presentations were refused, as a category.
        group:
          type:
          - string
          - 'null'
          description: The value grouped by. Null when not grouped, or when the check has none.
        count:
          type: integer
          format: int64
    AgeCheckStatsSummary:
      type: object
      properties:
        mode:
          type: string
          enum:
          - all
          - live
          - test
        current:
          $ref: '#/components/schemas/StatsPeriod'
        previous:
          $ref: '#/components/schemas/StatsPeriod'
        retention:
          $ref: '#/components/schemas/StatsRetention'
    StatsPoint:
      type: object
      properties:
        bucket:
          type: string
          description: YYYY-MM-DD, or YYYY-MM-DDTHH:00Z for hours (UTC)
        value:
          type:
          - number
          - 'null'
    AgeCheckStatsBreakdown:
      type: object
      properties:
        mode:
          type: string
          enum:
          - all
          - live
          - test
        groupBy:
          type: string
          enum:
          - api_key
          - format
          - method
          - mode
          - project
          - transport
        rows:
          type: array
          items:
            $ref: '#/components/schemas/StatsBreakdownRow'
        retention:
          $ref: '#/components/schemas/StatsRetention'
    AgeCheckStatsFailures:
      type: object
      properties:
        mode:
          type: string
          enum:
          - all
          - live
          - test
        groupBy:
          type:
          - string
          - 'null'
          enum:
          - method
          - null
        rows:
          type: array
          items:
            $ref: '#/components/schemas/StatsFailureRow'
        retention:
          $ref: '#/components/schemas/StatsRetention'
    StatsBreakdownRow:
      type: object
      properties:
        key:
          type:
          - string
          - 'null'
        label:
          type:
          - string
          - 'null'
          description: The project or API key name, for those groups.
        outcomes:
          $ref: '#/components/schemas/StatsOutcomes'
    StatsPeriod:
      type: object
      properties:
        from:
          type: string
          format: date
          description: First UTC day, inclusive.
        to:
          type: string
          format: date
          description: Last UTC day, inclusive.
        outcomes:
          $ref: '#/components/schemas/StatsOutcomes'
        passRate:
          type:
          - number
          - 'null'
          description: passed / ended, 0 to 1, where ended is total minus pending. Null when nothing ended.
        failRate:
          type:
          - number
          - 'null'
          description: (underAge + failed) / ended.
        noAnswerRate:
          type:
          - number
          - 'null'
          description: noAnswer / ended.
        p50Seconds:
          type:
          - number
          - 'null'
          description: Median seconds from creation to completion, over completed checks. For a same device check this includes the browser's return, because a check completes when the browser redeems the answer.
        p95Seconds:
          type:
          - number
          - 'null'
          description: The 95th percentile of the same.
    AgeCheckStatsFunnel:
      type: object
      properties:
        mode:
          type: string
          enum:
          - all
          - live
          - test
        created:
          type: integer
          format: int64
        responseReceived:
          type: integer
          format: int64
        completed:
          type: integer
          format: int64
        eudiw:
          $ref: '#/components/schemas/StatsEudiwFunnel'
        retention:
          $ref: '#/components/schemas/StatsRetention'
    StatsOutcomes:
      type: object
      description: Checks created in the period, by where they are now. `passed`, `underAge`, `failed`, `expired` and `pending` add up to `total`; `noAnswer` is a part of `expired`, not a sixth state.
      properties:
        total:
          type: integer
          format: int64
        passed:
          type: integer
          format: int64
          description: Completed and old enough.
        underAge:
          type: integer
          format: int64
          description: Completed and not old enough.
        failed:
          type: integer
          format: int64
          description: A presentation verified but carried no readable answer about age.
        expired:
          type: integer
          format: int64
          description: 'Ran out of time: no wallet answered, or every answer was refused or never redeemed.'
        pending:
          type: integer
          format: int64
        noAnswer:
          type: integer
          format: int64
          description: 'Of `expired`, those no wallet answered at all: no refused attempt and no presentation held for the browser. A held presentation is read from the check''s timeline, which the plan keeps for less time than the check (`retention.eventsFrom`), so before that day such a check is counted here.'
    StatsEudiwFunnel:
      type: object
      properties:
        created:
          type: integer
          format: int64
        requestFetched:
          type: integer
          format: int64
    AgeCheckStatsSeries:
      type: object
      properties:
        mode:
          type: string
          enum:
          - all
          - live
          - test
        metric:
          type: string
          enum:
          - checks
          - expired
          - failed
          - pass_rate
          - passed
          - under_age
        granularity:
          type: string
          enum:
          - day
          - hour
          - month
          - week
        points:
          type: array
          items:
            $ref: '#/components/schemas/StatsPoint'
        retention:
          $ref: '#/components/schemas/StatsRetention'
    PlanFeatureUnavailable:
      type: object
      properties:
        error:
          type: string
          enum:
          - plan_feature_unavailable
        feature:
          type: string
          enum:
          - stats.breakdown
          - stats.failures
          - stats.funnel
          - stats.summary
          - stats.timeseries
    Error:
      type: object
      properties:
        error:
          type: string
          description: Machine readable code (for example invalid_from, insufficient_scope, idempotency_key_reuse)
  responses:
    InvalidStatsRequest:
      description: The range is refused as for every chart (invalid_from, invalid_to, range_inverted, range_too_old, range_too_long), or invalid_mode, invalid_metric, invalid_group_by or invalid_project_id. Checked before the plan, so a malformed request is never answered with an upgrade.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PlanFeatureUnavailable:
      description: plan_feature_unavailable. The org's plan does not include this read. Every plan reads the summary, Starter adds the time series, Growth and above read all five.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlanFeatureUnavailable'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An API key (`tk_…`). A project's key with scope `full` calls every `/v1` route for its project; with `stats:read` it calls `/v1/stats/*` only. An organisation's key is always `stats:read` and reads every project in the organisation.