Billing

16 endpoints, generated from the API's own OpenAPI document. The self-serve subscription: plan, interval, seats, county slots, the API add-on, the card, invoices.

GET /v2/plans

The plan catalogue

Credentials: API key or App session. Operation id acctListPlans.

Either credential (an API key or a session); resolves the caller's active organization (X-DTG-Org). Any role. T14/T31: the Trial row, then every active plan in price order, with prices, counties, seats, the monthly points allowance and the API add-on. Every price is read from the payment catalog the checkout charges. Takes no query parameters. No side effects.

Parameters

X-DTG-Orgheader · string (uuid)
The organization this request acts in (a uuid). Omitted: the caller's own organization, else their earliest active membership. An API key is bound to its organization and may only name that one.

Responses

200 success

The catalogue.

As application/json.

dataarray of AcctPlanRowalways present
The rows.
data[].codestringalways present
The plan code (trial for the Trial row).
data[].namestringalways present
The display name (D42-FINAL).
data[].priceobjectalways present
Prices in US dollars.
data[].price.month_usdnumber or nullalways present
Monthly price; null for the Trial row.
data[].price.year_usdnumber or nullalways present
Annual price; null for the Trial row.
data[].countiesobjectalways present
Counties.
data[].counties.includedintegeralways present
Counties included; -1 means every county.
data[].counties.allbooleanalways present
True when every county is included.
data[].counties.extra_month_usdnumber or nullalways present
Price of one extra county slot a month; null when not sold.
data[].counties.extra_year_usdnumber or nullalways present
Price of one extra county slot a year; null when not sold.
data[].seatsobjectalways present
Seats.
data[].seats.includedinteger or nullalways present
Seats included; null for the Trial row.
data[].seats.extra_month_usdnumber or nullalways present
Price of one extra seat a month; null when not sold.
data[].seats.extra_year_usdnumber or nullalways present
Price of one extra seat a year; null when not sold.
data[].points_quota_monthinteger or nullalways present
The plan's monthly points allowance without the API add-on; null when unlimited, and on the Trial row.
data[].csv_accessboolean or nullalways present
True when CSV and XLSX export is included; null on the Trial row.
data[].vintage_accessboolean or nullalways present
True when earlier vintages are included; null on the Trial row.
data[].quarterly_accessboolean or nullalways present
True when quarterly data is included; null on the Trial row.
data[].api_addonobjectalways present
The API add-on with this plan.
data[].api_addon.availablebooleanalways present
True when the add-on is sold with this plan.
data[].api_addon.month_usdnumber or nullalways present
Always null: the add-on is sold with an annual plan only.
data[].api_addon.year_usdnumber or nullalways present
Its annual price; null when not sold.
data[].api_addon.points_quota_monthinteger or nullalways present
The monthly points allowance with the add-on; null when not sold or unlimited.
data[].trialobject or nullalways present
The trial's terms on the Trial row; null on every plan row.
data[].trial.daysintegeralways present
Trial length in days (rules.trial_days).
data[].trial.cooldown_daysnullalways present
Always null (not stated to customers).
data[].trial.countiesintegeralways present
Always 1: a trial unlocks one county.
data[].trial.export"trial_county"always present
Always trial_county: export of the trial county only.
data[].trial.live_keysbooleanalways present
Always false: a trial grants no live API keys.
metaobjectalways present
T153: which payment catalog the prices were read from.
meta.stripe_mode"fake" | "test" | "live"always present
The Stripe mode of the catalog every paid price here was read from: live (production on live keys), test (Stripe test mode) or fake (the development simulation). A pricing check reads it to know which catalog it compared.

400 error

Bad Request. Codes: unknown_parameter (any query parameter; the body carries parameters).

As application/problem+json.

401 error

Unauthorized. Codes: key_revoked (the API key was revoked; revoked_at, reason, and a sentence saying when and why); unauthenticated (no API key or session; the key is unknown, or its account, membership or organization is no longer active; the session has expired, passed its 30-day maximum age, or belongs to an unverified email address).

As application/problem+json.

403 error

Forbidden. Codes: no_membership (the account has no active membership in an active organization), account_suspended (O56: the signed-in person's own account is suspended by DTG; reason where recorded), org_suspended (the selected organization is suspended by DTG; the body carries organization {id, name} and reason), org_closed (the selected organization is closed; the body carries organization {id, name}), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API, or a live key on the sandbox; the body carries expected and base_url, the address that serves it).

As application/problem+json.

404 error

Not Found. Codes: not_found (the X-DTG-Org header is not a uuid, names an organization the caller is not an active member of, or, on an API key, names an organization other than the key's own).

As application/problem+json.

429 error

Only the per-minute rate limit: rate_limited (120 requests a minute per credential, 300 per organization; lower ceilings for a sandbox key), with Retry-After and X-RateLimit-*.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unknown_parameter (400), key_revoked (401), unauthenticated (401), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), not_found (404), rate_limited (429). Every problem is a problem document.

GET /v2/account/billing

The organization's billing state

Credentials: API key or App session. Operation id billGetSummary.

The plan, interval, add-ons, seats, county slots, the current subscription and its renewal, what is scheduled for the period end (pending_change), the default payment method (brand, last four, expiry) and the 12 most recent invoices. Either credential (API key or session). The owner or a billing contact only (O63 S11, Q22): anyone else, an admin included, is answered 403 role_required (required: [owner, billing_contact]); whether service is paused reaches every member as organization.past_due on GET /v2/account. Prices and allowances in the response are read from the plan catalog; GET /v2/plans is canonical. While subscription.status is past_due, L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing (not billing): fix the card with the payment-method endpoints and pay with POST /v2/account/billing/retry.

Responses

200 success

The billing summary.

As application/json.

gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
contract.notesstring or null
DTG's notes on the contract.
planobjectalways present
The plan the organization holds now.
plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
addonsarray of stringalways present
Active add-ons.
seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
counties.purchasedintegeralways present
Paid county slots beyond included.
counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
subscription.idstring
Stripe subscription id (sub_...).
subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
subscription.current_period_startstring (date-time) or null
Start of the current billing period.
subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
pending_change.changes[].kind"plan"
Always plan.
pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
pending_change.changes[].addonsarray of string
The add-ons that will be removed.
payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
payment_method.idstring
Stripe PaymentMethod id (pm_...).
payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
payment_method.last4string
Last four digits of the card number.
payment_method.exp_monthinteger
Card expiry month. (1 to 12)
payment_method.exp_yearinteger
Card expiry year (four digits).
invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
invoices[].idstringalways present
Stripe invoice id (in_...).
invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
invoices[].total_centsintegeralways present
Invoice total in US cents.
invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
invoices[].createdstring (date-time)always present
When the invoice was created.
invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
invoices[].periodobjectalways present
The service period the invoice covers.
invoices[].period.startstring (date-time)always present
Period start.
invoices[].period.endstring (date-time)always present
Period end.
invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), not_found (404). Every problem is a problem document.

GET /v2/account/billing/invoices

The organization's recent invoices

Credentials: API key or App session. Operation id billListInvoices.

Up to the 12 most recent Stripe invoices, newest first (the same list as invoices in GET /v2/account/billing). Not paged. Either credential (API key or session). The owner or a billing contact only (O63 S11, Q22; 403 role_required otherwise).

Responses

200 success

The invoices.

As application/json.

dataarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first. Empty when the organization has never had a Stripe customer.
data[].idstringalways present
Stripe invoice id (in_...).
data[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
data[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
data[].total_centsintegeralways present
Invoice total in US cents.
data[].amount_due_centsintegeralways present
Amount still owed, in US cents.
data[].amount_paid_centsintegeralways present
Amount paid, in US cents.
data[].createdstring (date-time)always present
When the invoice was created.
data[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
data[].periodobjectalways present
The service period the invoice covers.
data[].period.startstring (date-time)always present
Period start.
data[].period.endstring (date-time)always present
Period end.
data[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
data[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
data[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
data[].linesarray of BillInvoiceLinealways present
The invoice's lines.
data[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
data[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
data[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
data[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), not_found (404). Every problem is a problem document.

POST /v2/account/billing/payment-method

Start adding a card (a SetupIntent for the Payment Element)

Credentials: API key or App session. Operation id billCreateSetupIntent.

Creates a Stripe SetupIntent for the organization (creating its Stripe customer on first use) and returns its client secret for Stripe's Payment Element, which collects the card in the browser (card data never reaches Taigan). Then call POST /v2/account/billing/payment-method/confirm. No request body. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Not refused for a contract-managed organization. T108: takes the organization's billing lock, as every billing write does (409 billing_in_progress after 15 s).

Responses

201 success

SetupIntent created.

As application/json.

setup_intent_idstringalways present
SetupIntent id (seti_...); send it to POST /v2/account/billing/payment-method/confirm once Stripe.js has confirmed it.
client_secretstringalways present
The SetupIntent's client secret, for the Payment Element. Treat as a secret; do not log it.
publishable_keystring or nullalways present
Stripe publishable key to initialise Stripe.js with.
gateway"fake" | "test" | "live"always present
live (Stripe live mode, production only), test (Stripe test mode) or fake (development simulation).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404). Every problem is a problem document.

POST /v2/account/billing/payment-method/confirm

Make the confirmed card the default payment method

Credentials: API key or App session. Operation id billConfirmPaymentMethod.

After the Payment Element has confirmed the SetupIntent, makes its card the organization's default payment method for every future charge. Writes the audit row billing.payment_method_set (brand and last four only). Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). T108: takes the organization's billing lock (409 billing_in_progress after 15 s); an unknown setup_intent_id is the same 404 as another organization's (it answered 500).

Request body

Required; application/json.

setup_intent_idstringrequired
The SetupIntent from POST /v2/account/billing/payment-method, after the Payment Element confirmed it.

Responses

200 success

The new default payment method.

As application/json.

payment_methodBillPaymentMethodalways present
The organization's default payment method: the card brand, last four digits and expiry only (card data never reaches Taigan; it is captured by Stripe's Payment Element). When the card details cannot be read only id is present.
payment_method.idstringalways present
Stripe PaymentMethod id (pm_...).
payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
payment_method.last4string
Last four digits of the card number.
payment_method.exp_monthinteger
Card expiry month. (1 to 12)
payment_method.exp_yearinteger
Card expiry year (four digits).

400 error

Bad request. Codes: bad_request (setup_intent_id is missing or not a string), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the SetupIntent does not belong to this organization), not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: setup_intent_incomplete (the SetupIntent has not succeeded yet; confirm it with the Payment Element first; the problem carries Stripe's status, e.g. requires_payment_method).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 16 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: bad_request (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), setup_intent_incomplete (409), body_too_large (413). Every problem is a problem document.

POST /v2/account/billing/subscribe

Create the organization's first subscription

Credentials: API key or App session. Operation id billSubscribe.

Subscribes the organization to a plan at an interval, optionally with extra seats, paid county slots and (annual only) the API add-on. Charges the default payment method, so one must be set first. Ends any running trial as converted (the trial county becomes an ordinary county). An annual term is non-refundable from the purchase; cancelling stops renewal and access runs to the paid-through date. Writes the audit row billing.subscribed. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Request body

Required; application/json.

plan_codestringrequired
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
intervalobject
Billing interval; default month. (default "month")
seatsinteger
Extra seats to buy beyond the plan's included seats. (default 0; 0 to 500)
countiesinteger
Paid county slots to buy beyond the plan's included counties; only on a plan that sells extra counties. (default 0; 0 to 3194)
addonsarray of "api"
Add-ons to buy with the plan: only api, and only with interval: year.

Responses

201 success

Subscription created (check status: incomplete means the first payment did not succeed).

As application/json.

subscription_idstringalways present
Stripe subscription id (sub_...).
statusstringalways present
Stripe's status for the new subscription: active (or trialing) when the first payment succeeded; incomplete when it did not (no entitlement until it is paid).
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: annual_plan_required (the API add-on was requested with a non-annual interval, D48), bad_request (plan_code missing, unknown or not purchasable; interval not month/year; seats not an integer 0 to 500; counties not an integer 0 to 3194, or extra counties on a plan that sells none; an add-on other than api; a field of the wrong type), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

402 error

Payment required. Codes: payment_method_required (add a payment method first: POST /v2/account/billing/payment-method).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: already_subscribed (the organization already has a subscription; use POST /v2/account/billing/change), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 16 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: annual_plan_required (400), bad_request (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), payment_method_required (402), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), already_subscribed (409), billing_in_progress (409), body_too_large (413). Every problem is a problem document.

POST /v2/account/billing/preview

Price a change before making it

Credentials: API key or App session. Operation id billPreviewChange.

Classifies and prices a change to the subscription without making it: what is charged now (prorated, always_invoice), the next renewal invoice, what is scheduled now and what the change would leave scheduled, and whether the change needs a surviving-county choice. Everything is computed on the period-end state: every quantity the request names as requested, every other one as already scheduled. Adding the API add-on restarts the whole subscription's term today: term_restart is true and credit_cents and new_renewal_date are set. surviving_fips is ignored here. Takes no lock and changes nothing. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact).

Request body

Required; application/json.

plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
seatsnumber
The purchased (extra) seat quantity wanted, beyond the plan's included seats. The whole target, not a delta.
countiesnumber
The paid county-slot quantity wanted, beyond the plan's included counties. The whole target, not a delta.
addonsarray of string
The complete set of add-ons wanted ([] removes the API add-on at period end; ["api"] adds it, annual plans only, restarting the subscription's term, D49).
surviving_fipsarray of string
Only on POST /v2/account/billing/change: when the change leaves fewer county places than the organization's active counties (counties_requiring_choice in the preview), the counties to keep. Exactly capacity codes, each one of the preview's candidates. A choice already made stands while it still fits the period-end capacity. Ignored by the preview.

Responses

200 success

The preview.

As application/json.

currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
current.addonsarray of stringalways present
Add-ons.
current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
target.addonsarray of stringalways present
Add-ons.
target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
next_invoice.linesarray of BillAmountLinealways present
Its lines.
next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
unit_prices_cents.planintegeralways present
The plan price.
unit_prices_cents.seatintegeralways present
One extra seat.
unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
scheduled[].kind"plan"
Always plan.
scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
scheduled[].addonsarray of string
The add-ons that will be removed.
scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
scheduled_after[].kind"plan"
Always plan.
scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
scheduled_after[].addonsarray of string
The add-ons that will be removed.
replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaces.plan.kind"plan"always present
Always plan.
replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaces.counties.kind"counties"always present
Always counties.
replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaces.seats.kind"seats"always present
Always seats.
replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.

400 error

Bad request. Codes: annual_plan_required (the state the change produces would hold the API add-on on a non-annual interval: adding it off-annual, or keeping it through a move to monthly; for a deferred change the period-end state is checked, so a move to monthly is allowed when the add-on's removal is scheduled), bad_request (unknown or non-purchasable plan_code; interval not month/year; a field of the wrong type), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 16 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: annual_plan_required (400), bad_request (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), body_too_large (413). Every problem is a problem document.

POST /v2/account/billing/change

Change the plan, interval, seats, county slots or add-ons

Credentials: API key or App session. Operation id billApplyChange.

Applies a change. Increases (a higher plan, month to year, the add-on added, more seats or county slots) take effect now, prorated to the rest of the period and charged to the card at once (always_invoice); a declined card still grants them, except the API add-on. Decreases (a lower plan, year to month, add-on removal, fewer seats or slots) are scheduled for period end and are not credited; what was paid for stays usable until then. A mixed request applies its increases now at the current plan and interval and schedules the rest. The request touches only the quantities it names; a second change to the same quantity replaces the first (replaced); naming one at its current value withdraws its scheduled change. Adding the API add-on restarts the whole subscription's term with Stripe's pending-if-incomplete behaviour: a declined card leaves the add-on ungranted. When a scheduled add-on removal takes effect, the organization's live API keys are revoked; sandbox keys stay. When the period-end state holds fewer counties than are active, the request must carry surviving_fips (see the preview's counties_requiring_choice); at period end the counties not kept leave the active set, and members beyond the seat count become free members. Writes the audit row billing.changed. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Request body

Required; application/json.

plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
seatsnumber
The purchased (extra) seat quantity wanted, beyond the plan's included seats. The whole target, not a delta.
countiesnumber
The paid county-slot quantity wanted, beyond the plan's included counties. The whole target, not a delta.
addonsarray of string
The complete set of add-ons wanted ([] removes the API add-on at period end; ["api"] adds it, annual plans only, restarting the subscription's term, D49).
surviving_fipsarray of string
Only on POST /v2/account/billing/change: when the change leaves fewer county places than the organization's active counties (counties_requiring_choice in the preview), the counties to keep. Exactly capacity codes, each one of the preview's candidates. A choice already made stands while it still fits the period-end capacity. Ignored by the preview.

Responses

200 success

The change applied or scheduled, with the preview it was decided on and the new summary.

As application/json.

applied"immediately" | "period_end"always present
immediately when an increase was applied now (and charged), else period_end (the change, if any, is scheduled; also returned for a no-op).
replacedBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaced.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaced.plan.kind"plan"always present
Always plan.
replaced.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaced.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaced.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaced.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaced.counties.kind"counties"always present
Always counties.
replaced.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaced.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaced.seats.kind"seats"always present
Always seats.
replaced.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaced.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaced.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaced.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaced.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
previewobjectalways present
The preview the change was decided on.
preview.currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
preview.current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.current.addonsarray of stringalways present
Add-ons.
preview.current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
preview.target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.target.addonsarray of stringalways present
Add-ons.
preview.target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
preview.effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
preview.effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
preview.proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
preview.immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
preview.proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
preview.proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
preview.credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
preview.new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
preview.next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
preview.next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
preview.next_invoice.linesarray of BillAmountLinealways present
Its lines.
preview.next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
preview.unit_prices_cents.planintegeralways present
The plan price.
preview.unit_prices_cents.seatintegeralways present
One extra seat.
preview.unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
preview.unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
preview.counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
preview.counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
preview.counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
preview.counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
preview.counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
preview.counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
preview.counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
preview.county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
preview.seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
preview.scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
preview.scheduled[].kind"plan"
Always plan.
preview.scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled[].addonsarray of string
The add-ons that will be removed.
preview.scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
preview.scheduled_after[].kind"plan"
Always plan.
preview.scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled_after[].addonsarray of string
The add-ons that will be removed.
preview.replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
preview.replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
preview.replaces.plan.kind"plan"always present
Always plan.
preview.replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
preview.replaces.counties.kind"counties"always present
Always counties.
preview.replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
preview.replaces.seats.kind"seats"always present
Always seats.
preview.replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
preview.replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
preview.replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
preview.replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: annual_plan_required (as on the preview), bad_request (unknown or non-purchasable plan_code; interval not month/year; a field of the wrong type; or the surviving-county choice is missing or invalid: then the code is surviving_counties_required, with capacity and candidates, the FIPS codes to choose from, and errors[0] repeats it), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 16 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: annual_plan_required (400), bad_request (400), surviving_counties_required (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409), body_too_large (413). Every problem is a problem document.

DELETE /v2/account/billing/pending/{kind}

Withdraw one scheduled period-end change

Credentials: API key or App session. Operation id billCancelPendingChange.

Withdraws the scheduled change for one quantity. The other scheduled quantities, and a scheduled cancellation (which POST /v2/account/billing/resume withdraws), stay. Writes the audit row billing.pending_cancelled. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Parameters

kindpath · "plan" | "counties" | "seats" | "addon_removal"required
Which scheduled change to withdraw: plan, counties (a slot release), seats or addon_removal.

Responses

200 success

The withdrawn item and the new summary.

As application/json.

cancelledobjectalways present
The scheduled item that was withdrawn.
cancelled.kind"plan"
Always plan.
cancelled.plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
cancelled.interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
cancelled.effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
cancelled.counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
cancelled.seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
cancelled.addonsarray of string
The add-ons that will be removed.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (kind is not one of plan, counties, seats, addon_removal), not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: nothing_scheduled (nothing is scheduled for that quantity; the problem carries kind), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), nothing_scheduled (409), billing_in_progress (409). Every problem is a problem document.

POST /v2/account/billing/cancel

Cancel the subscription at period end

Credentials: API key or App session. Operation id billCancelAtPeriodEnd.

Sets the subscription to end at the current period end instead of renewing; the organization keeps everything until then and then drops to Free. Nothing is credited. Undo with POST /v2/account/billing/resume. No request body. Writes the audit row billing.cancelled. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Responses

200 success

The billing summary after the change (subscription.cancel_at_period_end true, pending_change.cancel true).

As application/json.

gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
contract.notesstring or null
DTG's notes on the contract.
planobjectalways present
The plan the organization holds now.
plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
addonsarray of stringalways present
Active add-ons.
seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
counties.purchasedintegeralways present
Paid county slots beyond included.
counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
subscription.idstring
Stripe subscription id (sub_...).
subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
subscription.current_period_startstring (date-time) or null
Start of the current billing period.
subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
pending_change.changes[].kind"plan"
Always plan.
pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
pending_change.changes[].addonsarray of string
The add-ons that will be removed.
payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
payment_method.idstring
Stripe PaymentMethod id (pm_...).
payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
payment_method.last4string
Last four digits of the card number.
payment_method.exp_monthinteger
Card expiry month. (1 to 12)
payment_method.exp_yearinteger
Card expiry year (four digits).
invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
invoices[].idstringalways present
Stripe invoice id (in_...).
invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
invoices[].total_centsintegeralways present
Invoice total in US cents.
invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
invoices[].createdstring (date-time)always present
When the invoice was created.
invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
invoices[].periodobjectalways present
The service period the invoice covers.
invoices[].period.startstring (date-time)always present
Period start.
invoices[].period.endstring (date-time)always present
Period end.
invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409). Every problem is a problem document.

POST /v2/account/billing/resume

Withdraw a scheduled cancellation

Credentials: API key or App session. Operation id billResume.

Ends a scheduled cancellation so the subscription renews. Touches no other scheduled change or its date. No request body. Writes the audit row billing.resumed. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Responses

200 success

The billing summary after the change.

As application/json.

gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
contract.notesstring or null
DTG's notes on the contract.
planobjectalways present
The plan the organization holds now.
plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
addonsarray of stringalways present
Active add-ons.
seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
counties.purchasedintegeralways present
Paid county slots beyond included.
counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
subscription.idstring
Stripe subscription id (sub_...).
subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
subscription.current_period_startstring (date-time) or null
Start of the current billing period.
subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
pending_change.changes[].kind"plan"
Always plan.
pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
pending_change.changes[].addonsarray of string
The add-ons that will be removed.
payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
payment_method.idstring
Stripe PaymentMethod id (pm_...).
payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
payment_method.last4string
Last four digits of the card number.
payment_method.exp_monthinteger
Card expiry month. (1 to 12)
payment_method.exp_yearinteger
Card expiry year (four digits).
invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
invoices[].idstringalways present
Stripe invoice id (in_...).
invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
invoices[].total_centsintegeralways present
Invoice total in US cents.
invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
invoices[].createdstring (date-time)always present
When the invoice was created.
invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
invoices[].periodobjectalways present
The service period the invoice covers.
invoices[].period.startstring (date-time)always present
Period start.
invoices[].period.endstring (date-time)always present
Period end.
invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409). Every problem is a problem document.

POST /v2/account/billing/retry

Pay the open invoice now

Credentials: API key or App session. Operation id billRetryInvoice.

Pays the latest open, card-charged invoice of the current subscription against the default payment method now, instead of waiting for Stripe's retry schedule. A success brings the subscription out of past_due in this response, which lifts L18's pause at once. A decline is a 200 with paid: false and the subscription still past_due. No request body. Writes the audit row billing.retried (invoice, paid, amount due). Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Responses

200 success

The payment attempt's outcome.

As application/json.

paidbooleanalways present
True when the invoice is now paid. A decline is not an error: paid is false and the subscription stays past_due.
invoiceBillInvoicealways present
A Stripe invoice for the organization.
invoice.idstringalways present
Stripe invoice id (in_...).
invoice.numberstring or nullalways present
The invoice number printed on it; null while a draft.
invoice.status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
invoice.total_centsintegeralways present
Invoice total in US cents.
invoice.amount_due_centsintegeralways present
Amount still owed, in US cents.
invoice.amount_paid_centsintegeralways present
Amount paid, in US cents.
invoice.createdstring (date-time)always present
When the invoice was created.
invoice.due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
invoice.periodobjectalways present
The service period the invoice covers.
invoice.period.startstring (date-time)always present
Period start.
invoice.period.endstring (date-time)always present
Period end.
invoice.hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
invoice.collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
invoice.descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
invoice.linesarray of BillInvoiceLinealways present
The invoice's lines.
invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
invoice.lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), no_open_invoice (nothing is owed right now), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), no_open_invoice (409), billing_in_progress (409). Every problem is a problem document.

POST /v2/account/seats

Set the purchased seat quantity

Credentials: API key or App session. Operation id billSetSeats.

Sets the number of extra seats bought beyond the plan's included seats (the whole target, not a delta). The same as POST /v2/account/billing/change {seats}: an increase applies now, prorated to the rest of the period and charged at once (always_invoice); a decrease is scheduled for period end, not credited, and the seats stay usable until then, when members beyond the seat count become free members. Price it first with POST /v2/account/billing/preview {seats}. Writes no audit row of its own. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Request body

Required; application/json.

quantityintegerrequired
Extra seats wanted, 0 to 500. (0 to 500)

Responses

200 success

The change applied or scheduled.

As application/json.

applied"immediately" | "period_end"always present
immediately when an increase was applied now (and charged), else period_end (the change, if any, is scheduled; also returned for a no-op).
replacedBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaced.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaced.plan.kind"plan"always present
Always plan.
replaced.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaced.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaced.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaced.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaced.counties.kind"counties"always present
Always counties.
replaced.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaced.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaced.seats.kind"seats"always present
Always seats.
replaced.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaced.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaced.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaced.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaced.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
previewobjectalways present
The preview the change was decided on.
preview.currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
preview.current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.current.addonsarray of stringalways present
Add-ons.
preview.current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
preview.target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.target.addonsarray of stringalways present
Add-ons.
preview.target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
preview.effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
preview.effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
preview.proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
preview.immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
preview.proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
preview.proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
preview.credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
preview.new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
preview.next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
preview.next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
preview.next_invoice.linesarray of BillAmountLinealways present
Its lines.
preview.next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
preview.unit_prices_cents.planintegeralways present
The plan price.
preview.unit_prices_cents.seatintegeralways present
One extra seat.
preview.unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
preview.unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
preview.counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
preview.counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
preview.counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
preview.counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
preview.counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
preview.counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
preview.counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
preview.county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
preview.seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
preview.scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
preview.scheduled[].kind"plan"
Always plan.
preview.scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled[].addonsarray of string
The add-ons that will be removed.
preview.scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
preview.scheduled_after[].kind"plan"
Always plan.
preview.scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled_after[].addonsarray of string
The add-ons that will be removed.
preview.replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
preview.replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
preview.replaces.plan.kind"plan"always present
Always plan.
preview.replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
preview.replaces.counties.kind"counties"always present
Always counties.
preview.replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
preview.replaces.seats.kind"seats"always present
Always seats.
preview.replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
preview.replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
preview.replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
preview.replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: bad_request (quantity missing, not a number, or not an integer 0 to 500), surviving_counties_required (a county choice is owed; capacity, candidates; errors repeats it), annual_plan_required (only when the period-end state would re-price the API add-on onto a non-annual interval), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 4 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: bad_request (400), surviving_counties_required (400), annual_plan_required (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409), body_too_large (413). Every problem is a problem document.

POST /v2/account/county-slots

Set the paid county-slot quantity

Credentials: API key or App session. Operation id billSetCountySlots.

Sets the number of paid county slots beyond the plan's included counties (D44; the whole target, not a delta). The same as POST /v2/account/billing/change {counties}: an increase applies now, prorated and charged at once (always_invoice); a decrease is scheduled for period end, not credited, and the slots stay usable until then. The county SET is managed at /v2/account/counties (which answers confirm_purchase_required when adding a county needs a slot bought); this is the billing quantity behind it. A decrease below the active counties needs a surviving-county choice, which this endpoint cannot carry: use POST /v2/account/billing/change {counties, surviving_fips}. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Request body

Required; application/json.

quantityintegerrequired
Paid county slots wanted, 0 to 3194. (0 to 3194)

Responses

200 success

The change applied or scheduled.

As application/json.

applied"immediately" | "period_end"always present
immediately when an increase was applied now (and charged), else period_end (the change, if any, is scheduled; also returned for a no-op).
replacedBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaced.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaced.plan.kind"plan"always present
Always plan.
replaced.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaced.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaced.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaced.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaced.counties.kind"counties"always present
Always counties.
replaced.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaced.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaced.seats.kind"seats"always present
Always seats.
replaced.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaced.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaced.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaced.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaced.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
previewobjectalways present
The preview the change was decided on.
preview.currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
preview.current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.current.addonsarray of stringalways present
Add-ons.
preview.current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
preview.target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.target.addonsarray of stringalways present
Add-ons.
preview.target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
preview.effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
preview.effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
preview.proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
preview.immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
preview.proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
preview.proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
preview.credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
preview.new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
preview.next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
preview.next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
preview.next_invoice.linesarray of BillAmountLinealways present
Its lines.
preview.next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
preview.unit_prices_cents.planintegeralways present
The plan price.
preview.unit_prices_cents.seatintegeralways present
One extra seat.
preview.unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
preview.unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
preview.counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
preview.counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
preview.counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
preview.counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
preview.counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
preview.counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
preview.counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
preview.county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
preview.seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
preview.scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
preview.scheduled[].kind"plan"
Always plan.
preview.scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled[].addonsarray of string
The add-ons that will be removed.
preview.scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
preview.scheduled_after[].kind"plan"
Always plan.
preview.scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled_after[].addonsarray of string
The add-ons that will be removed.
preview.replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
preview.replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
preview.replaces.plan.kind"plan"always present
Always plan.
preview.replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
preview.replaces.counties.kind"counties"always present
Always counties.
preview.replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
preview.replaces.seats.kind"seats"always present
Always seats.
preview.replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
preview.replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
preview.replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
preview.replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: bad_request (quantity missing, not a number, or not an integer 0 to 3194), surviving_counties_required (capacity, candidates; errors repeats it) when the decrease leaves fewer places than active counties and no earlier choice fits), annual_plan_required (only when the period-end state would re-price the API add-on onto a non-annual interval), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 4 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: bad_request (400), surviving_counties_required (400), annual_plan_required (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409), body_too_large (413). Every problem is a problem document.

POST /v2/account/addons

Buy the API add-on

Credentials: API key or App session. Operation id billAddAddon.

Adds the API add-on (live API keys) to the subscription. Sold only with an annual plan. Adding it mid-term restarts the whole subscription's term today: the new term is charged now and every item moves to the new renewal date. A declined card leaves the add-on ungranted (unlike other increases); check summary.addons. Price it first with POST /v2/account/billing/preview {addons: ["api"]}. Already holding it is a no-op. Writes no audit row of its own. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Request body

Required; application/json.

addon"api"required
The add-on to buy: only api.

Responses

200 success

The change applied.

As application/json.

applied"immediately" | "period_end"always present
immediately when an increase was applied now (and charged), else period_end (the change, if any, is scheduled; also returned for a no-op).
replacedBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaced.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaced.plan.kind"plan"always present
Always plan.
replaced.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaced.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaced.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaced.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaced.counties.kind"counties"always present
Always counties.
replaced.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaced.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaced.seats.kind"seats"always present
Always seats.
replaced.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaced.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaced.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaced.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaced.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
previewobjectalways present
The preview the change was decided on.
preview.currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
preview.current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.current.addonsarray of stringalways present
Add-ons.
preview.current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
preview.target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.target.addonsarray of stringalways present
Add-ons.
preview.target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
preview.effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
preview.effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
preview.proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
preview.immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
preview.proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
preview.proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
preview.credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
preview.new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
preview.next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
preview.next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
preview.next_invoice.linesarray of BillAmountLinealways present
Its lines.
preview.next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
preview.unit_prices_cents.planintegeralways present
The plan price.
preview.unit_prices_cents.seatintegeralways present
One extra seat.
preview.unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
preview.unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
preview.counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
preview.counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
preview.counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
preview.counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
preview.counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
preview.counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
preview.counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
preview.county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
preview.seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
preview.scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
preview.scheduled[].kind"plan"
Always plan.
preview.scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled[].addonsarray of string
The add-ons that will be removed.
preview.scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
preview.scheduled_after[].kind"plan"
Always plan.
preview.scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled_after[].addonsarray of string
The add-ons that will be removed.
preview.replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
preview.replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
preview.replaces.plan.kind"plan"always present
Always plan.
preview.replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
preview.replaces.counties.kind"counties"always present
Always counties.
preview.replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
preview.replaces.seats.kind"seats"always present
Always seats.
preview.replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
preview.replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
preview.replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
preview.replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: annual_plan_required (the plan is not annual), bad_request (addon is not api), malformed_json (the body is not valid JSON).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

413 error

Payload too large. Codes: body_too_large (the JSON body is over 4 KB; the problem carries limit_bytes).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: annual_plan_required (400), bad_request (400), malformed_json (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409), body_too_large (413). Every problem is a problem document.

DELETE /v2/account/addons/{addon}

Remove the API add-on at period end

Credentials: API key or App session. Operation id billRemoveAddon.

Schedules the API add-on's removal for the period end (never restarts the term, not credited; withdraw it with DELETE /v2/account/billing/pending/addon_removal). When the removal takes effect the organization's LIVE API keys are revoked; sandbox keys stay. Not holding it is a no-op. Writes no audit row of its own. Either credential (API key or session). Only the organization's owner or a member flagged as billing contact (an admin only when also a billing contact). Billing changes for one organization are serialized: a second one waits for the first and, after 15 seconds, answers 409 billing_in_progress.

Parameters

addonpath · "api"required
The add-on to remove: only api.

Responses

200 success

The removal scheduled.

As application/json.

applied"immediately" | "period_end"always present
immediately when an increase was applied now (and charged), else period_end (the change, if any, is scheduled; also returned for a no-op).
replacedBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
replaced.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
replaced.plan.kind"plan"always present
Always plan.
replaced.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
replaced.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
replaced.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
replaced.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
replaced.counties.kind"counties"always present
Always counties.
replaced.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
replaced.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
replaced.seats.kind"seats"always present
Always seats.
replaced.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
replaced.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
replaced.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
replaced.addon_removal.kind"addon_removal"always present
Always addon_removal.
replaced.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
replaced.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
previewobjectalways present
The preview the change was decided on.
preview.currentBillStateSnapshotalways present
A billing state: plan, interval, add-ons and purchased quantities.
preview.current.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.current.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.current.addonsarray of stringalways present
Add-ons.
preview.current.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.current.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.targetobjectalways present
The state the request asks for (unnamed quantities at their current values).
preview.target.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.target.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.target.addonsarray of stringalways present
Add-ons.
preview.target.seats_purchasednumberalways present
Purchased seats beyond the plan's included seats.
preview.target.counties_purchasednumberalways present
Paid county slots beyond the plan's included counties.
preview.kind"upgrade" | "downgrade" | "mixed" | "none"always present
upgrade (only increases: applied now), downgrade (only decreases: scheduled for period end), mixed (both: the increases now at the current plan and interval, the decreases scheduled), none (no change).
preview.effective"immediately" | "period_end"always present
immediately when anything applies now (upgrade or mixed), else period_end (also for none).
preview.effective_atstring (date-time) or nullalways present
Now for an immediate change, else the current period end.
preview.proration_behavior"always_invoice" | "none"always present
always_invoice when the change applies now: the prorated amount is invoiced and charged to the card at once. none for a period-end change: nothing is charged now and nothing is credited.
preview.immediate_charge_centsintegeralways present
What the card is charged now, in US cents (the sum of the proration lines, never below 0); 0 for a period-end change. (at least 0)
preview.proration_linesarray of BillAmountLinealways present
The prorated lines charged now. When the API add-on is being added (term restart) these are every line of the restarted term.
preview.proration_lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.proration_lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.proration_lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.term_restartbooleanalways present
True when the change adds the API add-on: the WHOLE subscription restarts its term today, every item moving to the new anchor together; the new term is charged now.
preview.credit_centsinteger or nullalways present
Only when term_restart is true: the magnitude, in US cents, of any credit lines Stripe returns for unused time (commonly 0, because Stripe nets a continuing item into one line). Null otherwise.
preview.new_renewal_datestring (date-time) or nullalways present
Only when term_restart is true: the renewal date after the restart. Null otherwise.
preview.next_invoiceobjectalways present
The next renewal invoice, priced on the period-end state (what this change asks for plus what is already scheduled). Empty (total_cents 0, no lines) on a term restart, where everything is due now.
preview.next_invoice.total_centsintegeralways present
Total of the next invoice in US cents.
preview.next_invoice.linesarray of BillAmountLinealways present
Its lines.
preview.next_invoice.lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
preview.next_invoice.lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
preview.next_invoice.lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
preview.unit_prices_centsobjectalways present
Unit prices, in US cents per interval, for the target plan and interval, from the price catalog; 0 where the catalog holds no such price.
preview.unit_prices_cents.planintegeralways present
The plan price.
preview.unit_prices_cents.seatintegeralways present
One extra seat.
preview.unit_prices_cents.countyintegeralways present
One extra county slot; 0 when the plan sells none.
preview.unit_prices_cents.api_addonintegeralways present
The API add-on (0 on a monthly interval: it is sold annual only).
preview.counties_requiring_choiceobject or nullalways present
Set when the period-end county capacity is below the organization's active counties (counties already scheduled to leave are not counted): the change must then carry surviving_fips. Null otherwise.
preview.counties_requiring_choice.capacityintegeralways present
How many counties the period-end state holds (included plus paid slots).
preview.counties_requiring_choice.candidatesarray of BillCountyCandidatealways present
The active counties to choose from, in KEEP order: the first capacity are the default choice.
preview.counties_requiring_choice.candidates[].fipsstringalways present
Five-digit county FIPS code.
preview.counties_requiring_choice.candidates[].source"manual" | "state" | "msa"always present
How the county entered the active set: manual (picked), state or msa (added as part of a state or metro).
preview.counties_requiring_choice.candidates[].added_atstring (date-time)always present
When it was added.
preview.counties_requiring_choice.candidates[].last_usedstring (date-time) or nullalways present
The organization's last data request touching this county in the past 90 days; null when none.
preview.county_slots_releasableintegeralways present
How many paid county slots the period-end state holds that the active set does not need (for example after a move to a plan with more included counties), so the customer could release them.
preview.seats_becoming_free_membersintegeralways present
How many seated members exceed the period-end seat count and would become free members.
preview.scheduledarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What is scheduled now, before this change.
preview.scheduled[].kind"plan"
Always plan.
preview.scheduled[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled[].addonsarray of string
The add-ons that will be removed.
preview.scheduled_afterarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemovalalways present
What this change would leave scheduled (in a mixed change, the plan move appears here).
preview.scheduled_after[].kind"plan"
Always plan.
preview.scheduled_after[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.scheduled_after[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.scheduled_after[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.scheduled_after[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.scheduled_after[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.scheduled_after[].addonsarray of string
The add-ons that will be removed.
preview.replacesBillPendingReplacedalways present
For each scheduled item a change would replace (a second change to the same quantity), the item it replaces, keyed by its kind (plan, counties, seats, addon_removal). An empty object when it replaces nothing.
preview.replaces.planBillPendingItemPlan
A scheduled plan or interval move, applied at period end.
preview.replaces.plan.kind"plan"always present
Always plan.
preview.replaces.plan.plan_codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
preview.replaces.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
preview.replaces.plan.effective_atstring (date-time) or nullalways present
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
preview.replaces.countiesBillPendingItemCounties
A scheduled decrease of the paid county-slot quantity (a slot release), applied at period end, not credited; the slots stay usable until then.
preview.replaces.counties.kind"counties"always present
Always counties.
preview.replaces.counties.counties_purchasedintegeralways present
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
preview.replaces.counties.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.seatsBillPendingItemSeats
A scheduled decrease of purchased seats, applied at period end, not credited; the seats stay usable until then.
preview.replaces.seats.kind"seats"always present
Always seats.
preview.replaces.seats.seats_purchasedintegeralways present
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
preview.replaces.seats.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
preview.replaces.addon_removalBillPendingItemAddonRemoval
A scheduled add-on removal, applied at period end. When the API add-on leaves, the organization's live API keys are revoked at that moment; sandbox keys stay.
preview.replaces.addon_removal.kind"addon_removal"always present
Always addon_removal.
preview.replaces.addon_removal.addonsarray of stringalways present
The add-ons that will be removed.
preview.replaces.addon_removal.effective_atstring (date-time) or nullalways present
When the change takes effect (the end of the current period). Same date for every scheduled item.
summaryBillSummaryalways present
The organization's billing state as Kelpie's seats-and-billing screen shows it.
summary.gateway"fake" | "test" | "live"always present
Which payment gateway this server runs: live (Stripe live mode, production only), test (Stripe test mode) or fake (an in-process simulation used in development and tests). T153: the Stripe secret key's prefix decides between test and live.
summary.publishable_keystring or nullalways present
The Stripe publishable key to initialise Stripe.js and the Payment Element with.
summary.billing_mode"self_serve" | "invoiced"always present
self_serve (card subscription managed through these endpoints) or invoiced (a contract managed by Data Tactical Group: every self-serve change answers 403 contract_managed).
summary.contractobject or nullalways present
The contract terms for an invoiced organization; null for self_serve.
summary.contract.expires_atstring (date-time) or null
When the contract ends; null for no end date.
summary.contract.notesstring or null
DTG's notes on the contract.
summary.planobjectalways present
The plan the organization holds now.
summary.plan.codestringalways present
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.plan.namestringalways present
The plan's display name (e.g. Local, Regional, National, Free).
summary.plan.interval"month" | "year"always present
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.addonsarray of stringalways present
Active add-ons.
summary.seatsobjectalways present
Seats: the plan's included seats plus purchased extra seats.
summary.seats.includedintegeralways present
Seats the plan includes (the plan's allowance; see GET /v2/plans), raised to grandfathered while that is set.
summary.seats.grandfatheredinteger or null
T163: an organization that had more seated members than its plan's new included count when Regional fell to 10 seats and National to 15 keeps that many included seats until its seated members fall to the plan's count or its plan changes. This is that count; null for every other organization.
summary.seats.purchasedintegeralways present
Extra seats the organization holds beyond included. A scheduled decrease does not lower this until period end.
summary.seats.billed_quantityintegeralways present
The seat quantity on the Stripe subscription (for an invoiced organization, the contracted extra seats; 0 with no subscription). Can differ from purchased briefly while a scheduled decrease has been sent to Stripe ahead of the renewal.
summary.seats.seat_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra seat, in US dollars; null when the plan sells no extra seats.
summary.seats.proration"always_invoice"always present
How a seat increase is billed: always always_invoice (prorated to the rest of the period and charged to the card at purchase).
summary.seats.proration_notestringalways present
A sentence stating the seat billing rule for display.
summary.countiesobjectalways present
County slots: the plan's included counties plus paid county slots. The county SET is managed at /v2/account/counties; this is the billing quantity behind it.
summary.counties.includedintegeralways present
Counties the plan includes; -1 means every county (National).
summary.counties.purchasedintegeralways present
Paid county slots beyond included.
summary.counties.billed_quantityintegeralways present
The county-slot quantity on the Stripe subscription (for an invoiced organization, the contracted slots; 0 with no subscription).
summary.counties.activeintegeralways present
Counties currently in the organization's active set, not counting a trial county.
summary.counties.county_price_usd_monthnumber or nullalways present
The plan's monthly price of one extra county slot, in US dollars; null when the plan sells no extra counties.
summary.counties.proration"always_invoice"always present
How a slot increase is billed: always always_invoice (prorated and charged at purchase).
summary.counties.proration_notestringalways present
A sentence stating the county-slot billing rule for display.
summary.counties.anchor_dayinteger or nullalways present
Day of the month of the organization's change window (the subscription's anchor date), on which county set changes land; null before a first subscription. (1 to 31)
summary.subscriptionobject or nullalways present
The current Stripe subscription (status active, trialing, past_due or incomplete); null when there is none (Free, or contract-managed without one).
summary.subscription.idstring
Stripe subscription id (sub_...).
summary.subscription.status"active" | "trialing" | "past_due" | "incomplete"
active; trialing; past_due (a renewal was declined: L18 pauses county detail, CSV/XLSX export, live API keys and cluster editing at once, while the plan and its capacity stay held; pay with POST /v2/account/billing/retry after fixing the card); incomplete (the first payment has not succeeded).
summary.subscription.current_period_startstring (date-time) or null
Start of the current billing period.
summary.subscription.current_period_endstring (date-time) or null
End of the current billing period: where scheduled changes and a cancellation take effect.
summary.subscription.renewal_datestring (date-time) or null
When the subscription renews (the period end); null when it is set to cancel at period end.
summary.subscription.cancel_at_period_endboolean
True when the subscription ends at current_period_end instead of renewing.
summary.subscription.past_due_sincestring (date-time) or null
When the subscription first became past due; null when it is not past due.
summary.subscription.dunning_grace_daysinteger
Days a past-due subscription has before it is cancelled and the organization drops to Free (the downgrade composite applies). Service is paused from the decline, not from the end of this window.
summary.pending_changeBillPendingChange or nullalways present
What is scheduled for the period end; null when nothing (and no cancellation) is scheduled.
summary.pending_change.plan_codestring or null
The plan the organization moves to at period end; null when no plan move is scheduled (an interval-only move leaves this null and sets interval).
summary.pending_change.interval"month" | "year" | null
The interval the organization moves to at period end; null when no interval move is scheduled.
summary.pending_change.seats_purchasedinteger or null
The purchased seat quantity from period end; null when no seat decrease is scheduled.
summary.pending_change.counties_purchasedinteger or null
The paid county-slot quantity from period end; null when no slot release is scheduled.
summary.pending_change.remove_addonsarray of string
Add-ons removed at period end; empty when none.
summary.pending_change.cancelboolean
True when the subscription is set to cancel at period end (POST /v2/account/billing/cancel); POST /v2/account/billing/resume clears it and nothing else.
summary.pending_change.effective_atstring (date-time)
The period end at which everything here takes effect.
summary.pending_change.changesarray of BillPendingItemPlan or BillPendingItemCounties or BillPendingItemSeats or BillPendingItemAddonRemoval
The scheduled set, one item per quantity. A cancellation is not an item here (see cancel).
summary.pending_change.changes[].kind"plan"
Always plan.
summary.pending_change.changes[].plan_codestring
A plan code as GET /v2/plans lists it (starter is Local, pro is Regional, national is National; free is the unpaid tier and is never purchasable). The plans, their allowances and prices are in GET /v2/plans.
summary.pending_change.changes[].interval"month" | "year"
Billing interval: month (monthly) or year (annual). The API add-on is sold only with year.
summary.pending_change.changes[].effective_atstring (date-time) or null
When the change takes effect: the end of the current subscription period. Every scheduled item shares this date. Null only in a preview's scheduled_after when nothing would be left scheduled.
summary.pending_change.changes[].counties_purchasedinteger
The paid county-slot quantity the organization will hold from effective_at (slots beyond the plan's included counties). (at least 0)
summary.pending_change.changes[].seats_purchasedinteger
The purchased (extra) seat quantity the organization will hold from effective_at, beyond the plan's included seats. (at least 0)
summary.pending_change.changes[].addonsarray of string
The add-ons that will be removed.
summary.payment_methodBillPaymentMethod or nullalways present
The default payment method; null when none is set.
summary.payment_method.idstring
Stripe PaymentMethod id (pm_...).
summary.payment_method.brandstring
Card brand as Stripe reports it, e.g. visa, mastercard.
summary.payment_method.last4string
Last four digits of the card number.
summary.payment_method.exp_monthinteger
Card expiry month. (1 to 12)
summary.payment_method.exp_yearinteger
Card expiry year (four digits).
summary.invoicesarray of BillInvoicealways present
Up to the 12 most recent invoices, newest first.
summary.invoices[].idstringalways present
Stripe invoice id (in_...).
summary.invoices[].numberstring or nullalways present
The invoice number printed on it; null while a draft.
summary.invoices[].status"draft" | "open" | "paid" | "void" | "uncollectible"always present
open is unpaid and collectable (a declined renewal stays open while the subscription is past_due; POST /v2/account/billing/retry pays it); paid; void; uncollectible; draft not yet finalized.
summary.invoices[].total_centsintegeralways present
Invoice total in US cents.
summary.invoices[].amount_due_centsintegeralways present
Amount still owed, in US cents.
summary.invoices[].amount_paid_centsintegeralways present
Amount paid, in US cents.
summary.invoices[].createdstring (date-time)always present
When the invoice was created.
summary.invoices[].due_datestring (date-time) or nullalways present
Due date for a send_invoice (contract) invoice; null for card-charged invoices.
summary.invoices[].periodobjectalways present
The service period the invoice covers.
summary.invoices[].period.startstring (date-time)always present
Period start.
summary.invoices[].period.endstring (date-time)always present
Period end.
summary.invoices[].hosted_invoice_urlstring (uri) or nullalways present
Stripe's hosted page for viewing and paying the invoice; null when Stripe has none.
summary.invoices[].collection_method"charge_automatically" | "send_invoice"always present
charge_automatically (charged to the card on file: self-serve) or send_invoice (sent for payment by its due date: contract-managed organizations).
summary.invoices[].descriptionstring or nullalways present
Free-text memo on the invoice (contract invoices), else null.
summary.invoices[].linesarray of BillInvoiceLinealways present
The invoice's lines.
summary.invoices[].lines[].descriptionstringalways present
The line's text as Stripe renders it (product, quantity, period).
summary.invoices[].lines[].amount_centsintegeralways present
Line amount in US cents; negative for a credit.
summary.invoices[].lines[].quantityintegeralways present
Quantity the line bills (1 for the plan and the add-on; the seat or county-slot count for those items).
summary.invoices[].lines[].prorationbooleanalways present
True when the line is a proration (the part-period charge or credit of a mid-period change).

400 error

Bad request. Codes: annual_plan_required (only when a scheduled plan move would re-price the add-on onto a non-annual interval in the state this request produces).

As application/problem+json.

401 error

Unauthenticated. Codes: unauthenticated (no valid API key or session); key_revoked (an API key that was revoked: revoked_at, and reason -- holder, admin, member_removed, seat_removed, api_disabled, addon_ended, account_closed, org_closed, retired, or null for a key revoked before T110 -- and a sentence saying when and why).

As application/problem+json.

403 error

Forbidden. Codes: role_required (only the owner, or a member flagged as billing contact, may manage billing; an admin only when also a billing contact; the problem carries required: [owner, billing_contact]), contract_managed (the organization is billing_mode: invoiced: its plan is managed under a contract by Data Tactical Group), no_membership (the account has no active organization), account_suspended (O56: the caller's own account is suspended by DTG), org_suspended (the organization is suspended), org_closed (the organization is closed), wrong_instance (a key of the mode this process does not serve: a sandbox key on the live API or a live key on the sandbox; base_url names the address that serves it). A sandbox key: sandbox_read_only (it may write only clusters).

As application/problem+json.

404 error

Not found. Codes: not_found (no such add-on: addon is not api), not_found (the X-DTG-Org header names an organization the caller does not belong to).

As application/problem+json.

409 error

Conflict. Codes: not_subscribed (the organization has no active subscription; use POST /v2/account/billing/subscribe), billing_in_progress (another billing change for this organization is running; the request waited 15 seconds; retry).

As application/problem+json.

429 error

rate_limited (the per-minute ceiling, X-RateLimit-* say which), points_exhausted (the monthly points allowance; Retry-After to the end of the UTC month), server_busy or sandbox_busy (load; retry after Retry-After). A refused server_busy request is not metered.

As application/problem+json.

Retry-After header
Seconds to wait before retrying.
X-RateLimit-Limit header
The per-minute request ceiling that applies.
X-RateLimit-Remaining header
Requests left in the current window.
X-RateLimit-Reset header
Seconds until the window refills: on every answer, the time until the bucket is full again; on a refusal, until a request is allowed (as Retry-After).

Problem codes: annual_plan_required (400), unauthenticated (401), key_revoked (401), account_closed (401), org_closed (401), role_required (403), contract_managed (403), no_membership (403), account_suspended (403), org_suspended (403), org_closed (403), wrong_instance (403), sandbox_read_only (403), not_found (404), not_subscribed (409), billing_in_progress (409). Every problem is a problem document.

Generated from taigan/openapi.yaml at catahoula 77925fab712f(API document version 2.0).