Administration API¶
Applies to: All subscriptions
Purpose¶
Describe the administrative surface for teams automating provisioning or operational tasks, and state plainly where automation is appropriate and where the console is the better tool.
Audience¶
Integration developers automating administration, and system administrators.
Prerequisites¶
- API Authentication — these endpoints use a user token with an administrative role
- Roles and Permissions
Reference¶
These endpoints exist to serve Complifly's own admin console. They are documented for automation, but the console is the supported path for occasional administration. Automate provisioning and bulk work; do not rebuild the console.
Users and access¶
Base path /api/admin
| Method | Path | Purpose |
|---|---|---|
GET |
/users |
List users |
POST |
/users |
Create a user |
PUT |
/users/{userId} |
Update a user |
DELETE |
/users/{userId} |
Remove a user |
GET |
/company-gstins |
Registrations for the company |
GET |
/all-companies |
Companies visible to the caller |
GET |
/approval-roles |
The assignable Approval Engine role ladder |
POST |
/features/toggle |
Set a per-GSTIN feature flag |
GET |
/operational-matrix |
Feature and permission overview |
GET |
/audit-logs |
Audit trail |
POST |
/audit/log |
Record an audit entry |
GET |
/fiscal-years |
Fiscal calendar |
POST |
/fiscal-years/toggle |
Open or close a year |
POST |
/fiscal-years/seed |
Seed the calendar |
Prefer disabling a user over deleting one. Deletion breaks the attribution of past actions in the audit trail, which a compliance system must preserve.
Assigning roles on a user¶
POST /users and PUT /users/{userId} accept two independent role fields. They are not interchangeable and a user usually needs both.
| Field | Required | Values | Effect |
|---|---|---|---|
role |
Yes on POST, optional on PUT |
org_admin, tax_controller, tax_executive, approver, transport_manager, logistics_operator, external_auditor, super_admin |
The permission set — which endpoints the user may call |
approvalRole |
No | One of the keys from GET /approval-roles, or null to clear |
Which level of a multi-level approval the user occupies |
Both are validated against a server-side allowlist. Two refusals to expect:
| Response | Condition |
|---|---|
403 — Unknown system role: {role}. Valid roles: … |
role is not in the permission matrix. A typo would otherwise create a user with an empty permission set who can sign in and do nothing |
403 — Only a Super Admin may assign the super_admin role |
An org administrator attempted to grant super_admin. That role reaches across tenant boundaries, so granting it is a platform act |
400 — Unknown approval role: {value} |
approvalRole is not in the ladder served by GET /approval-roles |
To clear an approval role, send approvalRole: null (or "") explicitly on PUT. Omitting the field leaves the current value unchanged — the two cases are distinguished deliberately, so an unrelated edit cannot unassign someone.
To let a user approve invoices in production, set both: a role that holds invoice.approve (approver or tax_controller) and an approvalRole naming their level. Setting one without the other is accepted and returns 200, but the user will never be able to complete an approval. Nothing warns you.
POST /api/admin/features/toggle¶
Sets one per-GSTIN feature flag. Requires admin.manage_users.
{ "gstin": "29AAACW3775F000", "featureKey": "IGM_APPROVAL_ENGINE", "value": false }
Most flags are written straight through. IGM_APPROVAL_ENGINE is the exception when the value is falsy, because switching it off changes the fate of documents already in flight rather than only what happens next.
| Response | Condition |
|---|---|
200 |
Written. cancelledApprovals is present only on a forced disable |
409 — APPROVALS_IN_FLIGHT |
Documents still await approval. The body carries open[], one row per blocking document with waitingOn and level |
400 — REASON_REQUIRED |
force: true was sent without a reason |
To force it through, add "force": true and a "reason". That path cancels the open approvals — OVERRIDDEN levels, CANCELLED requests, documents left with no approval decision — and never approves them. See Platform Error Codes.
GET /api/admin/approval-roles¶
The approval ladder an administrator may assign, in seniority order. Requires admin.manage_users. Tenant-independent — the ladder is the same for every organisation.
{
"roles": [
{ "key": "finance_executive", "label": "Finance Executive", "rank": 10 },
{ "key": "finance_manager", "label": "Finance Manager", "rank": 20 },
{ "key": "finance_controller", "label": "Finance Controller", "rank": 30 },
{ "key": "business_head", "label": "Business Head", "rank": 40 },
{ "key": "plant_head", "label": "Plant Head", "rank": 40 },
{ "key": "director", "label": "Director", "rank": 50 },
{ "key": "cfo", "label": "CFO", "rank": 60 }
]
}
rank orders the ladder; equal ranks are peers at the same level, not consecutive steps. Read the list rather than hardcoding it — it is the same allowlist the write endpoints validate against, so a hardcoded copy can only ever go stale.
| Response | Condition |
|---|---|
200 |
Success |
403 |
The caller does not hold admin.manage_users |
Machine credentials¶
Base path /api/admin/api-keys
| Method | Path | Purpose |
|---|---|---|
GET |
/ |
List static keys, without their secrets |
GET |
/connections |
List the OAuth connections — the credentials live integrations actually use |
POST |
/ |
Issue a static key |
PATCH |
/{keyId}/oauth-only |
Require OAuth for this client, or allow its static key again. Reversible |
DELETE |
/{keyId} |
Revoke a static key. Permanent |
A static key's secret is returned once, at issue. It cannot be retrieved afterwards. Capture it into a secret manager in the same operation that creates it — a provisioning script that issues a key and does not store it has created an unusable credential.
GET / returns a computed still_accepted for each key, which answers a different question from is_active: would this key be accepted by the API right now? A key can be dormant in every ordinary sense — unused for months, its ERP long since moved to OAuth — and still authenticate the moment anyone presents it. Use still_accepted, not the active flag, when auditing what is open.
Where a key has been superseded by an OAuth connection, superseded_by names it. A key that is both superseded and still accepted is an open path nobody is watching.
ERP connection onboarding¶
Base path /api/admin/erp-connections. Platform Super Admin only — these routes decide which external directory may post documents into a tenant.
| Method | Path | Purpose |
|---|---|---|
GET |
/ |
Connections at every stage, plus the consent configuration |
POST |
/ |
Create a connection and its first consent link |
POST |
/{id}/consent-link |
Mint a fresh consent link |
PATCH |
/{id}/tenant |
Record the customer's directory ID by hand |
PATCH |
/{id}/client-app |
Record their application ID — this activates the connection |
PATCH |
/{id}/status |
Suspend or resume |
There is one public route, and it is public by necessity:
| Method | Path | Purpose |
|---|---|---|
GET |
/api/erp-consent/callback |
Where Microsoft Entra returns the customer's administrator after consent |
That callback has no session and no bearer token — the person arriving is an administrator at another company who has never signed in. A single-use, short-lived state nonce is the whole control, and it is redeemed once. Do not treat it as an ordinary admin endpoint, and do not put it behind the admin gate: every real customer would be refused.
A connection's status is PENDING_CONSENT, AWAITING_CLIENT, ACTIVE or SUSPENDED. See Machine-to-Machine Authentication for what each stage is waiting on.
Feature configuration¶
| Method | Path | Purpose |
|---|---|---|
POST |
/api/admin/features/toggle |
Enable or disable a feature for a registration |
Features are per registration. A script enabling a module across a group must iterate every registration.
Provider configuration¶
Base path /api/gsp and /api/admin/gsp
| Method | Path | Purpose |
|---|---|---|
GET |
/capabilities |
Capability matrix |
GET |
/capabilities/document |
Capabilities for a specific document, following its provenance |
GET |
/providers |
Known providers |
GET |
/config |
Current assignment |
POST |
/config |
Assign a provider |
DELETE |
/config/{id} |
Remove an assignment |
POST |
/test |
Test the connection |
GET |
/live-documents |
Documents still live against a provider |
live-documents is the endpoint to consult before decommissioning a provider's credentials after a switch. Documents issued by that provider must still be serviceable by it.
Document routing¶
Base path /api/admin/doc-type-routing
| Method | Path | Purpose |
|---|---|---|
GET |
/ |
Current rules |
GET |
/resolve/{docType} |
How a type resolves |
POST |
/ |
Create a company rule (no update; see below) |
DELETE |
/{id} |
Remove a company rule |
These are the only way to manage routing — there is no admin console screen for it, and there is no update operation: changing a route means deleting the company rule and creating it again. Global defaults cannot be deleted. See Document Type Routing.
Write-back operations¶
Base path /api/v1/integration/admin
| Method | Path | Purpose |
|---|---|---|
GET |
/events |
Inspect events |
GET |
/events/{eventPk}/attempts |
Delivery attempt history |
GET |
/requeue/preview |
Preview what a requeue would affect |
POST |
/requeue |
Requeue failed events |
POST |
/events/{eventPk}/replay |
Replay one event |
POST |
/skip |
Skip events deliberately |
Always run the preview before a requeue. A requeue with a wider scope than intended replays a large volume into a consumer that may not be ready for it.
Write-back subscriptions¶
Base path /api/admin/writeback-subscriptions. Platform Super Admin only.
| Method | Path | Purpose |
|---|---|---|
GET |
/ |
Subscriptions, the connections eligible for one, and the emitted event catalogue |
POST |
/ |
Create a subscription for a connection and registration |
PATCH |
/{id}/active |
Pause or resume |
GET / reports which active connections have no subscriber, which is the condition worth acting on: without a subscription, that ERP's documents emit no events at all and nothing errors on either side.
There is deliberately no delete. Pausing stops delivery while events keep accumulating and drain on resume; a deleted row is indistinguishable from one that was never created, which is the state this endpoint exists to make visible.
The event catalogue is served by the API rather than held by any client. A subscription's event filter is an allowlist, so a type missing from a stale local list would silently drop that whole event type for that ERP.
Onboarding¶
Base path /api/admin/onboarding
| Method | Path | Purpose |
|---|---|---|
GET |
/defaults |
Default provisioning settings |
GET |
/companies |
Existing companies |
GET |
/preflight |
Check before provisioning |
POST |
/provision |
Provision a company or registration |
Provisioning creates a tenant boundary, so it is a platform-level act and is restricted accordingly. Run the preflight check first.
Validation¶
| Check | Method | Pass condition |
|---|---|---|
| Administrative authority required | Call with a non-administrative token | Refused |
| User creation works | Create one and sign in as it | Succeeds |
| Credential issue captures the secret | Inspect your provisioning script | The secret is stored at issue |
| Revocation is immediate | Revoke and call an ingest endpoint | Refused |
| Feature toggle applies per registration | Toggle for one registration and check another | Only the intended one changed |
| Provider test works | Run it | Success |
| Live documents checked before decommissioning | Query before withdrawing old credentials | An empty result before withdrawal |
| Requeue previewed | Preview before requeuing | The scope matches expectation |
| Audit entries appear | Perform an administrative action | Recorded with the correct actor |
Troubleshooting¶
| Symptom | Cause | Action |
|---|---|---|
403 on every administrative call |
Token lacks an administrative role | Use an administrative account |
403 Unknown system role when creating a user |
role misspelt or not a real role |
Send one of the eight values listed under Users and access |
403 Only a Super Admin may assign the super_admin role |
An org administrator tried to grant super_admin |
Correct. Escalate to Complifly if a platform-level account is genuinely needed |
| A user was created successfully but cannot approve anything | Only one of role / approvalRole was set |
Both are required. Check the user record and set the missing one |
| Clearing an approval role has no effect | The field was omitted rather than sent as null |
Send approvalRole: null explicitly on PUT |
| A credential is unusable after provisioning | The secret was not captured at issue | Revoke and re-issue, capturing it this time |
| A feature toggle appears not to work | Applied to one registration only, or the brief cache has not expired | Iterate all registrations; wait a minute |
| Cancellations fail after decommissioning a provider | Live documents still existed for it | Restore the credentials; check live-documents before withdrawal |
| A requeue flooded a consumer | Requeued without previewing | Preview first. Pause the consumer before a large replay |
| Audit trail cannot attribute an old action | The user was deleted rather than disabled | Disable, never delete |
| Provisioning fails | Preflight conditions not met | Run the preflight check and resolve what it reports |
| An automation broke after an upgrade | It depends on the console's own endpoints, which follow the interface | Automate provisioning and bulk work only; use the console for occasional administration |
Related Articles¶
- User and Role Administration — the model behind these endpoints
- Roles and Permissions — what each
rolevalue grants - Segregation of Duties — the two role axes and the approval ladder
- Feature Flags — what the toggles control
- GSP Configuration — provider assignment
- Write-back Failures — when to requeue or replay