mentio-dev Usage API

The Usage API from mentio-dev — 2 operation(s) for usage.

Operations 2

GET /v1/usage Get usage and balance #
GET /v1/usage/breakdown Get the usage breakdown #

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/mentio-dev:mentio-dev-usage-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

mentio-dev-usage-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Mentio Dev Usage API
  version: 0.0.1
  description: 'Operations tagged Usage across 4 of this provider''s published API definitions: api_mentio.json, mentio-dev-api-openapi.json, mentio-dev-app-openapi.json, mentio-dev-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.mentio.dev
tags:
- name: Usage
paths:
  /v1/usage:
    get:
      operationId: getUsage
      summary: Get usage and balance
      description: The prepaid balance (ledger, pending mention charges, and the effective balance the stop rule reads), the daily burn and the days it buys, the keywords the wallet runs and pauses, the matches recorded today and over 30 days, and whether tracking is stopped or the balance is low. Every matched mention bills ($0.008), relevant or not; every active keyword bills $5 a month, charged daily.
      tags:
      - Usage
      security:
      - bearerAuth: []
      responses:
        '200':
          description: The usage summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageSummary'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
  /v1/usage/breakdown:
    get:
      operationId: getUsageBreakdown
      summary: Get the usage breakdown
      description: 'What the workspace consumed and was charged over a window, grouped by one dimension per call (`by`: day, platform or keyword), in USD cents at list price, with the window''s totals on every call. `range` reads a trailing window of UTC days ending today (default 30d); `month` reads one calendar month (YYYY-MM), the shape a bill or a per-customer margin is reconciled against. Keyword-days come from the daily tick and mention charges from the matches that billed, so a deleted keyword keeps its charges in the keyword rows (`keyword.removed`) while its mention counts read 0; the same numbers ride on each keyword as `stats.cost` for the running month. `totals.ledgerDebitCents` is what the wallet has debited so far for the window''s days: mentions settle the morning after their day, so a window ending today lags `totals.totalCents` by the unsettled ones, and a closed month differs from it only by cumulative rounding. Rows are paged (`limit`, `offset`, `total`); a workspace may read this at most 30 times a minute through its keys and tokens together.'
      tags:
      - Usage
      security:
      - bearerAuth: []
      parameters:
      - schema:
          type: string
          enum:
          - day
          - platform
          - keyword
          - group
          default: keyword
          description: 'The dimension to group by: day (one row per UTC day of the window), platform, keyword (default: the row a margin is computed from), or group (what a customer or a campaign cost).'
        required: false
        description: 'The dimension to group by: day (one row per UTC day of the window), platform, keyword (default: the row a margin is computed from), or group (what a customer or a campaign cost).'
        name: by
        in: query
      - schema:
          type: string
          enum:
          - 7d
          - 30d
          - 90d
          description: 'Trailing window of UTC days ending today: 7d, 30d, 90d (default 30d). Ignored when `month` is given.'
        required: false
        description: 'Trailing window of UTC days ending today: 7d, 30d, 90d (default 30d). Ignored when `month` is given.'
        name: range
        in: query
      - schema:
          type: string
          pattern: ^\d{4}-(0[1-9]|1[0-2])$
          description: 'A calendar month (YYYY-MM, UTC) instead of a trailing window: from its first day to its last, or to today for the running month. A future month is a 400.'
        required: false
        description: 'A calendar month (YYYY-MM, UTC) instead of a trailing window: from its first day to its last, or to today for the running month. A future month is a 400.'
        name: month
        in: query
      - schema:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: First UTC day of a custom window, YYYY-MM-DD, inclusive; with `to` (default today). At most 366 days. Wins over `range` and `month`.
        required: false
        description: First UTC day of a custom window, YYYY-MM-DD, inclusive; with `to` (default today). At most 366 days. Wins over `range` and `month`.
        name: from
        in: query
      - schema:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Last UTC day of a custom window, YYYY-MM-DD, inclusive; never after today. Needs `from`.
        required: false
        description: Last UTC day of a custom window, YYYY-MM-DD, inclusive; never after today. Needs `from`.
        name: to
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            minLength: 1
            maxLength: 200
          maxItems: 30
          description: Only these keywords (kw_...), deleted ones included. Repeatable, or comma-separated.
        required: false
        description: Only these keywords (kw_...), deleted ones included. Repeatable, or comma-separated.
        name: keywordIds
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            minLength: 1
            maxLength: 200
          maxItems: 30
          description: 'Only these groups (grp_...): a keyword-day by the group it was metered under, a mention or a comment by its keyword''s group as it is now. Repeatable, or comma-separated.'
        required: false
        description: 'Only these groups (grp_...): a keyword-day by the group it was metered under, a mention or a comment by its keyword''s group as it is now. Repeatable, or comma-separated.'
        name: groupIds
        in: query
      - schema:
          type: array
          items:
            type: string
            enum:
            - bluesky
            - hackernews
            - github
            - stackoverflow
            - devto
            - reddit
            - x
            - youtube
            - news
            - linkedin
            - tiktok
            - instagram
            - appstore
            - googleplay
            - trustpilot
            - googlemaps
            - rss
          maxItems: 20
          description: Only these platforms. A keyword-day belongs to no platform, so with this filter the keyword line reads 0 and only mentions and comments count. Repeatable, or comma-separated.
        required: false
        description: Only these platforms. A keyword-day belongs to no platform, so with this filter the keyword line reads 0 and only mentions and comments count. Repeatable, or comma-separated.
        name: platforms
        in: query
      - schema:
          type: integer
          minimum: 1
          maximum: 500
          default: 100
          description: Rows per page, 1 to 500 (default 100). Only by=keyword can outgrow a page; a window has at most 90 days and a dozen platforms.
        required: false
        description: Rows per page, 1 to 500 (default 100). Only by=keyword can outgrow a page; a window has at most 90 days and a dozen platforms.
        name: limit
        in: query
      - schema:
          type:
          - integer
          - 'null'
          minimum: 0
          default: 0
          description: Skip this many rows.
        required: false
        description: Skip this many rows.
        name: offset
        in: query
      responses:
        '200':
          description: The window's totals and one page of rows for the dimension
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageBreakdown'
        '400':
          description: Unknown dimension or range, month malformed or in the future, limit out of range
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: More than 30 breakdown reads this minute for the workspace
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
components:
  schemas:
    UsageBreakdown:
      type: object
      properties:
        window:
          type: object
          properties:
            from:
              type: string
              description: First day, YYYY-MM-DD, inclusive, UTC.
            to:
              type: string
              description: 'Last day, inclusive: today for a trailing window or the running month.'
            days:
              type: integer
              minimum: 0
              description: Length of the window in days.
            keywordDaysFrom:
              type:
              - string
              - 'null'
              description: 'The first day of the window with a recorded keyword count, or null when there is none. Earlier days carry keywordDays: null.'
          required:
          - from
          - to
          - days
          - keywordDaysFrom
          description: The window the report covers, in UTC days.
        by:
          type: string
          enum:
          - day
          - platform
          - keyword
          - group
          description: The dimension the rows are grouped by.
        filtered:
          type: boolean
          description: 'true when keywordIds, groupIds or platforms narrowed the report: totals and rows count only what passes them, except totals.ledgerDebitCents, which is the whole workspace''s.'
        currency:
          type: string
          enum:
          - USD
          description: Every amount is in USD cents.
        totals:
          type: object
          properties:
            keywordDays:
              type: integer
              minimum: 0
              description: Keyword-days metered in the window.
            keywordCents:
              type: integer
              description: The keyword-days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total.
            matchedMentions:
              type: integer
              minimum: 0
              description: Matches recorded in the window, relevant or not.
            billableMentions:
              type: integer
              minimum: 0
              description: Of the matches billed in the window (every scored match, relevant or not), the ones in this group.
            unclassifiedMentions:
              type: integer
              minimum: 0
              description: 'Matches recorded in the window that are never charged: no score yet (still being scored, or classification failed), or a free review from the look-back of a newly connected app. Every other match is charged, on the mentions line or, for a comment, on the comments line.'
            mentionCents:
              type: integer
              description: The billed mentions at $0.008 each, rounded once on the total.
            billableComments:
              type: integer
              minimum: 0
              description: 'Comments billed in the window (the comments line): comments delivered under your mentions and comments that matched a keyword, each once per workspace.'
            commentCents:
              type: integer
              description: The billed comments at $0.008 each, rounded once on the total.
            totalCents:
              type: integer
              description: keywordCents plus mentionCents plus commentCents.
            ledgerDebitCents:
              type: integer
              description: What the ledger has debited so far for the days of the window, each debit by the day it settled, for the whole workspace whatever the filters. Mentions settle the morning after their day, so a window ending today lags totalCents by today's mentions (and yesterday's before the tick at 00:05 UTC); a closed month differs from totalCents only by cumulative rounding.
            unattributedBillable:
              type: integer
              minimum: 0
              description: Billed mentions whose match row is gone (deleted keyword), so no platform or keyword row can claim them. Charged all the same. Comments carry their keyword and platform on the billed row, so they are never unattributed (by=group puts a deleted keyword's comments on the no-group row).
          required:
          - keywordDays
          - keywordCents
          - matchedMentions
          - billableMentions
          - unclassifiedMentions
          - mentionCents
          - billableComments
          - commentCents
          - totalCents
          - ledgerDebitCents
          - unattributedBillable
          description: The whole window as one line, the same for every dimension.
        data:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
                description: 'The row''s key: the UTC day (YYYY-MM-DD) for by=day, the platform for by=platform, the keyword id for by=keyword, the group id for by=group.'
              label:
                type: string
                description: 'Readable name: the keyword term or the group name, otherwise the key.'
              keyword:
                type:
                - object
                - 'null'
                properties:
                  id:
                    type: string
                    description: Keyword id (kw_...); a deleted keyword keeps its id here.
                  term:
                    type: string
                    description: The term as it was last metered, or as the keyword reads now.
                  removed:
                    type: boolean
                    description: The keyword has since been deleted. Its charges stay on the record; its mentions went with it, so its mention counts read 0.
                required:
                - id
                - term
                - removed
                description: by=keyword only; null otherwise.
              group:
                type:
                - object
                - 'null'
                properties:
                  id:
                    type: string
                    description: Group id, or "none" for keyword-days metered before groups existed whose keyword is gone.
                  name:
                    type: string
                    description: The group's name as it reads now, or "Deleted group" / "No group".
                  removed:
                    type: boolean
                    description: The group has since been deleted.
                required:
                - id
                - name
                - removed
                description: by=group only; null otherwise.
              keywordDays:
                type:
                - integer
                - 'null'
                minimum: 0
                description: 'Keyword-days metered in this group: the days the daily tick charged for. Null for by=platform (a keyword-day belongs to no platform) and for a day before the first recorded tick (unknown, not zero); a keyword row counts only the days on record, so before window.keywordDaysFrom it is a floor, not a zero.'
              keywordCents:
                type: integer
                description: The keyword-days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total.
              matchedMentions:
                type: integer
                minimum: 0
                description: Matches recorded in the window, relevant or not.
              billableMentions:
                type: integer
                minimum: 0
                description: Of the matches billed in the window (every scored match, relevant or not), the ones in this group.
              unclassifiedMentions:
                type: integer
                minimum: 0
                description: 'Matches recorded in the window that are never charged: no score yet (still being scored, or classification failed), or a free review from the look-back of a newly connected app. Every other match is charged, on the mentions line or, for a comment, on the comments line.'
              mentionCents:
                type: integer
                description: The billed mentions at $0.008 each, rounded once on the total.
              billableComments:
                type: integer
                minimum: 0
                description: 'Comments billed in the window (the comments line): comments delivered under your mentions and comments that matched a keyword, each once per workspace.'
              commentCents:
                type: integer
                description: The billed comments at $0.008 each, rounded once on the total.
              totalCents:
                type: integer
                description: keywordCents plus mentionCents plus commentCents.
            required:
            - key
            - label
            - keyword
            - group
            - keywordDays
            - keywordCents
            - matchedMentions
            - billableMentions
            - unclassifiedMentions
            - mentionCents
            - billableComments
            - commentCents
            - totalCents
          description: 'by=day: chronological. by=platform and by=keyword: most expensive first, then most matched, deleted keywords included.'
        total:
          type: integer
          minimum: 0
          description: Rows in the dimension before `limit` and `offset`.
      required:
      - window
      - by
      - filtered
      - currency
      - totals
      - data
      - total
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
              - unauthorized
              - forbidden
              - read_only_key
              - validation_error
              - not_found
              - invalid_cursor
              - payload_too_large
              - rate_limited
              - duplicate_keyword
              - insufficient_balance
              - keyword_limit_reached
              - billing_not_configured
              - order_not_credited
              - schedule_required
              - unknown_channel
              - not_a_digest
              - hourly_email_unsupported
              - slack_not_connected
              - slack_not_configured
              - telegram_not_configured
              - feed_unreadable
              - feed_login_required
              - feed_login_expired
              - feed_limit_reached
              - feed_auth_not_configured
              - email_not_configured
              - invalid_assignee
              - classification_pending
              - invalid_member
              - already_member
              - last_owner
              - duplicate_segment
              - filter_too_complex
              - duplicate_view
              - duplicate_group
              - default_group
              - default_group_context
              - group_changed
              - invalid_signature
              - webhook_not_configured
              - invalid_token
              - protected_user
              - upstream_unavailable
              - internal_error
              description: 'Stable machine-readable code; branch on this, never on the message. Codes are additive: a client should treat one it does not know as a generic failure of the same status.'
            message:
              type: string
              description: Human-readable detail; may change between releases.
            requestId:
              type: string
              description: The id of this request (also the X-Request-Id response header); quote it to support.
            retryAfterSeconds:
              type: integer
              description: 'For rate_limited and other retryable errors: how long to wait before retrying (mirrors the Retry-After header).'
          required:
          - code
          - message
          description: The error.
      required:
      - error
    UsageSummary:
      type: object
      properties:
        balance:
          type: object
          properties:
            cents:
              type: integer
              description: 'Ledger balance: every credit minus every settled debit.'
            pendingCents:
              type: integer
              description: Mentions and comments billed since the last daily settlement, priced but not yet debited.
            effectiveCents:
              type: integer
              description: 'cents minus pendingCents: what the stop rule and the keyword gate look at.'
            currency:
              type: string
              enum:
              - USD
          required:
          - cents
          - pendingCents
          - effectiveCents
          - currency
          description: The prepaid wallet.
        burn:
          type: object
          properties:
            perDayCents:
              type: integer
              description: Average daily debit over the last 7 days (or since the workspace was created).
            daysLeft:
              type:
              - integer
              - 'null'
              minimum: 0
              description: effectiveCents divided by perDayCents; null when nothing is burning.
          required:
          - perDayCents
          - daysLeft
          description: How fast the balance goes.
        keywords:
          type: object
          properties:
            active:
              type: integer
              minimum: 0
              description: Unmuted keywords, the ones charged daily.
            paused:
              type: integer
              minimum: 0
              description: Keywords the wallet paused for lack of balance; a top-up resumes them.
            capped:
              type: integer
              minimum: 0
              description: 'Unmuted keywords at their monthly mention cap: still charged daily, not matched until the month turns or the cap is raised.'
            limit:
              type: integer
              minimum: 0
              description: 'How many keywords the workspace may run right now: the self-serve ceiling when the balance covers one more keyword-day, else 0.'
            dayCents:
              type: integer
              description: What one more day of the active keywords costs.
          required:
          - active
          - paused
          - capped
          - limit
          - dayCents
          description: Keywords against the wallet.
        mentions:
          type: object
          properties:
            today:
              type: integer
              minimum: 0
              description: 'Matches recorded today (UTC), relevant or not: every one bills.'
            last30d:
              type: integer
              minimum: 0
              description: Matches recorded in the last 30 days.
          required:
          - today
          - last30d
          description: Matched mentions, the other thing that bills.
        stopped:
          type: boolean
          description: The wallet paused tracking; a top-up that covers a day of every keyword resumes it.
        lowBalance:
          type: boolean
          description: Running, and the effective balance is at or under 20 percent of the last credit.
        lastTopUpAt:
          type:
          - string
          - 'null'
          description: Newest paid top-up; null before the first.
      required:
      - balance
      - burn
      - keywords
      - mentions
      - stopped
      - lowBalance
      - lastTopUpAt
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key minted via POST /v1/api-keys (format mk_live_...)
x-refined-from:
- api_mentio.json
- mentio-dev-api-openapi.json
- mentio-dev-app-openapi.json
- mentio-dev-openapi.json
x-mentio-errors:
- code: unauthorized
  status: 401
  source: user
  retryable: false
  description: No credential, or one that does not resolve to a workspace.
  fix: 'Send Authorization: Bearer mk_live_… with a key from /api-keys.'
- code: forbidden
  status: 403
  source: user
  retryable: false
  description: The credential is valid but may not do this.
- code: read_only_key
  status: 403
  source: user
  retryable: false
  description: A read key was used on a write endpoint.
  fix: Create a key with write scope.
- code: validation_error
  status: 400
  source: user
  retryable: false
  description: The body or query failed validation; the message names the field.
- code: not_found
  status: 404
  source: user
  retryable: false
  description: No such resource in your workspace. An id from another workspace is a 404, never a 403.
- code: invalid_cursor
  status: 400
  source: user
  retryable: false
  description: The cursor was not one this endpoint issued, or the filters changed between pages.
- code: payload_too_large
  status: 413
  source: user
  retryable: false
  description: The body exceeds the endpoint limit.
- code: rate_limited
  status: 429
  source: user
  retryable: true
  description: The workspace made more than 600 requests in a minute (every key and token together), or hit an endpoint's own cap; Retry-After says when.
  fix: Wait Retry-After seconds and send the same request again. X-RateLimit-Remaining on every response says how much room is left.
- code: duplicate_keyword
  status: 409
  source: user
  retryable: false
  description: The group already tracks this term. A term may be tracked once per group; another group may track it too.
- code: insufficient_balance
  status: 402
  source: user
  retryable: false
  description: The wallet cannot cover one more keyword-day.
  fix: Top up from Billing; tracking resumes on its own.
- code: keyword_limit_reached
  status: 402
  source: user
  retryable: false
  description: The self-serve keyword cap; beyond it is an enterprise conversation.
- code: billing_not_configured
  status: 503
  source: system
  retryable: false
  description: This deployment has no payment provider set up.
- code: schedule_required
  status: 400
  source: user
  retryable: false
  description: A daily alert rule was created without a schedule.
- code: unknown_channel
  status: 400
  source: user
  retryable: false
  description: A rule referenced a channel id the workspace does not own.
- code: not_a_digest
  status: 400
  source: user
  retryable: false
  description: A digest-only action was called on an instant rule.
- code: hourly_email_unsupported
  status: 400
  source: user
  retryable: false
  description: An hourly rule was given an email channel (up to 24 emails a day per rule). Use Slack, Telegram or a webhook, or a daily digest by email.
- code: slack_not_connected
  status: 409
  source: user
  retryable: false
  description: Connect Slack from Settings first. 404 on the Slack connection endpoints, 409 elsewhere.
- code: slack_not_configured
  status: 503
  source: system
  retryable: false
  description: This deployment has no Slack app credentials.
- code: telegram_not_configured
  status: 503
  source: system
  retryable: false
  description: This deployment has no Telegram bot.
- code: feed_unreadable
  status: 400
  source: user
  retryable: false
  description: No feed was found at the address, or the site blocks automated readers, or it answers an error; the message says which.
- code: feed_login_required
  status: 400
  source: user
  retryable: false
  description: The address answers a sign-in or access-denied page. Send it again with `auth` (the cookie your browser sends to the forum, or one header) to read it signed in.
- code: feed_login_expired
  status: 400
  source: user
  retryable: false
  description: 'The feed still answers a sign-in page with the `auth` sent: copy a fresh cookie from a signed-in browser.'
- code: feed_limit_reached
  status: 409
  source: user
  retryable: false
  description: A workspace reads at most 500 feeds; disconnect one before connecting another.
- code: feed_auth_not_configured
  status: 503
  source: system
  retryable: false
  description: This deployment has no FEED_AUTH_SECRET, so a feed sign-in (auth) cannot be stored encrypted and is refused instead.
- code: email_not_configured
  status: 503
  source: system
  retryable: false
  description: This deployment has no Resend key, so nothing that needs Resend (the audience sync) can run.
- code: invalid_assignee
  status: 400
  source: user
  retryable: false
  description: The assignee id is not a workspace member.
- code: classification_pending
  status: 409
  source: user
  retryable: true
  description: A relevance or sentiment verdict was sent for a mention the classifier has not scored yet.
- code: invalid_member
  status: 400
  source: user
  retryable: false
  description: A person's owner, and the member an outreach activity is credited to, must be workspace members.
- code: already_member
  status: 409
  source: user
  retryable: false
  description: An invitation was sent to an address that already belongs to a member.
- code: last_owner
  status: 409
  source: user
  retryable: false
  description: Removing this member would leave the workspace without an owner.
- code: duplicate_segment
  status: 409
  source: user
  retryable: false
  description: Segment names are unique per workspace.
- code: filter_too_complex
  status: 400
  source: user
  retryable: false
  description: The filters together (lists, anyOf groups, a view or alert rule applied on top) name more values than one query can carry. Shorten the lists or use fewer groups.
- code: duplicate_view
  status: 409
  source: user
  retryable: false
  description: View names are unique per workspace.
- code: duplicate_group
  status: 409
  source: user
  retryable: false
  description: Group names and externalIds are unique per workspace.
- code: default_group
  status: 409
  source: user
  retryable: false
  description: Every workspace keeps one default group, where a keyword lands when no group is named.
- code: default_group_context
  status: 400
  source: user
  retryable: false
  description: 'The default group is the workspace itself: its company is the profile (PATCH /v1/company). A company description goes on any other group.'
- code: group_changed
  status: 409
  source: user
  retryable: false
  description: A keyword was created in or moved into the group while its keywords were being deleted. Its other keywords are gone; retry the delete.
- code: invalid_signature
  status: 401
  source: user
  retryable: false
  description: An inbound webhook did not carry a valid signature.
- code: webhook_not_configured
  status: 503
  source: system
  retryable: false
  description: The inbound webhook has no secret on this deployment.
- code: invalid_token
  status: 400
  source: user
  retryable: false
  description: A signed link (unsubscribe, confirmation) was tampered with or is malformed.
- code: protected_user
  status: 409
  source: user
  retryable: false
  description: Staff accounts cannot be deleted from the admin page.
- code: upstream_unavailable
  status: 502
  source: platform
  retryable: true
  description: A provider (Slack, Telegram, Polar, …) failed while serving your request. Retry with backoff.
- code: internal_error
  status: 500
  source: system
  retryable: false
  description: Something failed on our side. The response carries a requestId; quote it to support.