Billing.
Read the wallet ledger, receipts, invoices, this period's usage against your limits, your plan and your prices. Every request needs an API key in the Authorization header; the reference overview covers keys, errors and rate limits.
List wallet transactions
GET/v1/billing/transactionsFull access key
Every row of the team's wallet, as the billing page's ledger lists it: top-ups, Pro months, units, SMS charges and releases, sender ID fees and refunds, adjustments and reversals. amountMinor is signed (positive into the wallet) in the wallet's currency; receiptReference is set on a row that has a receipt. type lists one kind of row only. Newest first. Filter with from (inclusive) and to (exclusive) as ISO 8601 times. Pass nextCursor back as cursor for the next page; limit is 1 to 100 (20 by default). A team with no wallet yet answers an empty list and a null currency.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
| Field | Type | About |
|---|---|---|
type | string | Only rows of this type. One of |
from | string | Only rows made at or after this time (ISO 8601). |
to | string | Only rows made before this time (ISO 8601). |
cursor | string | `nextCursor` from the previous page. |
limit | integer | Default |
curl -X GET "https://app.usenotix.dev/api/v1/billing/transactions" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.transactions({ type: "SMS_CHARGE", from: "2026-09-01T00:00:00Z" });
const next = data?.nextCursor; // pass back as cursor for the next page
Responses
200A page of the wallet's rows, newest first, with the cursor for the next page.
| Field | Type | About |
|---|---|---|
currencyrequired | string | The wallet's currency; null when the team has no wallet yet. One of |
datarequired | object[] | |
data[].idrequired | string | |
data[].typerequired | string | One of |
data[].amountMinorrequired | integer | Signed, in the currency's minor unit: positive into the wallet, negative out of it. |
data[].amountFormattedrequired | string | |
data[].balanceAfterMinorrequired | integer | |
data[].balanceAfterFormattedrequired | string | |
data[].referencerequired | string | |
data[].customerDescriptionrequired | string | What Notix wrote for you on this row, when anything. Can be null. |
data[].receiptReferencerequired | string | Set when the row has a receipt: read it with GET /v1/billing/receipts/{reference}. Can be null. |
data[].createdAtrequired | string (date-time) | |
nextCursorrequired | string | Can be null. |
400A query value is not valid, or the cursor is not from this list.
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
422The read took longer than 10 seconds.
429The team read billing 60 times in the last minute.
503The rate counters cannot be read just now; try again shortly.
List receipts
GET/v1/billing/receiptsFull access key
The receipts in the team's wallet: paid top-ups, Pro months paid from the wallet (with their invoice number), sender ID fees and their refunds. Newest first. Filter with from (inclusive) and to (exclusive) as ISO 8601 times. Pass nextCursor back as cursor for the next page; limit is 1 to 100 (20 by default). A page can hold fewer than limit receipts and still have a nextCursor.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
| Field | Type | About |
|---|---|---|
type | string | Only receipts of this type. One of |
from | string | Only rows made at or after this time (ISO 8601). |
to | string | Only rows made before this time (ISO 8601). |
cursor | string | `nextCursor` from the previous page. |
limit | integer | Default |
curl -X GET "https://app.usenotix.dev/api/v1/billing/receipts" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.receipts({ type: "PRO_CHARGE" });
Responses
200A page of receipts, newest first.
| Field | Type | About |
|---|---|---|
currencyrequired | string | One of |
datarequired | object[] | |
data[].invoiceNumberrequired | string | Set on a Pro month paid from the wallet. Can be null. |
data[].referencerequired | string | |
data[].typerequired | string | One of |
data[].titlerequired | string | |
data[].descriptionrequired | string | |
data[].amountMinorrequired | integer | Negative for money that left the wallet, positive for money that entered it. |
data[].amountFormattedrequired | string | The amount without its sign. |
data[].directionrequired | string | One of |
data[].balanceAfterMinorrequired | integer | |
data[].balanceAfterFormattedrequired | string | |
data[].currencyrequired | string | One of |
data[].createdAtrequired | string (date-time) | |
nextCursorrequired | string | A page can hold fewer than `limit` receipts and still have a next one. Can be null. |
400A query value is not valid, or the cursor is not from this list.
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
422The read took longer than 10 seconds.
429The team read billing 60 times in the last minute.
503The rate counters cannot be read just now; try again shortly.
Get a receipt
GET/v1/billing/receipts/{reference}Full access key
One receipt by its reference (a transaction's receiptReference), with the figures the printable receipt shows. Another team's reference, a row that is not a receipt and a top-up that never paid answer 404.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
| Field | Type | About |
|---|---|---|
referencerequired | string |
curl -X GET "https://app.usenotix.dev/api/v1/billing/receipts/<reference>" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.receipt("plan_42_2026-10-01");
Responses
200One receipt, as the printable receipt page shows it.
| Field | Type | About |
|---|---|---|
invoiceNumberrequired | string | Set on a Pro month paid from the wallet. Can be null. |
referencerequired | string | |
typerequired | string | One of |
titlerequired | string | |
descriptionrequired | string | |
amountMinorrequired | integer | Negative for money that left the wallet, positive for money that entered it. |
amountFormattedrequired | string | The amount without its sign. |
directionrequired | string | One of |
balanceAfterMinorrequired | integer | |
balanceAfterFormattedrequired | string | |
currencyrequired | string | One of |
createdAtrequired | string (date-time) | |
teamNamerequired | string |
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
404No receipt with this reference in the team's wallet.
422The read took longer than 10 seconds.
429The team read billing 60 times in the last minute.
503The rate counters cannot be read just now; try again shortly.
List invoices
GET/v1/billing/invoicesFull access key
The team's latest 12 Stripe invoices, newest first, as the billing page lists them: id, number, date, amounts in cents and status. The id is Stripe's own (in_...), since Notix has no other id for an invoice; it opens nothing by itself. The link to pay or download an invoice is not returned: open it from the billing page. A team Stripe has never billed answers an empty list. A Pro month paid from the wallet is a receipt, not a Stripe invoice: see GET /v1/billing/receipts.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
curl -X GET "https://app.usenotix.dev/api/v1/billing/invoices" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.invoices();
Responses
200The team's latest 12 Stripe invoices, newest first. Empty for a team Stripe has never billed.
| Field | Type | About |
|---|---|---|
datarequired | object[] | |
data[].idrequired | string | Stripe's own invoice id (`in_...`): Notix has no other id for it. |
data[].numberrequired | string | Can be null. |
data[].createdAtrequired | string (date-time) | |
data[].amountDuerequired | integer | Minor units (cents). |
data[].amountPaidrequired | integer | Minor units (cents). |
data[].currencyrequired | string | |
data[].statusrequired | string |
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
429The team read invoices 20 times in the last minute, or Notix's invoice reads across every team are at their limit.
503Stripe or the rate counters cannot be reached just now.
Get an invoice
GET/v1/billing/invoices/{id}Full access key
One Stripe invoice of the team, by its Stripe id (in_...). An invoice of any other Stripe customer answers 404. The link to pay or download it is not returned: open it from the billing page.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
| Field | Type | About |
|---|---|---|
idrequired | string |
curl -X GET "https://app.usenotix.dev/api/v1/billing/invoices/<id>" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.invoice("in_1PqRsTuVwXyZ");
Responses
200One Stripe invoice of the team.
| Field | Type | About |
|---|---|---|
idrequired | string | Stripe's own invoice id (`in_...`): Notix has no other id for it. |
numberrequired | string | Can be null. |
createdAtrequired | string (date-time) | |
amountDuerequired | integer | Minor units (cents). |
amountPaidrequired | integer | Minor units (cents). |
currencyrequired | string | |
statusrequired | string |
400The id is not an invoice id.
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
404No invoice with this id for this team.
429The team read invoices 20 times in the last minute, or Notix's invoice reads across every team are at their limit.
503Stripe or the rate counters cannot be reached just now.
Get the plan
GET/v1/billing/subscriptionFull access key
The team's plan and how it is paid: the card subscription (status, period, whether it cancels at the period's end), the wallet's state (renewal date, grace, whether units are blocked), the Pro price in the wallet's currency (a fixed local price for NGN and KES) and the Pro month the team is on, owes or is paying, with its status and whether it is cancelled at the period's end. Read only: change the plan in the dashboard.
Who can call it
A full access or read only key made by someone who is a team admin today (the team owner always is), as the billing page is for admins. A key made by a member answers 403 FORBIDDEN, and so does a key made before Notix recorded who made each key. Sandbox, send-only and live AI keys answer 403 SCOPE_DENIED; a key limited to one domain answers 403 DOMAIN_PINNED. Every read is recorded in the key's audit log (GET /v1/audit-log).
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
curl -X GET "https://app.usenotix.dev/api/v1/billing/subscription" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.subscription();
console.log(data?.planPayment.live?.periodEnd);
Responses
200The team's plan: how it is paid, its renewal and grace dates, and the Pro month it is on.
| Field | Type | About |
|---|---|---|
planrequired | string | |
isActiverequired | boolean | |
billingMethodrequired | string | One of |
striperequired | object | The card subscription, when the team has one. Can be null. |
stripe.statusrequired | string | |
stripe.currentPeriodStartrequired | string (date-time) | Can be null. |
stripe.currentPeriodEndrequired | string (date-time) | Can be null. |
stripe.cancelAtPeriodEndrequired | boolean | |
stripe.cancelAtrequired | string (date-time) | Can be null. |
walletrequired | object | |
wallet.staterequired | string | One of |
wallet.proRenewsAtrequired | string (date-time) | Can be null. |
wallet.graceStartedAtrequired | string (date-time) | Can be null. |
wallet.graceEndsAtrequired | string (date-time) | Can be null. |
wallet.unitsBlockedrequired | boolean | |
planPaymentrequired | object | |
planPayment.currencyrequired | string | One of |
planPayment.priceMinorrequired | integer | |
planPayment.priceFormattedrequired | string | |
planPayment.priceConfiguredrequired | boolean | |
planPayment.fixedPricerequired | boolean | True for NGN and KES, which pay a fixed local price. |
planPayment.walletPaysPlanrequired | boolean | |
planPayment.liverequired | object | The Pro month the team is on, owes or is paying (wallet or saved card). Can be null. |
planPayment.live.statusrequired | string | One of |
planPayment.live.paidViarequired | string | One of |
planPayment.live.periodStartrequired | string (date-time) | |
planPayment.live.periodEndrequired | string (date-time) | |
planPayment.live.amountMinorrequired | integer | |
planPayment.live.amountFormattedrequired | string | |
planPayment.live.cancelAtPeriodEndrequired | boolean | |
planPayment.live.graceEndsAtrequired | string (date-time) | Can be null. |
planPayment.live.invoiceNumberrequired | string | Can be null. |
planPayment.live.receiptReferencerequired | string | Can be null. |
403`SCOPE_DENIED`: a sandbox, send-only or live AI key. `DOMAIN_PINNED`: a key limited to one domain. `FORBIDDEN`: the key was made by a member who is not a team admin, or before Notix recorded who made each key.
429The team read billing 60 times in the last minute.
503The rate counters cannot be read just now; try again shortly.
Get usage
GET/v1/billing/usageFull access key
The figures the Usage and billing pages show: this billing period's emails against the monthly and daily limits (the daily limit is the one enforced today), the plan's units and an estimate of any overage, the team's domains, contact books, members and webhooks against the plan, the API rate limit, and this calendar month's emails, texts and one-time codes. thisMonth.textSpendFormatted (what the texts cost the wallet) is only given to a key made by a team admin that is not limited to one domain; it is null otherwise.
Who can call it
Full access, read only and live AI keys, including a key limited to one domain: they help a caller stay within the team's limits. Sandbox and send-only keys answer 403 SCOPE_DENIED.
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
curl -X GET "https://app.usenotix.dev/api/v1/billing/usage" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.usage();
const daily = data?.sending.daily; // used, limit, percentUsed
Responses
200This period's sending and resources against the plan's limits, and this calendar month's texts and codes.
| Field | Type | About |
|---|---|---|
periodrequired | object | |
period.startDayrequired | string | |
period.endDayrequired | string | Exclusive; null when the period has no set end. Can be null. |
period.labelrequired | string | |
planrequired | object | |
plan.keyrequired | string | |
plan.effectiveKeyrequired | string | The plan the limits are enforced against today. |
plan.displayNamerequired | string | |
plan.monthlyUsdrequired | number | |
plan.statusrequired | string | Can be null. |
plan.isEntitledrequired | boolean | |
emailsrequired | object | |
emails.marketingThisMonthrequired | integer | |
emails.transactionalThisMonthrequired | integer | |
emails.totalThisMonthrequired | integer | |
emails.totalTodayrequired | integer | |
sendingrequired | object | |
sending.monthlyrequired | object | |
sending.monthly.usedrequired | integer | |
sending.monthly.limitrequired | integer | -1 means no limit. |
sending.monthly.unlimitedrequired | boolean | |
sending.monthly.percentUsedrequired | number | |
sending.dailyrequired | object | |
sending.daily.usedrequired | integer | |
sending.daily.limitrequired | integer | -1 means no limit. |
sending.daily.unlimitedrequired | boolean | |
sending.daily.percentUsedrequired | number | |
unitsrequired | object | Null on the free plan, which is not metered. Can be null. |
units.includedrequired | integer | |
units.usedrequired | integer | |
units.overagerequired | integer | |
units.overageUsdrequired | number | |
units.overageMinorrequired | integer | |
units.overageFormattedrequired | string | |
units.unitPriceFormattedrequired | string | Can be null. |
units.noterequired | string | |
billingrequired | object | |
billing.methodrequired | string | One of |
billing.currencyrequired | string | One of |
billing.unitPriceMicrorequired | integer | Can be null. |
resourcesrequired | object | |
resources.domainsrequired | object | |
resources.domains.usedrequired | integer | |
resources.domains.limitrequired | integer | -1 means no limit. |
resources.domains.unlimitedrequired | boolean | |
resources.domains.percentUsedrequired | number | |
resources.contactBooksrequired | object | |
resources.contactBooks.usedrequired | integer | |
resources.contactBooks.limitrequired | integer | -1 means no limit. |
resources.contactBooks.unlimitedrequired | boolean | |
resources.contactBooks.percentUsedrequired | number | |
resources.teamMembersrequired | object | |
resources.teamMembers.usedrequired | integer | |
resources.teamMembers.limitrequired | integer | -1 means no limit. |
resources.teamMembers.unlimitedrequired | boolean | |
resources.teamMembers.percentUsedrequired | number | |
resources.webhooksrequired | object | |
resources.webhooks.usedrequired | integer | |
resources.webhooks.limitrequired | integer | -1 means no limit. |
resources.webhooks.unlimitedrequired | boolean | |
resources.webhooks.percentUsedrequired | number | |
apiRateLimitrequired | integer | Requests a second the team's keys may make. |
thisMonthrequired | object | This calendar month (UTC), as the billing page's "This month" card shows it. |
thisMonth.emailsrequired | object | |
thisMonth.emails.usedrequired | integer | |
thisMonth.emails.limitrequired | integer | |
thisMonth.emails.unlimitedrequired | boolean | |
thisMonth.emails.percentrequired | number | |
thisMonth.textsrequired | integer | |
thisMonth.codesrequired | integer | |
thisMonth.textSpendFormattedrequired | string | What this month's texts cost the wallet. Only for a key a team admin made that is not limited to one domain. Can be null. |
403`SCOPE_DENIED`: a sandbox or send-only key.
422The read took longer than 10 seconds.
429The team read billing 60 times in the last minute.
503The rate counters cannot be read just now; try again shortly.
Get prices
GET/v1/billing/pricingFull access key
The package price list the billing page's Pricing table shows, in the team's billing currency (USD for a team that has not chosen one): each channel's volume tiers and the price of each product line per tier, in millionths of the currency's major unit per message. A null cell is "On request". pro is the Pro plan's monthly price in the same currency; NGN and KES pay a fixed local price.
Who can call it
Full access, read only and live AI keys, including a key limited to one domain: they help a caller stay within the team's limits. Sandbox and send-only keys answer 403 SCOPE_DENIED.
The team can make 60 billing reads a minute through the API (20 for invoices, which are read from Stripe, within a limit shared by every team); when Notix cannot count them the answer is 503 SERVICE_UNAVAILABLE (try again shortly), never a 429.
curl -X GET "https://app.usenotix.dev/api/v1/billing/pricing" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.billing.pricing();
console.log(data?.pro.monthlyFormatted);
Responses
200The package price list in the team's billing currency, and the Pro plan's monthly price.
| Field | Type | About |
|---|---|---|
currencyrequired | string | One of |
channelsrequired | object[] | |
channels[].channelrequired | string | One of |
channels[].labelrequired | string | |
channels[].tiersrequired | object[] | |
channels[].tiers[].idrequired | string | |
channels[].tiers[].positionrequired | integer | |
channels[].tiers[].namerequired | string | |
channels[].tiers[].minVolumerequired | integer | |
channels[].tiers[].maxVolumerequired | integer | Can be null. |
channels[].tiers[].recommendedrequired | boolean | |
channels[].tiers[].volumeLabelrequired | string | |
channels[].linesrequired | object[] | |
channels[].lines[].productLinerequired | string | One of |
channels[].lines[].labelrequired | string | |
channels[].lines[].monthlyFeerequired | boolean | |
channels[].lines[].cellsrequired | object[] | |
prorequired | object | |
pro.currencyrequired | string | One of |
pro.monthlyMinorrequired | integer | |
pro.monthlyFormattedrequired | string | |
pro.unitPriceMicrorequired | integer | |
pro.fixedPricerequired | boolean | True for NGN and KES, which pay a fixed local price. |
pro.configuredrequired | boolean | False when Notix has not priced this currency yet. |