Check the licence
Step-by-step use case to read the licence of a firm through the API, find out its caps and its monthly estimate, and activate an activation key.
The licence of a firm determines its plan, its caps on companies and users and its billing estimate. Your integration can read it to check that a company can still be created, or to display the consumption in a dashboard.
Prerequisites: a token with the read ability, held by a member of the firm, and the public_token of the firm. Activating a key additionally requires write and the administrator or manager role.
Step 1: read the licence
curl "https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/licence?lang=fr" \
-H "Authorization: Bearer $NOVAFISKO_TOKEN"
{
"status": "active",
"subscription": {
"id": 31,
"status": "active",
"billing_interval": "monthly",
"current_period_start": "2026-10-01",
"current_period_end": "2026-10-31",
"trial_ends_at": null,
"source": "licence_key",
"billed": true,
"pilot": {"active": false, "until": null}
},
"plan": {
"code": "firm",
"name": "Cabinet",
"kind": "firm",
"features": ["peppol", "document_import", "bank"],
"base_price_monthly": 49.0,
"tiers": [{"from": 1, "to": 10, "unit_price": 9.0}, {"from": 11, "to": null, "unit_price": 7.0}],
"max_companies": null,
"peppol_fair_use_per_company": 200,
"annual_discount_pct": 10.0
},
"usage": {
"month": "2026-10",
"companies": 12,
"users": 4,
"bank_accounts": 15,
"rows": [
{"company_id": 318, "token": "k3Jd9fPq2LmX", "name": "Le Comptoir Montois SRL", "code": "COMPTOIR", "bank_accounts": 2, "status": "active", "activated_at": "2026-01-06T09:00:00+00:00", "deactivated_at": null}
],
"max_companies": 25,
"over_limit": false,
"suggestion": null
},
"estimate": {
"month": "2026-10",
"base": 49.0,
"companies_breakdown": [
{"from": 1, "to": 10, "quantity": 10, "unit_price": 9.0, "total": 90.0},
{"from": 11, "to": null, "quantity": 2, "unit_price": 7.0, "total": 14.0}
],
"options": [],
"discount": 0.0,
"subtotal": 153.0,
"vat_rate": 21.0,
"vat_amount": 32.13,
"total_incl_vat": 185.13,
"billed": true
},
"next_month_preview": {"companies": 12, "total": 153.0},
"over_limit": false,
"limits": {"max_users": 10, "max_companies": 25, "users_count": 4, "companies_count": 12},
"expires_at": "2027-09-30",
"warning": null,
"activation": {
"key_masked": "NF-••••-••••-••••-7K2Q",
"activated_at": "2026-01-06T08:55:12+00:00",
"valid_until": "2027-09-30",
"services": ["peppol", "document_import"]
},
"statements": [
{"id": 904, "reference": "NF-2026-09-0031", "kind": "monthly", "period": "2026-09", "subtotal": 146.0, "vat_amount": 30.66, "total": 176.66, "status": "paid", "issued_at": "2026-10-01", "paid_at": "2026-10-03"}
],
"options_available": [
{"code": "extra_bank_account", "name": "Compte bancaire supplémentaire", "price_monthly": 2.0, "unit": "par compte"}
],
"can_manage": true
}
The response is abridged: it also contains entitlements, companies_detail, comparison and a few legacy fields kept for older versions of the applications. The figures above are examples: the actual price list is published by GET /v1/pricing.
Fields useful to an integration
| Field | Usage |
|---|---|
status |
none if the firm has no usable subscription, otherwise the status of the subscription |
limits.max_companies, limits.companies_count |
Find out whether there is room left for a new company. null means no cap |
limits.max_users, limits.users_count |
Same logic for team members |
over_limit |
The firm exceeds the cap of its plan |
expires_at |
End of validity of the activation key, null without a key |
warning |
Warning to display (approaching deadline, cap exceeded), null otherwise |
estimate |
Estimate for the current month, exclusive and inclusive of VAT |
can_manage |
The user can activate or release a key |
Licence amounts are JSON numbers and not strings. They are commercial amounts and not accounting entries. See Conventions.
A user who is not a member of the firm receives 404.
Step 2: check before creating a company
def can_add_company(licence):
limits = licence["limits"]
if limits["max_companies"] is None:
return True # no ceiling on this plan
return limits["companies_count"] < limits["max_companies"]
If you create a company anyway while the cap is reached, POST /v1/companies responds 422 with the company_limit_reached code. In the same way, adding a team member beyond the cap responds 422 with user_limit_reached.
Step 3: activate a key
An activation key has the form NF-XXXX-XXXX-XXXX-XXXX. It grants a plan, options and caps for a given duration.
curl -X POST https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/licence/activate \
-H "Authorization: Bearer $NOVAFISKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"key": "NF-8H2K-P4QM-7TZD-7K2Q"}'
On success, the 200 response is the updated licence, in the same shape as in step 1. On refusal, the response is 422:
{
"message": "Cette clé d'activation a expiré.",
"code": "expired_key",
"errors": {"key": ["Cette clé d'activation a expiré."]}
}
code |
Meaning |
|---|---|
invalid_key |
Key unknown or mistyped |
expired_key |
Key expired |
exhausted_key |
Allowed number of activations already reached |
key_reserved |
Key reserved for another firm |
already_active |
Key already active on this firm |
The route is limited to 10 attempts per minute.
Release a key
curl -X DELETE https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/licence/activation \
-H "Authorization: Bearer $NOVAFISKO_TOKEN"
The key becomes available again and the subscription that depends on it is cancelled. The response is the updated licence.
Activating and releasing a key are blocked in the demo firm (403, code demo_mode).
Public price list
Two public routes, without authentication, feed a simulator:
curl https://api.novafisko.com/v1/pricing
curl "https://api.novafisko.com/v1/pricing/simulate?companies=12"
Their detailed schema is in the reference.