Skip to main content

Core API

Base URL: https://api.bcmlogic.com/v1/core
Style: RESTful, JSON. Resource-oriented. Plural nouns. Standard HTTP verbs and status codes.
Purpose: Source of truth for all business data in BCMLogic Next.

For guidance on when to call Core API versus Intelligence Service, see The Two-API Model.

Modules

Core API is organised into bounded contexts. Each context owns its resources and its part of the data model.

ModulePath prefixPrimary resources
Continuity/v1/core/continuityprocesses, bia, dr-plans, exercises
ERM/v1/core/ermrisks, kri, controls, assessments
Vendor/v1/core/vendorsvendors, contracts, assessments, incidents
Documents/v1/core/documentsdocuments, versions, attachments
Identity/v1/core/identityusers, roles, groups, tenants
Audit/v1/core/auditevents — read-only
Reports/v1/core/reportsreports, templates — the PDF/DOCX artifacts; generation is via Intelligence Service

Note the split on reports: the report file (PDF, DOCX) lives in Core API because it is an audit-bound artifact; the generation logic lives in Intelligence Service because it uses an LLM. See Intelligence Service → Reports.

Resource Conventions

  • Resources use plural names: /risks, not /risk.
  • Identifiers are opaque ULIDs with type prefixes: rsk_01HQ8K3.... Do not parse or construct them.
  • Timestamps are RFC 3339 in UTC: 2026-05-15T10:30:00Z.
  • Money is represented as { "amount": "1234.56", "currency": "EUR" } — string amount to avoid floating-point errors.
  • Enumerations use snake_case string values, never integers.
  • Boolean fields are prefixed is_, has_, or requires_.

Response Envelopes

Single resource

{
"id": "rsk_01HQ8K3ABCDEF",
"type": "risk",
"attributes": { },
"relationships": { },
"meta": {
"created_at": "2026-05-15T10:30:00Z",
"updated_at": "2026-05-15T10:30:00Z",
"version": 3
}
}

List

{
"data": [
{ "id": "rsk_01HQ8K3ABCDEF", "type": "risk", "attributes": { } }
],
"pagination": {
"next_cursor": "eyJpZCI6...",
"has_more": true,
"page_size": 50
}
}

See Cross-cutting Concerns → Pagination for cursor usage.

Mutations

Writes (POST, PUT, PATCH, DELETE) require:

  1. A valid bearer token — see Authentication.
  2. An Idempotency-Key header — UUID v4 recommended. Repeating a request with the same key within 24 hours returns the original response without re-executing the operation. See ADR-007.
  3. A valid request body — the server validates against JSON Schema. Validation failures return 422 Unprocessable Entity with field-level errors.

Example — create a risk

curl -X POST https://api.bcmlogic.com/v1/core/erm/risks \
-H "Authorization: Bearer eyJhbGc..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"attributes": {
"name": "Concentration risk in cloud provider",
"severity": "high",
"status": "open"
}
}'
const response = await fetch('https://api.bcmlogic.com/v1/core/erm/risks', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
attributes: {
name: 'Concentration risk in cloud provider',
severity: 'high',
status: 'open',
},
}),
});

Optimistic concurrency

To update safely under concurrency, include If-Match: <version> on PATCH and PUT. The server returns 409 Conflict if the version no longer matches.

curl -X PATCH https://api.bcmlogic.com/v1/core/erm/risks/rsk_01HQ8K3ABCDEF \
-H "If-Match: 3" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440001" \
...

Versioning

The API version is in the URL path: /v1/core/.... Breaking changes ship as a new major version: /v2/.... See API Lifecycle for the full versioning and deprecation policy.