Usage and costs API
Messages, AI replies and estimated Meta costs. 8 ops: get_overview, get_usage, get_costs, get_analytics, get_meta_rates, list_spend_budgets, set_spend_budget, delete_spend_budget.
Messages, AI replies and estimated Meta costs.
get_overview
readGet overview · POST /api/v1/get_overview · scope usage:read or GET …?input=
The operations snapshot the dashboard Overview shows, right now: conversations needing a reply (and the oldest waiting since), escalated ones, customer service windows expiring soon and open, today's outbound messages sent / delivered / read / failed with delivery and read rates, today's estimated Meta spend (labeled estimate), the AI-contained resolution rate over the last 30 days, and this period's plan usage. Call it to answer "how are we doing today" or before deciding what to work on first. Definitions are in `definitions`.
curl -X POST https://getwabi.dev/api/v1/get_overview \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi get_overview{
"type": "object",
"properties": {
"window_warning_minutes": {
"default": 120,
"description": "How soon a window must close to count as expiring, in minutes. Default 120.",
"type": "integer",
"minimum": 5,
"maximum": 1440
}
}
}get_usage
readGet usage · POST /api/v1/get_usage · scope usage:read or GET …?input=
This period's plan usage and message volume: messages and AI replies used against the plan's allowance (percent, month-end forecast), overage so far and its forecast against the budget cap, whether sends are stopped, the counted limits (numbers, members, agents), and for a date range the messages sent, delivered, read, failed and received per day, template vs free-form, by country, read rate by template locale and the most common failure codes. Sandbox messages are free and excluded unless sandbox is true or "all". Use it before a bulk send, or when someone asks how much of the plan is left. Plan changes: get_pricing and create_checkout_link; the cap: set_budget_cap.
curl -X POST https://getwabi.dev/api/v1/get_usage \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi get_usage{
"type": "object",
"properties": {
"from": {
"description": "Start of the range (ISO 8601). Default: the first day of this month, UTC.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"to": {
"description": "End of the range, exclusive (ISO 8601). Default: now.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"days": {
"description": "Instead of from: the last N days up to `to`.",
"type": "integer",
"minimum": 1,
"maximum": 400
},
"sandbox": {
"default": false,
"description": "Which numbers to count: false live numbers only (default), true the sandbox only, \"all\" both.",
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"const": "all"
}
]
}
}
}get_costs
readGet costs · POST /api/v1/get_costs · scope usage:read or GET …?input=
Meta's per-message fees for a date range, as provisional estimates (one per delivered outbound message, priced from Meta's published rate card in force that day by the recipient's market, the category and the month's volume tier; free messages counted at 0) and, separately, reconciled actuals from Meta's pricing analytics per account and day (with discrepancies flagged). Broken down by day, category, template, country, account, campaign and agent, with cost per delivered message, this month's spend and month-end forecast, spend budgets and how close each is, and the rate card used. Meta bills these fees to the customer's WhatsApp Business Account at cost; Wabi never marks them up or bills them. Sandbox costs (what the same traffic would cost live) only with sandbox true or "all".
curl -X POST https://getwabi.dev/api/v1/get_costs \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi get_costs{
"type": "object",
"properties": {
"from": {
"description": "Start of the range (ISO 8601). Default: the first day of this month, UTC.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"to": {
"description": "End of the range, exclusive (ISO 8601). Default: now.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"days": {
"description": "Instead of from: the last N days up to `to`.",
"type": "integer",
"minimum": 1,
"maximum": 400
},
"sandbox": {
"default": false,
"description": "Which numbers to count: false live numbers only (default), true the sandbox only, \"all\" both.",
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"const": "all"
}
]
}
}
}get_analytics
readGet analytics · POST /api/v1/get_analytics · scope usage:read or GET …?input=
Support and operational metrics for a date range, each with its formal definition: conversations created, needing a reply and unanswered, first response time and resolution time (p50 and p90 seconds), reopen rate, AI-contained resolution rate (provisional for the last 72 hours), escalation rate, AI answer quality from evaluations, CSAT, top support categories and per-assignee workload with SLA risk; plus delivery analytics and cost optimization hints (billed templates that could have been free inside an open window, utility sent outside the window, expensive destinations, duplicate notifications, failure patterns, low-read locales), each with its numbers. Filter by account, AI agent or conversation language. Use it for a weekly review or to find what to fix.
curl -X POST https://getwabi.dev/api/v1/get_analytics \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi get_analytics{
"type": "object",
"properties": {
"from": {
"description": "Start of the range (ISO 8601). Default: the first day of this month, UTC.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"to": {
"description": "End of the range, exclusive (ISO 8601). Default: now.",
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"days": {
"description": "Instead of from: the last N days up to `to`.",
"type": "integer",
"minimum": 1,
"maximum": 400
},
"account_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "WhatsApp Business Account id in this organization (whatsapp_accounts.id, not Meta's WABA id)."
},
"agent_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "AI agent id."
},
"language": {
"description": "Only conversations in this language (BCP 47, e.g. es, pt-BR).",
"type": "string",
"minLength": 2,
"maxLength": 35
}
}
}get_meta_rates
readGet Meta rates · POST /api/v1/get_meta_rates · scope usage:read or GET …?input=
What Meta charges per delivered message in a market, from its published rate card in force on a date: by category (marketing, utility, authentication, authentication_international, service) with the volume tiers for utility and authentication, in USD. Pass a recipient's WhatsApp id (or phone number with country code) or an ISO country code. Service messages and utility templates inside an open 24-hour window are free. Use it to estimate a campaign's cost before sending; the exact charge is on each message's estimate (get_costs).
curl -X POST https://getwabi.dev/api/v1/get_meta_rates \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi get_meta_rates{
"type": "object",
"properties": {
"wa_id": {
"description": "Recipient's WhatsApp id or phone number with country code, e.g. 447700900123.",
"type": "string",
"pattern": "^\\+?[0-9 ()-]{6,20}$"
},
"country": {
"description": "ISO 3166 country code, e.g. GB. Ignored when wa_id is given.",
"type": "string",
"pattern": "^[A-Za-z]{2}$"
},
"category": {
"description": "Only this category.",
"type": "string",
"enum": [
"marketing",
"utility",
"authentication",
"authentication_international",
"service"
]
},
"date": {
"description": "The day to price (YYYY-MM-DD). Default today.",
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
}
}
}List spend budgets · POST /api/v1/list_spend_budgets · scope usage:read or GET …?input=
This organization's monthly Meta spend budgets (organization-wide, per WhatsApp account, per campaign): the limit, alert thresholds, whether non-critical sends stop at 100 %, what was spent this month (estimated), percent used and the month-end forecast.
curl -X POST https://getwabi.dev/api/v1/list_spend_budgets \ -H "Authorization: Bearer wabi_…"npx @meterapp/wabi list_spend_budgets{
"type": "object",
"properties": {}
}Set spend budget · POST /api/v1/set_spend_budget · scope usage:write
Create or replace a monthly budget on estimated Meta spend, for the whole organization, one WhatsApp account or one campaign, in US dollars. Owners and admins are emailed when spend passes each alert threshold (default 50, 80 and 100 %). With hard_stop, marketing and bulk sends from that scope are refused once the month's spend reaches the limit; authentication, utility and replies are never stopped. Separate from the plan's overage cap (set_budget_cap). A human decision: only when asked.
curl -X POST https://getwabi.dev/api/v1/set_spend_budget \ -H "Authorization: Bearer wabi_…" \ -H "Content-Type: application/json" \ -d '{"monthly_limit":1}'npx @meterapp/wabi set_spend_budget --json '{"monthly_limit":1}'{
"type": "object",
"properties": {
"scope": {
"default": "organization",
"type": "string",
"enum": [
"organization",
"account",
"campaign"
]
},
"account_id": {
"description": "For scope account.",
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"campaign_id": {
"description": "For scope campaign.",
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"monthly_limit": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 10000000,
"description": "US dollars of estimated Meta spend per calendar month."
},
"alert_thresholds": {
"default": [
50,
80,
100
],
"description": "Percents of the limit that send an alert.",
"minItems": 1,
"maxItems": 6,
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"hard_stop": {
"default": false,
"description": "Refuse non-critical sends from this scope at 100 %.",
"type": "boolean"
}
},
"required": [
"monthly_limit"
]
}Delete spend budget · POST /api/v1/delete_spend_budget · scope usage:write
Remove a Meta spend budget by id (list_spend_budgets). Its alerts stop and its hard stop, if any, lifts at once.
curl -X POST https://getwabi.dev/api/v1/delete_spend_budget \ -H "Authorization: Bearer wabi_…" \ -H "Content-Type: application/json" \ -d '{"id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'npx @meterapp/wabi delete_spend_budget --json '{"id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Budget id from list_spend_budgets."
}
},
"required": [
"id"
]
}