The Kontier Billing API runs subscription and usage-based billing: customers and their legal identifiers, a versioned catalog (products, prices, plans, rate tables, formulas), subscriptions authored as revisions of dated phases, quotes with e-signature, usage events and meters, invoices, credit notes and e-invoicing, payments and refunds, wallets, promotions, dunning cases, webhooks and integrations.
Base URL: https://api.kontier.eu/v1
Authentication: All requests require an Authorization: Bearer ... header. See Authentication for details.
Idempotency: Every POST must carry an Idempotency-Key header. See Errors.
Dashboard-only surfaces: a few things are done by a person in the dashboard and are deliberately not part of this reference: deciding approval requests, mail templates and sending providers, branding, and audit retention and redaction.
- External ID - your internal identifier for this customer, used for idempotent upserts
- Billing model - controls how charges are calculated (prepaid, postpaid, or hybrid)
- Customer type -
individualorcompany, affects tax treatment and invoice formatting - Metadata - arbitrary key-value pairs for your own bookkeeping
DRAFT → ACTIVE ⇄ PAUSED → CANCELLED. A trial is not a status; it is a phase whose price is free.
Revisions, phases and lines. The deal is held in a revision. A revision is an ordered list of phases (each with an opening rule, a closing rule and what follows it), and each phase bills lines: one per product, pre-filled from a plan or product version (the line's origin). A line value — quantity, price, allowance, cadence, timing, track — is either stated on the phase, carried from an earlier phase, or taken from the catalogue.
Lifecycle through the API:
POST /subscriptionscreates the envelope (customer, name, currency) inDRAFTwith an empty draft revision 1.PUT /subscriptions/{id}/revisions/draftwrites the phases and lines of revision 1.POST /subscriptions/{id}/activatepublishes revision 1 and starts the subscription.- To change a running deal, open the next revision (
POST /subscriptions/{id}/revisions/cutorPOST /subscriptions/{id}/revisions/draft), edit it, and publish it withPOST /subscriptions/{id}/revisions/draft/publish. POST /subscriptions/{id}/pause,/resumeand/cancel(now, at a date, or at the end of the billing period);DELETE /subscriptions/{id}/scheduled-cancellationwithdraws a planned cancellation.
draft → finalized → sent → paid (or void / uncollectible). Draft invoices can be edited; finalized invoices are immutable and receive a sequential invoice number.
Key concepts:
- Invoice type -
subscription(recurring),one_off(manual), orcredit_note(refund/adjustment) - Line items - individual charges with product, quantity, amount, and tax breakdown
- Credit notes - partial or full reversals of a finalized invoice
- PDF export - generate a formatted PDF for download or email delivery
- XRechnung - EU-compliant electronic invoice format (XML) for B2G billing
- Buyer reference - PO number or reference that appears on the invoice for the customer's records
POST /changes with operation: catalog.publish_version — now or at a scheduled time. scheduled_versions lists versions waiting to publish, GET /plans/{id}/history lists the published ones.
Subscribers. Each subscription line either follows its plan (moves to new versions, by its version_change strategy) or is pinned to the version it was sold on.- Credit - add funds to the wallet (from a payment, promotion, or manual adjustment)
- Debit - remove funds (applied automatically during invoicing, or manually)
- Hold - reserve an amount for a pending charge (released or captured later)
- Transfer - move funds between wallets (e.g., currency conversion)
- Adjust - correct the balance without a formal credit/debit (e.g., migration adjustment)
POST /quotes/{id}/revisions): a new DRAFT subscription, or a new revision of an existing one, whose phases and lines are authored with the subscription revision operations. Sending the quote gives the buyer a signing link; signing publishes the bound revisions. Contract clauses and quote presets are managed here too.- Product type -
recurring,usage,one_time, orseat- determines how charges are calculated - External ID - your internal SKU or product code for integration with other systems
- Cost tracking - named COGS entries via
costs[](per-product or org-scoped) for margin analysis - Dependencies -
requires_product_idsenforces that certain products must be purchased together
- Flat - a fixed amount per billing period (e.g., $49/month)
- Per-unit - a fixed amount multiplied by quantity (e.g., $10/seat)
- Tiered - different rates at different volume thresholds (e.g., $0.10/unit for 0–1,000, $0.08/unit for 1,001–10,000)
- Volume - the tier that contains the total quantity determines the rate for all units
- Graduated - each tier's rate applies only to units within that tier's range
- Formula - a mathematical expression evaluated at billing time (see Price Formulas)
- Effective date - prices can be scheduled to take effect in the future
- Country code - geo-specific pricing for different markets
- Currency - each price is denominated in a single currency; use multiple prices for multi-currency support
base_price * (1 - volume_discount) where volume_discount increases with usage.- Code - the coupon code a customer enters (e.g.,
SAVE20) - Effects - what the promotion does: percentage discount, fixed discount, free trial extension, or credit grant
- Conditions - eligibility rules: minimum spend, specific plans, customer segments, date ranges
- Budget - optional spending cap; the promotion deactivates when the budget is exhausted
- Stackable - whether this promotion can combine with other active promotions
- Simulation - preview the financial impact of a promotion before activating it
GET /usage-events/billing to find the invoice that billed one event.- Provider - the payment processor (
stripe,gocardless, etc.) - Mode -
liveortest- determines whether real charges are made - Supported currencies - which currencies this gateway can process
- Supported methods - which payment methods this gateway handles (card, direct_debit, etc.)
is_default and is used automatically when invoices are finalized.- Jurisdiction - country and optional region the rule applies to
- Tax type -
vat,sales_tax,gst,hst, etc. - Inclusive vs. exclusive - whether the tax is included in the listed price or added on top
- Compound tax - whether this tax is calculated on the pre-tax amount or on the amount including other taxes
- Apply order - controls the sequence when multiple tax rules apply
GET /changes/operations lists the operations this deployment can schedule, with the when kinds each accepts (now, a wall-clock time, the end of the billing period, …) and the schema of its payload.
Author with POST /changes, preview first with POST /changes/preview, move one with PATCH /changes/{id}, cancel one with DELETE /changes/{id}, and read what it did with GET /changes/{id}/outcomes.
Publishing a plan, product, rate table, tax rule or price formula draft is always a Change: operation: catalog.publish_version.billing_state, and stage changes are delivered as webhook events.GET /webhook-endpoints/event-catalog lists them), read delivery attempts and requeue one. The payload of every event type is documented under Webhooks in this reference.gate: approval, …). A gated call answers 202 with an approval_request_id; read the request here, or wait for the approval.* webhook events whose request_id is that id. Deciding, cancelling and retrying a request is a person's act in the dashboard: an API key cannot decide.jobs.dead_lettered carry a job_id you can look up here.GET /organization/settings/catalog lists every key with its type; GET /organization/settings/resolve answers the effective value and where it came from. Also: sharing a resource (such as a dunning policy) with the organizations below yours, and e-invoicing channels and their credentials.text, number, boolean, date, enum, entity_ref
Key concepts:
- Entity types - which resources this field applies to (e.g.,
customer,subscription) - Field group - logical grouping for UI display
- Validation - regex patterns, min/max values, required/optional
- Auditable - whether changes to this field are tracked in the audit log
- Deprecation - soft-disable a field before permanent removal
pending → verified / failed / expired.
Use verifications for KYC/KYB compliance, age verification, or business entity validation.- MRR - the normalized monthly revenue from all active subscriptions
- Churn - the rate at which customers cancel or downgrade
- Revenue - breakdown by product, plan, currency, and time period
403.403.- Authenticate the customer in your own app, as you do today.
- Find their Kontier customer:
GET /v1/customers?email=jane@example.com(or keep the customeridyou stored when you created them). - Issue a link:
POST /v1/customers/{id}/portal-linkswith a shortttl_secondsand, if you want, areturn_path. - Redirect the browser to the returned
urlat once. The customer lands signed in, onreturn_pathif you gave one.
Code
Every POST needs anCode
Idempotency-Key. Use a new one for each sign-in: a retry with the same key replays the first answer, which is the same single-use link.
Security contract
- Authenticate your customer first. Whoever holds the URL is signed in as that customer.
- Redirect, do not send. Never email, log or store the link unless delivering it is what you mean to do.
- Links are single-use and short-lived. A link signs in once; opening it again lands on the portal's expired page, exactly as an expired link does. It lives for
ttl_seconds(60 up to the deployment's link TTL, 30 minutes unless configured otherwise). Ask for 60 to 120 seconds when you redirect at once. Links issued before single-use links were introduced carry no single-use id and are refused: issue a new one. - Scope your key. The endpoint needs the
portal.links.issuepermission (area Portal Sign-in in the key's custom access). Give the key that signs customers in that permission and only what else it needs. Keys that heldcustomer.writebefore this permission existed were granted it once, so existing integrations keep working.
return_path must be one of the portal's own pages, such as /portal/invoices, /portal/invoices/{id}/pay, /portal/quote/{id} or /portal/subscriptions/{id}. Anything else (another host, a query, //) is refused with 400.
Each link you issue is recorded in the audit log as customer.portal_access_issued: who issued it, for which customer, the landing page and the expiry. The link itself is never stored.POST /invitations).GET /customers/{id}/audit-events.allowance.given_back
allowance.rolled_over
approval.applied
approval.apply_failed
approval.request_approved
approval.request_cancelled
approval.request_created
approval.request_expired
approval.request_rejected
approval.request_retried
approval.withdraw_failed
approval.withdrawn
catalog.version_published
connection.health_changed
customer.created
customer.currency_changed
customer.mode_changed
customer.type_changed
dispute.changed
document.generated
document.requested
dunning.case.closed
dunning.case.opened
dunning.case.reopened
dunning.step.cancel
dunning.step.email
dunning.step.grace
dunning.step.suspend
e_invoicing.document.generated
e_invoicing.document.quarantined
firing.recorded
integration.run_failed
invoice.corrected
invoice.drafted
invoice.finalized
invoice.payment_attempt_failed
invoice.payment_failed_terminal
invoice.payment_recorded
invoice.reservation_released
invoice.written_off
jobs.dead_lettered
marketplace.payout.paid
marketplace.sale.agreed
marketplace.sale.cancelled
marketplace.sale.chargeback_reassigned
marketplace.sale.completed
marketplace.sale.funded
marketplace.sale.refunded
marketplace.seller.closed
marketplace.seller.created
marketplace.seller.reinstated
marketplace.seller.suspended
marketplace.seller.verified
marketplace.statement.finalized
meter.threshold_breached
organization.closed
organization.delegation_granted
organization.delegation_revoked
organization.hold_placed
organization.hold_released
payment.changed
payment_method.attached
payment_method.default_set
payment_method.removed
payment_method.updated
plan.cloned
plan.created
plan.deleted
plan.subscribers_migrated
plan.updated
product.activated
product.archived
product.copied
product.created
product.deleted
product.updated
product.version_rebased
promotion.created
promotion.ended
promotion.narrowed
promotion.published
promotion.terms_changed
quote.approved
quote.created
quote.declined
quote.expired
quote.orchestrated
quote.orchestration_requested
quote.rejected
quote.reminded
quote.sent
quote.signed
quote.viewed
redemption.created
redemption.ended
redemption.status_changed
reserve_outcome.captured
reserve_outcome.failed
reserve_outcome.queued
sepa_mandate.activated
sepa_mandate.created
sepa_mandate.failed
sepa_mandate.revoked
signing.countersign_requested
signing.envelope_cancelled
signing.envelope_completed
signing.envelope_expired
signing.envelope_sent
signing.reminder_sent
signing.signer_declined
signing.signer_signed
signing.signer_viewed
signing.turn_reached
subscription.activated
subscription.billing_blocked
subscription.billing_unblocked
subscription.cancelled
subscription.created
subscription.dunning_entered
subscription.dunning_stage_changed
subscription.event_fired
subscription.paused
subscription.payment_failed
subscription.phase_entered
subscription.recovered
subscription.renewal_upcoming
subscription.resumed
subscription.revision_published
subscription.status_changed
subscription.stopped
tag.applied
tag.deleted
tag.removed
tag.renamed
tax.oss_threshold_approaching
tax.oss_threshold_exceeded
wallet.apply_to_invoice
wallet.auto_topup_triggered
wallet.hold_expired
wallet.low_balance
wallet.payment_skipped
wallet.promotional_balance_expired
wallet.topped_up
wallet.transferred