mentio-dev Billing API

The Billing API from mentio-dev — 5 operation(s) for billing.

Operations 5

POST /v1/billing/top-ups Create a top-up checkout #
GET /v1/billing/wallet Get the wallet #
GET /v1/billing/ledger List ledger entries #
GET /v1/billing/invoices List receipts #
GET /v1/billing/invoices/{id}/url Get a receipt link #

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-billing-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-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Mentio Dev Billing API
  version: 0.0.1
  description: 'Operations tagged Billing 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: Billing
paths:
  /v1/billing/top-ups:
    post:
      operationId: createTopUp
      summary: Create a top-up checkout
      description: Returns a hosted checkout URL with `amountCents` prefilled (editable there, $20 to $5,000). The balance is credited when the payment lands, within a minute, and tracking the wallet had paused resumes at once. Nothing is charged by this call itself. `successUrl` must be on an origin this deployment trusts; omit it for the dashboard's billing page.
      tags:
      - Billing
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                amountCents:
                  type: integer
                  minimum: 2000
                  maximum: 500000
                  description: Amount to add, in USD cents (2000 to 500000). Prefilled at checkout, editable there.
                successUrl:
                  type: string
                  maxLength: 2000
                  format: uri
                  description: 'Where the customer lands after paying: a page on an origin this deployment trusts (the dashboard). Omit it and the dashboard''s billing page is used.'
              required:
              - amountCents
      responses:
        '200':
          description: Hosted checkout URL with the amount prefilled
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    description: Hosted Polar checkout URL.
                required:
                - url
        '400':
          description: Invalid amount or disallowed successUrl
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Workspace has no owner to bill
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: More than a few checkouts a minute for one workspace
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Billing is not configured on this deployment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
  /v1/billing/wallet:
    get:
      operationId: getWallet
      summary: Get the wallet
      description: 'The prepaid balance in full: ledger, pending mention charges and the effective balance the stop rule reads, the daily burn and the days it buys, how many keywords run and how many the wallet paused, what a day costs and what a resume needs, the welcome credit, the newest top-up, the top-up bounds and the auto-recharge settings. `GET /v1/usage` is the short form.'
      tags:
      - Billing
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Balance, burn, and whether tracking is paused
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Wallet'
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
  /v1/billing/ledger:
    get:
      operationId: listLedger
      summary: List ledger entries
      description: 'Every movement of the balance, newest first: the welcome credit, top-ups, refunds, the daily keyword-day and mention debits, adjustments. A debit row carries the UTC day it settled and the cumulative units behind it. Cursor paged.'
      tags:
      - Billing
      security:
      - bearerAuth: []
      parameters:
      - schema:
          type: string
          description: Opaque cursor from a previous page (`nextCursor`).
        required: false
        description: Opaque cursor from a previous page (`nextCursor`).
        name: cursor
        in: query
      - schema:
          type: integer
          minimum: 1
          maximum: 100
          description: Page size, 1 to 100 (default 25).
          example: 25
        required: false
        description: Page size, 1 to 100 (default 25).
        name: limit
        in: query
      responses:
        '200':
          description: Ledger entries, newest first
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LedgerList'
        '400':
          description: Invalid cursor
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
  /v1/billing/invoices:
    get:
      operationId: listInvoices
      summary: List receipts
      description: 'The orders behind the top-ups, newest first, as the merchant of record (Polar) holds them: this workspace''s share of the billing customer''s newest 100 orders. Empty before the first top-up.'
      tags:
      - Billing
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Recent paid orders (receipts). Empty when the org has never paid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceList'
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
  /v1/billing/invoices/{id}/url:
    get:
      operationId: getInvoiceUrl
      summary: Get a receipt link
      description: A short-lived link to the receipt PDF of one paid order (an id from the receipts list).
      tags:
      - Billing
      security:
      - bearerAuth: []
      parameters:
      - schema:
          type: string
          minLength: 1
          description: The order id from GET /v1/billing/invoices.
        required: true
        description: The order id from GET /v1/billing/invoices.
        name: id
        in: path
      responses:
        '200':
          description: A short-lived link to the receipt PDF
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    description: A short-lived link to the receipt PDF.
                required:
                - url
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: No such receipt, or its PDF is not ready yet
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Billing is not configured
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    servers:
    - url: https://api.mentio.dev
components:
  schemas:
    Wallet:
      type: object
      properties:
        balanceCents:
          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.
        effectiveBalanceCents:
          type: integer
          description: 'balanceCents minus pendingCents: what the stop sweep and the keyword gate look at.'
        burnPerDayCents:
          type: integer
          description: Average daily debit over the last 7 days (or since the workspace was created).
        daysLeft:
          type:
          - integer
          - 'null'
          minimum: 0
          description: effectiveBalanceCents divided by burnPerDayCents; null when nothing is burning.
        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: the same rule as the low-balance email.'
        activeKeywords:
          type: integer
          minimum: 0
          description: Unmuted keywords.
        autoMutedKeywords:
          type: integer
          minimum: 0
          description: Keywords the wallet paused; a top-up resumes them.
        nextDayCents:
          type: integer
          description: What one more day of the running keywords costs; tracking stops when the effective balance drops under it.
        resumeCostCents:
          type: integer
          description: What one day of every keyword (running and paused) costs; a stopped workspace resumes once the effective balance covers it.
        signupCredit:
          type:
          - object
          - 'null'
          properties:
            amountCents:
              type: integer
              description: Integer USD cents.
            grantedAt:
              type: string
              description: ISO 8601 timestamp, UTC.
          required:
          - amountCents
          - grantedAt
          description: The welcome credit this workspace received, or null (a second workspace of the same user gets none).
        lastTopUpAt:
          type:
          - string
          - 'null'
          description: Newest paid top-up; null before the first.
        billingConfigured:
          type: boolean
          description: 'False when this deployment has no Polar credentials: the top-up button is hidden.'
        minTopUpCents:
          type: integer
          description: Smallest top-up the checkout accepts.
        maxTopUpCents:
          type: integer
          description: Largest single top-up.
        defaultTopUpCents:
          type: integer
          description: Amount prefilled in the checkout.
        currency:
          type: string
          enum:
          - USD
          description: Every amount on this page is in USD cents.
        autoRecharge:
          type: object
          properties:
            available:
              type: boolean
              description: This deployment can charge saved cards; false hides the setting.
            enabled:
              type: boolean
              description: Charge the saved card automatically when the balance runs low.
            thresholdCents:
              type: integer
              description: Charge when the effective balance drops under this.
            amountCents:
              type: integer
              description: How much to add per automatic charge (same bounds as a manual top-up).
            weeklyLimitCents:
              type:
              - integer
              - 'null'
              description: Most the saved card may be charged automatically over any 7 days, before tax; null = no limit.
            spentThisWeekCents:
              type: integer
              description: 'What counts against the weekly limit over the last 7 days, before tax: automatic charges made plus any still settling.'
            lastRunAt:
              type:
              - string
              - 'null'
              description: Newest successful automatic charge.
            lastError:
              type:
              - string
              - 'null'
              description: Why the last automatic charge failed; null after a success.
          required:
          - available
          - enabled
          - thresholdCents
          - amountCents
          - weeklyLimitCents
          - spentThisWeekCents
          - lastRunAt
          - lastError
      required:
      - balanceCents
      - pendingCents
      - effectiveBalanceCents
      - burnPerDayCents
      - daysLeft
      - stopped
      - lowBalance
      - activeKeywords
      - autoMutedKeywords
      - nextDayCents
      - resumeCostCents
      - signupCredit
      - lastTopUpAt
      - billingConfigured
      - minTopUpCents
      - maxTopUpCents
      - defaultTopUpCents
      - currency
      - autoRecharge
    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
    LedgerList:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                description: Ledger entry id (led_...).
              kind:
                type: string
                enum:
                - signup_credit
                - topup
                - refund
                - debit_keyword_days
                - debit_mentions
                - debit_comments
                - adjustment
                description: signup_credit, topup, refund, debit_keyword_days, debit_mentions, debit_comments or adjustment.
              amountCents:
                type: integer
                description: Integer USD cents; credits positive, debits negative.
              day:
                type:
                - string
                - 'null'
                description: 'Debit rows: the last UTC day the row settled (YYYY-MM-DD).'
              units:
                type:
                - integer
                - 'null'
                description: 'Debit rows: cumulative units (mentions or keyword-days) settled up to this row.'
              note:
                type:
                - string
                - 'null'
                description: Free text on credits and adjustments.
              polarOrderId:
                type:
                - string
                - 'null'
                description: 'Top-ups and refunds: the Polar order.'
              createdAt:
                type: string
                description: ISO 8601 timestamp, UTC.
            required:
            - id
            - kind
            - amountCents
            - day
            - units
            - note
            - polarOrderId
            - createdAt
          description: Ledger entries, newest first.
        nextCursor:
          type:
          - string
          - 'null'
          description: Pass it back as `cursor` for the next page; null on the last.
      required:
      - data
      - nextCursor
    InvoiceList:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                description: The Polar order id; what GET /v1/billing/invoices/{id}/url takes.
              createdAt:
                type: string
                description: When the order was placed (ISO 8601).
              status:
                type: string
                description: The order status as Polar reports it (paid, refunded, ...).
              paid:
                type: boolean
                description: Whether the order was paid.
              totalAmount:
                type: integer
                description: What was charged, in minor units of `currency`, tax included.
              currency:
                type: string
                description: ISO 4217 currency of the order (usd).
              billingReason:
                type:
                - string
                - 'null'
                description: Why the order exists, as Polar reports it (purchase, subscription_cycle, ...); null when it does not say.
            required:
            - id
            - createdAt
            - status
            - paid
            - totalAmount
            - currency
            - billingReason
          description: Paid orders, newest first; empty before the first top-up.
      required:
      - data
  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.