Skip to content
Cowliss is in beta: features and pricing may change.

Billing

Spend is one weighted total over events, emails, webhooks and automation runs, counted from what already happened, never billed in arrears. Credit is the plan’s monthly included usage ($0.50 on Free, $15 on Plus; resets each UTC month, no rollover) plus the prepaid wallet (carries over). At zero credit, the platform hard-stops: ingestion is refused and sends are skipped. The plan also caps what an organization holds (live apps: 1 on Free, 15 on Plus; sending domains: 1 on Free, 10 on Plus). limits reports what it holds against them, and creating one more past a limit answers plan_limit. Subscribing to Plus and managing the subscription happen in the dashboard; the CLI and MCP read the plan from GET /v1/billing. See the Billing guide.

Billing summary for the current UTC month

Auth: Session token.

Response 200

{
"data": {
"plan": "free",
"subscription": {
"status": "string",
"currentPeriodEnd": "2026-01-15T09:30:00.000Z",
"cancelAtPeriodEnd": true
},
"limits": {
"apps": {
"used": 42,
"max": 42
},
"senderDomains": {
"used": 42,
"max": 42
}
},
"allowanceMicros": 42,
"walletBalanceMicros": 42,
"periodStart": "2026-01-15T09:30:00.000Z",
"periodEnd": "2026-01-15T09:30:00.000Z",
"spentMicros": 42,
"remainingMicros": 42,
"overageMicros": 42,
"overageAllowed": true,
"previousMonth": {
"month": "string",
"allowanceMicros": 42,
"spentMicros": 42,
"overageMicros": 42
},
"usage": {
"events": 42,
"emails": 42,
"webhooks": 42,
"automationRuns": 42
},
"prices": {
"event": 42,
"email": 42,
"webhook": 42,
"automationRun": 42
},
"warn": true,
"over": true,
"owing": true
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.plan “free” | “plus” yes
data.subscription object | null yes
data.subscription.status string yes
data.subscription.currentPeriodEnd string (date-time) yes
data.subscription.cancelAtPeriodEnd boolean yes
data.limits object yes
data.limits.apps object yes
data.limits.apps.used integer yes
data.limits.apps.max integer yes
data.limits.senderDomains object yes
data.limits.senderDomains.used integer yes
data.limits.senderDomains.max integer yes
data.allowanceMicros integer yes 0 ≤ x ≤ ∞
data.walletBalanceMicros integer yes
data.periodStart string (date-time) yes
data.periodEnd string (date-time) yes
data.spentMicros integer yes 0 ≤ x ≤ ∞
data.remainingMicros integer yes 0 ≤ x ≤ ∞
data.overageMicros integer yes 0 ≤ x ≤ ∞
data.overageAllowed boolean yes
data.previousMonth object | null yes
data.previousMonth.month string yes
data.previousMonth.allowanceMicros integer yes 0 ≤ x ≤ ∞
data.previousMonth.spentMicros integer yes 0 ≤ x ≤ ∞
data.previousMonth.overageMicros integer yes 0 ≤ x ≤ ∞
data.usage object yes
data.usage.events integer yes 0 ≤ x ≤ ∞
data.usage.emails integer yes 0 ≤ x ≤ ∞
data.usage.webhooks integer yes 0 ≤ x ≤ ∞
data.usage.automationRuns integer yes 0 ≤ x ≤ ∞
data.prices object yes
data.prices.event integer yes 0 ≤ x ≤ ∞
data.prices.email integer yes 0 ≤ x ≤ ∞
data.prices.webhook integer yes 0 ≤ x ≤ ∞
data.prices.automationRun integer yes 0 ≤ x ≤ ∞
data.warn boolean yes
data.over boolean yes
data.owing boolean yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

List wallet top-ups

Auth: Session token.

Query parameters

{
"cursor": "string",
"limit": 50
}
Field Type Required Constraints
cursor string no
limit integer no default 50; 1 ≤ x ≤ 100

Response 200

{
"data": [
{
"id": "string",
"amountMicros": 42,
"status": "pending",
"stripeCheckoutSessionId": "string",
"stripeAdjustmentId": "string",
"createdAt": "2026-01-15T09:30:00.000Z",
"completedAt": "2026-01-15T09:30:00.000Z"
}
],
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object[] yes
data[] object yes
data[].id string yes
data[].amountMicros integer yes
data[].status “pending” | “completed” | “failed” yes
data[].stripeCheckoutSessionId string | null yes
data[].stripeAdjustmentId string | null yes
data[].createdAt string (date-time) yes
data[].completedAt string (date-time) | null yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Start a wallet top-up

Admin only. Returns a hosted checkout URL to redirect to. amountMicros must be one of the fixed presets.

Auth: Session token.

Request body

{
"data": {
"amountMicros": 10000000
}
}
Field Type Required Constraints
data object yes
data.amountMicros 10000000 | 50000000 | 200000000 yes

Response 201

{
"data": {
"checkoutUrl": "https://example.com/hooks/cowliss"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.checkoutUrl string (uri) yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Subscribe to Plus

Admin only. Returns a hosted checkout URL to redirect to. The organization is on Plus once the first payment goes through.

Auth: Session token.

Response 201

{
"data": {
"checkoutUrl": "https://example.com/hooks/cowliss"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.checkoutUrl string (uri) yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Manage the Plus subscription

Admin only. Returns a hosted page to redirect to, where the subscription is cancelled, its card changed, and its invoices downloaded. 404 for an organization that has never subscribed.

Auth: Session token.

Response 201

{
"data": {
"portalUrl": "https://example.com/hooks/cowliss"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.portalUrl string (uri) yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Stripe webhook (public)

Auth: None: verifies the caller’s own signature/token.

Errors follow the shared envelope and code table.