Admin API
Management API — checkouts, transactions, invoices, clients, sites, providers, and organization settings.
Admin API
Base URL (canonical on the service): https://<your-admin-backend-host>/api/v1 — your deployment sets the host via ADMIN_BACKEND_DOMAIN. Self-hosted examples often use api.yourcompany.com or api.example.com; hosted production uses https://api.payment-gateway.app — Hostnames & DNS conventions.
OpenAPI / Swagger UI: https://<your-admin-backend-host>/api/v1/docs/index.html
Shorter public path (default reverse proxy): same host with /v1/... — payment-gateway-reverseproxy/Caddyfile rewrites /v1/* → /api/v1/* on {$ADMIN_BACKEND_DOMAIN} before proxying to the Admin Backend.
The Admin Backend is the primary integration surface for server-side automation. All endpoints require an API Key or JWT in the Authorization: Bearer header.
For merchant integrations, this is the API you should target. Use Organization API keys for organization-scoped automation. System API keys are intended for global administrative tasks such as platform provisioning or system-wide automation.
API Key format: sk_live_<keyId>.<secret> or sk_test_<keyId>.<secret>
The key ID and secret are dot-separated. Both parts are shown only once at creation time.
Organization API keys are already bound to a single organization. Do not send X-Organization-ID with organization API key requests; the backend resolves the organization directly from the key. JWT/session-based dashboard requests resolve organization context from the route :orgId parameter when present, otherwise from the selectedOrganization cookie maintained by the admin frontend.
[!IMPORTANT] Every endpoint enforces both role permission (
Viewer,Editor,Admin) and scope (resource:action). A request fails with403if the API key lacks the required scope.
Authentication
POST /api/v1/auth # Initiate WebAuthn authentication
POST /api/v1/auth/authenticate-complete # Complete WebAuthn authentication → JWT
POST /api/v1/auth/refresh-token # Refresh JWT
POST /api/v1/auth/logout # Invalidate session
GET /api/v1/auth/login/check # Check if current JWT is validCheckouts
| Method | Path | Required Scope | Description |
|---|---|---|---|
POST | /api/v1/checkouts/{siteId}/create | checkout:create | Create a checkout session for a site |
GET | /api/v1/checkouts | checkout:read | List all checkouts |
GET | /api/v1/checkouts/{checkoutId} | checkout:read | Get a checkout by checkout ID |
PATCH | /api/v1/checkouts/{checkoutId} | checkout:update | Update checkout metadata |
[!IMPORTANT] The
{siteId}in the create path is your Site MongoDB ObjectId (from Sites → Edit). The{checkoutId}in get / patch is the checkout document id — not the site id.
Create Checkout
POST /api/v1/checkouts/{siteId}/create
Authorization: Bearer sk_live_keyid.secret
Content-Type: application/json[!NOTE] Path examples below use
/api/v1/...as registered in the Admin Backend. On{$ADMIN_BACKEND_DOMAIN}with the default Caddyfile, the same handlers are reachable at/v1/....
{
"amount": 4900,
"currency": "EUR",
"email": "buyer@example.com",
"returnUrl": "https://yourapp.com/success?txId={transactionId}",
"cancelUrl": "https://yourapp.com/cancel",
"ipnUrl": "https://yourapp.com/webhooks/payment-ipn",
"externalReference": "order_12345",
"invoiceNumber": "INV-2026-0001",
"clientId": "507f1f77bcf86cd799439014",
"items": [
{
"name": "Professional Plan — Monthly",
"description": "Professional Plan — Monthly",
"quantity": 1,
"unitPrice": 4900,
"vatRate": 19,
"itemType": "virtual"
}
}
}[!IMPORTANT] Provide at least one of
externalReferenceorinvoiceNumber. The API accepts both, but a reference is required for reconciliation.
[!NOTE]
{transactionId}inreturnUrl/cancelUrlis a literal template placeholder — the gateway substitutes the actual transaction ID at redirect time.
Optional ipnUrl sets where the Main Backend sends outbound IPN for transactions created from this checkout; the Webhook Signing Secret on the Site is used to sign those requests.
Response 200:
{
"id": "507f1f77bcf86cd799439011",
"sessionPublicId": "abc123xyz789def456",
"shortCode": "aB3xK9mw2P",
"paymentUrl": "https://secure.payment-gateway.app/checkout/aB3xK9mw2P"
}paymentUrl is always on MAIN_FRONTEND_DOMAIN (hosted: secure.payment-gateway.app). See Hostnames & DNS conventions.
Transactions
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/transactions | transaction:read | List transactions (filterable) |
GET | /api/v1/transactions/:id | transaction:read | Get transaction details |
GET | /api/v1/transactions/:id/tax | transaction:read | Get full tax decision metadata |
PUT | /api/v1/transactions/:id | transaction:update | Update transaction metadata |
DELETE | /api/v1/transactions/:id | transaction:delete | Delete transaction |
POST | /api/v1/transactions/manual | transaction:create | Create a manual (off-platform) transaction |
PATCH | /api/v1/transactions/:id/chargeback/:chargebackId | transaction:execute | Update chargeback status |
POST | /api/v1/transactions/:id/recalculate-tax | transaction:execute | Re-run tax engine for one transaction |
GET | /api/v1/transactions/bulk-recalculate-tax | transaction:read | Get latest bulk tax recalculation job |
POST | /api/v1/transactions/bulk-recalculate-tax | transaction:execute | Start bulk tax recalculation |
GET | /api/v1/transactions/bulk-recalculate-tax/:jobId | transaction:read | Poll bulk tax recalculation job status |
List Transactions
GET /api/v1/transactions?status=succeeded¤cy=EUR&from=2026-01-01&to=2026-03-31&limit=50&page=1Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status | string | Filter: initiated, pending_provider, succeeded, failed, cancelled |
currency | string | ISO 4217 currency code (e.g., EUR, USD, GBP) |
from | date | Start date (ISO 8601) |
to | date | End date (ISO 8601) |
siteId | string | Filter by site |
providerId | string | Filter by provider |
clientId | string | Filter by client |
page | int | Page number (default: 1) |
limit | int | Items per page (default: 50, max: 100) |
Invoices
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/invoices | invoice:read | List invoices |
GET | /api/v1/invoices/:id | invoice:read | Get invoice |
POST | /api/v1/invoices | invoice:create | Create draft invoice |
POST | /api/v1/invoices/preview-tax | invoice:create | Preview canonical tax for a draft invoice payload |
POST | /api/v1/invoices/from-transaction/:transactionId | invoice:create | Create invoice from transaction |
PUT | /api/v1/invoices/:id | invoice:update | Update draft invoice fields and/or line items |
PATCH | /api/v1/invoices/:id/notes | invoice:update | Update invoice notes |
PUT | /api/v1/invoices/:id/transaction | invoice:update | Assign a transaction to an existing invoice |
POST | /api/v1/invoices/:id/issue | invoice:execute | Issue invoice (draft → issued) |
POST | /api/v1/invoices/:id/void | invoice:execute | Void an issued invoice (Admin role required) |
POST | /api/v1/invoices/:id/correct | invoice:update | Correct an invoice with audit trail / credit-note workflow |
POST | /api/v1/invoices/:id/send-email | invoice:execute | Email invoice to client |
POST | /api/v1/invoices/:id/payment-checkout | invoice:execute | Create an online payment checkout for the invoice |
GET | /api/v1/invoices/:id/pdf | invoice:execute | Download PDF |
GET | /api/v1/invoices/:id/xml | invoice:execute | Download XML (XRechnung / configured e-invoice output) |
GET | /api/v1/invoices/:id/xml/peppol | invoice:execute | Download Peppol XML |
GET | /api/v1/invoices/:id/pdf/zugferd | invoice:execute | Download ZUGFeRD PDF |
POST | /api/v1/invoices/:id/regenerate-pdf | invoice:execute | Force PDF regeneration |
DELETE | /api/v1/invoices/:id | invoice:delete | Delete draft invoice |
Draft Invoice Tax Semantics
Draft invoice creation, draft invoice updates, recurring invoice generation, and transaction tax calculation all rely on the same backend tax engine and tax-rate timing rules.
- Omit
items[].taxRateto let the backend auto-calculate tax from the seller context, client billing country, client tax country fallback, item type, and the effective tax-rate schedule. - Provide
items[].taxRateto apply an explicit manual override for that line item. - Use
POST /api/v1/invoices/preview-taxbefore creating or updating a draft invoice when you need the exact canonical rate, totals, andtaxRateCodethe backend will use.
Example manual draft invoice payload with one automatic line and one explicit override:
{
"siteId": "507f1f77bcf86cd799439011",
"clientId": "507f1f77bcf86cd799439012",
"currency": "EUR",
"items": [
{
"description": "Subscription",
"quantity": 1,
"unitPrice": 12100,
"amountType": "gross",
"itemType": "virtual"
},
{
"description": "Manual reduced VAT line",
"quantity": 1,
"unitPrice": 10700,
"amountType": "gross",
"taxRate": 7,
"itemType": "physical"
}
]
}In the example above, the first line is auto-calculated and the second line uses an explicit 7% override.
Recurring Schedules
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/invoices/recurring | invoice:read | List schedules |
POST | /api/v1/invoices/recurring | invoice:create | Create schedule |
POST | /api/v1/invoices/recurring/:id/pause | invoice:execute | Pause schedule |
POST | /api/v1/invoices/recurring/:id/resume | invoice:execute | Resume schedule |
POST | /api/v1/invoices/recurring/:id/cancel | invoice:execute | Cancel schedule |
POST | /api/v1/invoices/recurring/:id/generate | invoice:execute | Manually generate next invoice |
GET | /api/v1/invoices/recurring/:id/upcoming | invoice:execute | Preview upcoming invoices |
Credit Notes
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/credit-notes | credit_note:read | List credit notes |
GET | /api/v1/credit-notes/:id | credit_note:read | Get credit note |
GET | /api/v1/credit-notes/:id/pdf | credit_note:execute | Download PDF |
POST | /api/v1/credit-notes/:id/send-email | credit_note:execute | Email credit note |
Clients
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/clients | client:read | List clients |
GET | /api/v1/clients/search | client:execute | Full-text search |
GET | /api/v1/clients/:id | client:read | Get client |
POST | /api/v1/clients | client:create | Create client |
PUT | /api/v1/clients/:id | client:update | Update client |
DELETE | /api/v1/clients/:id | client:delete | Delete client |
GET | /api/v1/clients/:id/history | client:execute | Get client audit history |
Sites
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/sites | site:read | List sites |
GET | /api/v1/sites/:id | site:read | Get site |
POST | /api/v1/sites | site:create | Create site |
DELETE | /api/v1/sites/:id | site:delete | Delete site |
POST | /api/v1/sites/:id/webhook-secret/regenerate | site:update | Rotate outbound webhook secret |
Organization Settings
Invoicing Settings
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/organizations/settings/invoicing | organization:read | Get invoicing settings for the active organization |
PUT | /api/v1/organizations/settings/invoicing | organization:update | Update invoicing settings for the active organization |
The numbering contract is layout-based. Organizations store one layout for invoices and one for credit notes.
{
"enabled": true,
"autoGenerateInvoice": false,
"companyName": "Example GmbH",
"companyAddress": {
"street": "Example Street 1",
"city": "Berlin",
"postalCode": "10115",
"country": "DE"
},
"companyEmail": "billing@example.com",
"invoiceNumberLayout": {
"prefix": "INV-",
"periodType": "calendar",
"periodGranularity": "year",
"fiscalYearStartMonth": 1,
"fiscalYearLabelMode": "end_year",
"periodSeparator": "dash",
"infix": "-",
"sequenceDigits": 6,
"suffix": "",
"resetPolicy": "calendar_year",
"startNumber": 1
},
"creditNoteNumberLayout": {
"prefix": "CN-",
"periodType": "calendar",
"periodGranularity": "year",
"fiscalYearStartMonth": 1,
"fiscalYearLabelMode": "end_year",
"periodSeparator": "dash",
"infix": "-",
"sequenceDigits": 6,
"suffix": "",
"resetPolicy": "calendar_year",
"startNumber": 1
}
}Tax settings (organization)
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/organizations/settings/tax | organization:execute | Read org tax configuration (OSS/IOSS flags, VIES, rounding, etc.) |
PUT | /api/v1/organizations/settings/tax | organization:execute | Update org tax configuration (Admin permission; API keys need scope above) |
GET | /api/v1/organizations/settings/tax/oss-threshold-status | organization:read | EU B2C cross-border threshold vs OSS registration status |
Notes:
periodTypeis one ofnone,calendar, orfiscal.periodGranularityis one ofyear,year_month, oryear_month_day.periodSeparatorisdashornoneand only matters when month or day is visible.resetPolicyis one ofnever,calendar_year, orfiscal_year.- Sites inherit these layouts and may override only
invoicePrefixandcreditNotePrefixin their site-level invoicing settings.
Providers
| Method | Path | Required Scope | Required Role | Description |
|---|---|---|---|---|
GET | /api/v1/providers | provider:read | Viewer | List providers |
GET | /api/v1/providers/:id | provider:read | Viewer | Get provider |
POST | /api/v1/providers | provider:create | Admin | Create provider |
DELETE | /api/v1/providers/:id | provider:delete | Admin | Delete provider |
POST | /api/v1/providers/:id/toggle | provider:update | Admin | Enable/disable provider |
Domains
| Method | Path | Required Scope | Required Role | Description |
|---|---|---|---|---|
GET | /api/v1/domains | domain:read | Viewer | List domains |
POST | /api/v1/domains | domain:create | Admin | Register custom domain |
DELETE | /api/v1/domains/:id | domain:delete | Admin | Remove domain |
GET | /api/v1/domains/verify-cname | domain:execute | Editor | Verify CNAME record |
API Keys
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/organizations/{orgId}/api-keys | api_key:read | List organization API keys |
POST | /api/v1/organizations/{orgId}/api-keys | api_key:create | Create organization API key |
GET | /api/v1/organizations/{orgId}/api-keys/{id} | api_key:read | Get organization API key details |
PUT | /api/v1/organizations/{orgId}/api-keys/{id} | api_key:update | Update API key metadata / scopes |
DELETE | /api/v1/organizations/{orgId}/api-keys/{id} | api_key:delete | Delete API key |
POST | /api/v1/organizations/{orgId}/api-keys/{id}/revoke | api_key:execute | Revoke API key |
POST | /api/v1/organizations/{orgId}/api-keys/{id}/rotate | api_key:execute | Rotate API key (issues new secret) |
Organization API keys are already bound to one organization, but the management endpoints remain nested under
/organizations/{orgId}/api-keys for admin and automation workflows. System API keys use the /api/v1/system/api-keys
family and are intended for global administrative automation rather than normal merchant checkout integrations.
Portal
| Method | Path | Required Scope | Description |
|---|---|---|---|
POST | /api/v1/organizations/settings/portal/magic-links | portal:create | Generate a one-time direct-login customer portal link |
Create Customer Portal Magic Link
POST /api/v1/organizations/settings/portal/magic-links
Authorization: Bearer sk_live_keyid.secret
Content-Type: application/json{
"email": "buyer@example.com",
"ttlMinutes": 15
}Returns a one-time magic-link URL that can be used to direct the customer straight into the portal login flow for that email.
ttlMinutes is optional. If omitted, the system portal magic-link TTL is used. If provided, it can only shorten the lifetime; values above the system policy are capped to the configured system maximum.
Example server-side usage:
const response = await fetch(
`${adminBaseUrl}/api/v1/organizations/settings/portal/magic-links`,
{
method: "POST",
headers: {
Authorization: `Bearer ${organizationApiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "buyer@example.com",
ttlMinutes: 15,
}),
},
);
if (!response.ok) {
throw new Error(`Failed to create portal magic link: ${response.status}`);
}
const { url, expiresAt, ttlMinutes } = await response.json();
return {
loginUrl: url,
expiresAt,
effectiveTtlMinutes: ttlMinutes,
};The endpoint only succeeds when:
- system-level portal access is enabled,
- system-level portal magic links are enabled,
- the authenticated organization has portal access enabled, and
- the email has at least one portal-visible invoice, credit note, or recurring subscription in that organization.
Use this for trusted backend automations only. Do not expose it to browser or mobile clients.
Tax Management
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/tax-rules | tax_rule:read | List tax rules |
POST | /api/v1/tax-rules | tax_rule:create | Create tax rule |
DELETE | /api/v1/tax-rules | tax_rule:delete | Delete all tax rules (destructive) |
PUT | /api/v1/tax-rules/:id | tax_rule:update | Update tax rule |
DELETE | /api/v1/tax-rules/:id | tax_rule:delete | Delete one tax rule |
POST | /api/v1/tax-rules/populate-defaults | tax_rule:create | Load default EU/UK/US/CA rules |
GET | /api/v1/tax-rates | tax_rate:read | List tax rates |
POST | /api/v1/tax-rates | tax_rate:create | Create tax rate |
DELETE | /api/v1/tax-rates | tax_rate:delete | Delete all tax rates (destructive) |
POST | /api/v1/tax-rates/replace-defaults | tax_rate:execute | Replace rates with the current default catalog |
GET | /api/v1/tax-rates/:id | tax_rate:read | Get one tax rate |
PUT | /api/v1/tax-rates/:id | tax_rate:update | Update tax rate |
DELETE | /api/v1/tax-rates/:id | tax_rate:delete | Delete one tax rate |
Admin JWT calls use the Admin role for these routes; API keys need the matching tax_rule:* / tax_rate:* scopes.
Tax Reports
Reports use query parameters for filters (e.g. startDate, endDate, timezone, source=transactions|invoices|both, currency, siteId). VAT OSS endpoints require year and quarter (1–4). Export endpoints return a file download and are GET, not POST.
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/tax/reports/by-country | tax_report:read | Tax summary grouped by buyer country |
GET | /api/v1/tax/reports/by-country/details | tax_report:read | Row-level basis for one country in that report |
GET | /api/v1/tax/reports/by-country/export | tax_report:execute | Download country report as CSV |
GET | /api/v1/tax/reports/revenue-by-country | tax_report:read | Revenue-style summary by country |
GET | /api/v1/tax/reports/revenue-by-country/export | tax_report:execute | Download revenue-by-country report as CSV |
GET | /api/v1/tax/reports/currencies | tax_report:read | Currencies available for report filters |
GET | /api/v1/tax/reports/vat-oss | tax_report:read | EU VAT OSS quarterly aggregation |
GET | /api/v1/tax/reports/vat-oss/details | tax_report:read | OSS line basis (country, rate code, supply type) |
GET | /api/v1/tax/reports/vat-oss/export | tax_report:execute | Download OSS report as XML |
GET | /api/v1/tax/reports/vat-oss/export-elster | tax_report:execute | Download OSS data as Elster CSV (Germany) |
Tax records (canonical ledger)
Immutable tax records back admin reporting drill-downs and traceability. List filters include date range, sourceKind, taxCountry, recognitionMode (accrual / cash), pagination, and links to transactions or invoices.
| Method | Path | Required Scope | Description |
|---|---|---|---|
GET | /api/v1/tax/records | tax_record:read | List tax records |
GET | /api/v1/tax/records/:id | tax_record:read | Get one tax record |
GET | /api/v1/transactions/:id/tax-records | tax_record:read | Tax records linked to a transaction |
GET | /api/v1/invoices/:id/tax-records | tax_record:read | Tax records linked to an invoice |
Data Import / Export
| Method | Path | Required Scope | Description |
|---|---|---|---|
POST | /api/v1/data-import-export/import | data_io:execute | Import CSV data |
POST | /api/v1/data-import-export/import/validate | data_io:execute | Validate import file before committing |
POST | /api/v1/data-import-export/export | data_io:execute | Export entity data to CSV |
GET | /api/v1/data-import-export/template/:entityType | data_io:read | Download import CSV template |
Dashboard
GET /api/v1/dashboardReturns aggregated metrics: gross volume, net revenue, transaction counts, failure ratios, top providers, and recent transactions. Used by the Admin Panel home page.
API Key Scopes Reference
| Scope | Grants |
|---|---|
checkout:read | Read checkouts |
checkout:create | Create checkout URLs |
checkout:update | Update checkout metadata |
transaction:read | Read transactions and tax details |
transaction:create | Create manual transactions |
transaction:update | Update transaction metadata |
transaction:delete | Delete transactions |
transaction:execute | Chargeback management |
invoice:read | Read invoices and recurring schedules |
invoice:create | Create invoices and schedules |
invoice:update | Update draft invoices, notes, invoice links, and correction workflows |
invoice:execute | Preview tax, issue, void, email, payment checkout, PDF download, and recurring schedule actions |
invoice:delete | Delete draft invoices |
credit_note:read | Read credit notes |
credit_note:execute | Download credit note PDFs and send credit note email |
client:read | Read clients |
client:create | Create clients |
client:update | Update clients |
client:delete | Delete clients |
client:execute | Search clients, view history |
site:read | Read sites |
site:create | Create sites |
site:delete | Delete sites |
site:update | Update sites, rotate webhook secret |
provider:read | Read providers |
provider:create | Create providers (Admin role also required) |
provider:update | Enable/disable providers (Admin role) |
provider:delete | Delete providers (Admin role) |
domain:read | Read domains |
domain:create | Create domains (Admin role) |
domain:delete | Delete domains (Admin role) |
domain:execute | Verify CNAME, Apple Pay files |
api_key:read | Read API keys |
api_key:create | Create API keys |
api_key:update | Update API key metadata, scopes, or whitelist |
api_key:delete | Delete API keys |
api_key:execute | Rotate or revoke API keys |
organization:read | Read organization details |
organization:update | Update organization settings |
organization:execute | Access settings, encryption operations |
tax_rule:read | Read tax rules |
tax_rule:create | Create tax rules and populate default rule sets |
tax_rule:update | Update tax rules |
tax_rule:delete | Delete tax rules |
tax_rate:read | Read tax rates |
tax_rate:create | Create tax rates |
tax_rate:update | Update tax rates |
tax_rate:delete | Delete tax rates |
tax_rate:execute | Replace default tax rates (replace-defaults) |
tax_report:read | Read tax reports |
tax_report:execute | Export tax reports (CSV/XML/Elster) |
tax_record:read | Read canonical tax ledger records |
data_io:read | Read import/export templates |
data_io:execute | Import and export data |
export:execute | Generate CSV exports |
portal:create | Generate direct-login customer portal magic links |
vies:read | Check EU countries |
vies:execute | Validate VAT IDs |
userprofile:read | Read own user profile |
userprofile:update | Update passkey labels, notification prefs |
userprofile:execute | Manage passkeys and related user profile actions |
Common least-privilege bundles
- Checkout creation:
checkout:create - Website billing bridge auto-provisioning:
client:read,client:create,invoice:read,invoice:create - Recurring schedule management:
invoice:read,invoice:create,invoice:execute
Recurring schedules do not use a separate recurring:* scope family. They are governed by the invoice:* scope family.