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: 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.