Basics
Errors
One shape for every refusal, with a stable code — and what to do about each.
Every refusal has the same shape:
{ "detail": { "code": "invoice_not_issuable", "messages": ["Kundenadresse ist unvollständig."] } }Programs decide on code — it is stable and documented below. Some codes carry fields of their own (scope,
invoice_id, open_from …), listed with the code. message and messages appear where AlphaCount's invoicing has
a sentence for a person, in German; do not parse them.
A body that does not fit
Wrong type, a missing field, an unknown field, a value out of range: 422 validation_failed with the places, without
the values you sent.
{
"detail": {
"code": "validation_failed",
"errors": [
{ "loc": ["body", "lines", 0, "vat_rate"], "type": "literal_error", "msg": "Input should be 0, 7 or 19" }
]
}
}Rely on loc and type. msg is for reading.
Status codes
| Status | Means | Retry? |
|---|---|---|
400 | the request is malformed (a header, the version) | no — fix it |
401 | the key is missing, unknown, expired, or its creator inactive | no |
403 | the key may not do this | no |
404 | not found in the key's company | no |
409 | a conflict with what exists | only conflict_retry |
422 | the request is understood but refused | no — fix the cause |
500 | AlphaCount failed | yes — a POST /invoices with the same Idempotency-Key |
Every code
| Code | Status | Meaning | Returned by |
|---|---|---|---|
api_key_admin_required | 403 | The key's creator is not an admin of the organisation. API keys act with an admin's rights. An admin creates the key. | every operation |
api_key_entity_not_accessible | 403 | The key's company is no longer reachable for its creator. | every operation |
api_key_entity_not_single | 403 | The key is not limited to exactly one company. The API works on one company per key. Create the key for exactly one company. | every operation |
api_key_expired | 401 | The key has passed its expiry date. Create a new key. | every operation |
api_key_invalid | 401 | The key is unknown, revoked, or not an AlphaCount API key. Create a new key under Integrations → API keys. | every operation |
api_key_missing | 401 | No API key: the request has no `Authorization: Bearer …` header. Send the key as `Authorization: Bearer ab_…`. | every operation |
api_key_scope_missing | 403 | The key lacks the scope this route needs. Create a key with the scope named in `scope`. Extra fields: scope | every operation |
api_key_user_inactive | 401 | The person who created the key no longer has access to the organisation. An active admin creates a new key. | every operation |
api_version_unknown | 400 | The `AlphaCount-Version` header names a version this API does not offer. Use one of `supported`, or leave the header out for the current version. Extra fields: supported | every operation |
commission.agreement_not_found | 404 | No agreement with this reference. | createInvoice, upsertCommissionAttribution |
commission.agreement_partner_mismatch | 409 | The agreement belongs to another partner. | upsertCommissionAgreement |
commission.agreement_takes_no_attributions | 422 | The agreement applies to all customers and takes no attributions. | createInvoice, upsertCommissionAttribution |
commission.agreement_terms_frozen | 409 | An agreement's terms cannot change once made. Make a new agreement; end the old one with `end_date`. | upsertCommissionAgreement |
commission.anchor_invalid | 422 | `anchor` is neither `attribution_start` nor `first_paid_revenue`. | upsertCommissionAgreement |
commission.applies_to_invalid | 422 | `applies_to` is neither `attributed_customers` nor `all_customers`. | upsertCommissionAgreement |
commission.attribution_conflict | 409 | Another partner holds this customer. End that attribution first. | createInvoice, upsertCommissionAttribution |
commission.attribution_reference_mismatch | 409 | The attribution reference exists for another customer or agreement. | createInvoice, upsertCommissionAttribution |
commission.billing_mode_invalid | 422 | Unknown billing mode. | upsertCommissionPartner |
commission.condition_not_found | 404 | The condition named in `condition_id` does not exist. | upsertCommissionAgreement |
commission.creditor_number_range_exhausted | 409 | The company has no free creditor number left (70000–79999). | upsertCommissionPartner |
commission.date_range_invalid | 422 | The end is before the start. | upsertCommissionAgreement, upsertCommissionAttribution |
commission.e_invoice_format_invalid | 422 | Unknown e-invoice format. | upsertCommissionPartner |
commission.min_payout_invalid | 422 | The minimum payout cannot be negative. | upsertCommissionPartner |
commission.partner_archived | 409 | The partner is archived. | upsertCommissionPartner |
commission.partner_kind_invalid | 422 | Unknown partner kind. | upsertCommissionPartner |
commission.partner_name_missing | 422 | The partner needs a name. | upsertCommissionPartner |
commission.partner_not_found | 404 | No revenue-share partner with this reference. | listCommissionEntries, listCommissionStatements, retrieveCommissionPartner, upsertCommissionAgreement |
commission.product_not_found | 404 | A named product does not exist in the company. Extra fields: product_numbers | createRevenueEvent, upsertCommissionAgreement |
commission.product_scope_invalid | 422 | The product selection is invalid. | upsertCommissionAgreement |
commission.revenue_event_not_found | 404 | `reverses_ref` names no revenue event of yours. | createRevenueEvent |
commission.revenue_lines_do_not_add_up | 422 | The lines do not add up to `net_amount`. | createRevenueEvent |
commission.start_date_missing | 422 | The start date is missing. | upsertCommissionAgreement |
commission.statement_not_found | 404 | No issued statement with this id. | downloadCommissionStatementPdf, retrieveCommissionStatement |
commission.supplier_not_found | 404 | The supplier to link the partner to does not exist. | upsertCommissionPartner |
commission.tax_status_invalid | 422 | Unknown tax status. | upsertCommissionPartner |
commission.tiers_empty | 422 | Give at least one tier. | upsertCommissionAgreement |
conflict_retry | 409 | Another request changed the same record at the same moment. Repeat the request. | createInvoice, createRevenueEvent, reportUsage, upsertCommissionAgreement, upsertCommissionAttribution, upsertCommissionPartner, upsertContract, upsertCustomer, upsertProduct |
contract.customer_mismatch | 409 | The contract belongs to another customer; a contract cannot change its customer. | upsertContract |
contract.date_range_invalid | 422 | The end is before the start. | upsertContract |
contract.end_before_billed | 422 | The end lies inside a period already billed in advance. End on `billed_until` or later; an earlier end needs a cancellation invoice in the app. Extra fields: args | upsertContract |
contract.ended | 409 | The contract has ended and cannot change. | upsertContract |
contract.interval_mismatch | 422 | A product recurs in another interval than the contract (or is one-off). Extra fields: product | upsertContract |
contract.item_not_found | 404 | A usage record names an item reference the contract does not have. Extra fields: item_refs | reportUsage |
contract.item_product_changed | 409 | An item reference keeps its product. Use a new `ref` for another product. Extra fields: ref | upsertContract |
contract.not_active | 409 | The contract is not active (a draft, or ended). | reportUsage, upsertContract |
contract.not_draft | 409 | A running contract cannot go back to draft. | upsertContract |
contract.terms_frozen | 409 | The contract runs: its interval and start are fixed. | upsertContract |
contract.usage_period_closed | 422 | Usage before `open_from` belongs to a period already billed; it could never reach an invoice. Extra fields: open_from, refs | reportUsage |
contract_not_found | 404 | No contract with this reference in the company. | reportUsage, retrieveContract |
customer_not_found | 404 | No customer with this reference in the company. Create it first with `PUT /customers/by-ref/{source}/{external_ref}`. | createInvoice, createRevenueEvent, upsertCommissionAttribution, upsertContract |
customer_number_range_exhausted | 409 | The company has no free customer number left. | upsertCustomer |
idempotency_key_invalid | 400 | The `Idempotency-Key` is not 1–255 printable characters without spaces. | createInvoice |
idempotency_key_missing | 400 | `POST /invoices` needs an `Idempotency-Key` header. Send a unique key per invoice, for example a UUID, and repeat it on retries. | createInvoice |
idempotency_key_reused | 409 | This `Idempotency-Key` was used with a different body. Use a new key for a new request. | createInvoice |
invoice_external_ref_exists | 409 | An invoice with this `external_ref` exists already. Retrieve it by reference, or use a new reference for a new invoice. Extra fields: invoice_id | createInvoice |
invoice_not_cancellable | 422 | The invoice cannot be cancelled in its state. Extra fields: messages, message | cancelInvoice |
invoice_not_found | 404 | No invoice the API can see under this id or reference. Invoices written in the app are not visible to the API. | cancelInvoice, downloadInvoicePdf, retrieveInvoice, retrieveInvoiceByRef, sendInvoice |
invoice_not_issuable | 422 | A mandatory detail for issuing is missing (on the company, the customer or a line). `messages` says what is missing; it is German text from the invoicing engine. Extra fields: messages, message | createInvoice |
invoice_not_issued | 409 | The invoice is a draft and has no PDF yet. | downloadInvoicePdf |
invoice_pdf_missing | 404 | The PDF of this invoice is not available. | downloadInvoicePdf |
invoice_render_failed | 500 | Rendering the PDF or e-invoice failed. Nothing was created. Repeat the request; if it persists, contact support. | cancelInvoice, createInvoice |
invoice_send_failed | 422 | The invoice exists, but the mail could not be sent. Retry with `POST /invoices/{id}/send`. Extra fields: message | sendInvoice |
period_locked | 409 | The accounting period is locked (Festschreibung). Corrections go into the open period. Extra fields: message | cancelInvoice, createInvoice |
pricing.model_unknown | 422 | Unknown pricing model. | upsertContract, upsertProduct |
pricing.negative_value | 422 | Quantities and prices cannot be negative. | upsertContract, upsertProduct |
pricing.overage_needs_quota | 422 | An overage price needs a quota (`included_quantity`). | upsertContract, upsertProduct |
pricing.package_size_missing | 422 | The package model needs the package size in `included_quantity`. | upsertContract, upsertProduct |
pricing.quantity_negative | 422 | A quantity cannot be negative. | upsertContract, upsertProduct |
pricing.tier_incomplete | 422 | A tier lacks `from` or `unit_price`. | upsertContract, upsertProduct |
pricing.tier_invalid | 422 | A tier is invalid. | upsertContract, upsertProduct |
pricing.tiers_empty | 422 | A tiered model needs at least one tier. | upsertContract, upsertProduct |
pricing.tiers_overlap | 422 | The tiers overlap, or an open-ended tier is not the last. | upsertContract, upsertProduct |
product_not_found | 404 | No product with this reference or article number in the company. Create it with `PUT /products/by-ref/{source}/{external_ref}`. Extra fields: product_ref, product_number | createInvoice, upsertContract |
product_number_taken | 409 | The article number belongs to another product. | upsertProduct |
validation_failed | 422 | The body or a parameter does not fit the schema. `errors` names each field (`loc`), the rule (`type`) and why (`msg`). Values are never echoed. Extra fields: errors | every operation |