Documentation

API reference

The academy-api HTTP endpoints, generated from the OpenAPI specification.

Generated from the OpenAPI specification (CNCR-IRF academy API 0.1.0). It documents the currently specified endpoints; more are covered by the spec over time.

health

GET/healthz

Liveness probe

Responses
  • 200 The process is up.
GET/readyz

Readiness probe

Responses
  • 200 The process can reach its dependencies.
  • 503 A dependency is not ready.

catalog

GET/api/v1/scenarios

List scenarios

Parameters
  • track in query
  • difficulty in query
  • status in query
Responses
  • 200 A page of scenarios.
  • 400
POST/api/v1/scenarios

Register a new draft scenario

Responses
  • 201 The created scenario.
  • 400
  • 403
GET/api/v1/scenarios/{id}

Get a scenario by id

Parameters
  • in
Responses
  • 200 The scenario.
  • 404
PUT/api/v1/scenarios/{id}

Replace a draft lab's content

Parameters
  • in
Responses
  • 200 The updated scenario.
  • 400
  • 403
  • 404
  • 409
POST/api/v1/scenarios/{id}/validate

Transition a scenario from draft to validated

Parameters
  • in
Responses
  • 200 The updated scenario.
  • 404
  • 409
POST/api/v1/scenarios/{id}/publish

Transition a scenario from validated to published

Parameters
  • in
Responses
  • 200 The updated scenario.
  • 404
  • 409
GET/api/v1/scenarios/{id}/image-source

Where this lab's own image lives

Parameters
  • in
Responses
  • 200 Where the lab's image lives.
  • 404
PUT/api/v1/scenarios/{id}/image-source

Point this lab at an image your organisation hosts

Parameters
  • in
Responses
  • 204 Recorded.
  • 400
  • 403
  • 404
DELETE/api/v1/scenarios/{id}/image-source

Stop using an externally hosted image for this lab

Parameters
  • in
Responses
  • 204 Removed.
  • 404
GET/api/v1/badges/availability

Whether badges can reach anybody for this caller

Responses
  • 200 How far the chain gets.
GET/api/v1/paths/{id}/holders

Who has finished this learning path

Parameters
  • id in path · required
Responses
  • 200 Who has finished it.
  • 404

public

GET/api/v1/public/ctf

List the public competitions

Responses
  • 200 Every public round, open and finished. An empty list is an ordinary answer.
POST/api/v1/public/subscriptions

Ask to hear when the next competition opens

Responses
  • 202 The request is recorded and a confirmation is on its way.
  • 400
POST/api/v1/public/subscriptions/confirm

Confirm a request to hear about competitions

Responses
  • 200 Confirmed.
  • 400
  • 404
POST/api/v1/public/subscriptions/unsubscribe

Leave the list

Responses
  • 204 They are not on the list.
  • 400
GET/api/v1/public/ctf/{id}

Read one public competition

Parameters
  • in
Responses
  • 200 The event.
  • 400
  • 404
POST/api/v1/public/ctf/{id}/entries

Enter a public competition

Parameters
  • in
Responses
  • 202 The entry is recorded and the link is on its way.
  • 400
  • 404
  • 409
GET/api/v1/public/registration

Whether a person may make an account of their own here

Responses
  • 200 Whether the form should be offered, and the texts it must link to.
GET/api/v1/public/registration/challenge

A proof of work for one registration

Responses
  • 200 A challenge. Never cached.
  • 403 Registration is closed on this deployment.
  • 429 Too many challenges from one address this hour.
  • 503 The limits could not be counted, so registration is refused.
POST/api/v1/public/registrations

Register as an organisation of one

Responses
  • 202 The registration is taken and a message is on its way.
  • 400 Not an address, the terms not accepted, or a proof of work that is wrong, expired or already used. The message says which.
  • 403 Registration is closed on this deployment.
  • 409 The terms or the privacy notice changed after the page was opened; the versions sent are not the ones this build serves.
  • 422 The address is at a domain this deployment does not take registrations from (ADR-240), or the intent names a plan not bought on the site (ADR-244). Refused before anything is counted. An intent naming a currency the site does not price in is refused the same way, as 400.
  • 429 Too many registrations from one address this hour.
  • 503 The deployment's hourly cap is reached, or the limits could not be counted.
GET/api/v1/entrant/runs/{id}/artifacts

Download a public competitor's evidence bundle

Parameters
  • id in path · required
Responses
  • 200 The evidence, as a zip.
  • 404
  • 409
GET/api/v1/entrant/runs/{id}/artifacts/manifest

List the files in a public competitor's evidence bundle

Parameters
  • id in path · required
Responses
  • 200 The bundle's files.
  • 404
  • 409

platform

GET/api/v1/status

What works, for the people who use the platform

Responses
  • 200 What works.
  • 503 This deployment records no component health, so nothing can be reported.
GET/api/v1/platform/federations

Who has asked to sign in through their own identity provider

Responses
  • 200 Every organisation's single sign-on request.
  • 403
  • 503 This deployment does not serve the vendor console.
GET/api/v1/platform/clients

Every organisation on this deployment, for the vendor

Responses
  • 200 The deployment's organisations.
  • 503 This deployment does not serve the client list.
POST/api/v1/platform/clients

Take a customer on

Responses
  • 201 The organisation, as the list serves it. Every count is zero.
  • 400 The slug is not a shape this platform and the identity provider can carry, or the name is empty. The message names which.
  • 409 Another organisation already holds that slug. A refusal rather than a resolve-to-the-existing-one: the two are indistinguishable to whoever filled in the form and their consequences are not.
  • 503 This deployment does not manage clients.
GET/api/v1/platform/clients/personal

Personal accounts, a page at a time, for the vendor

Parameters
  • offset in query
  • limit in query
Responses
  • 200 One page of personal accounts.
  • 400 An offset or a limit that is not a page.
  • 503 This deployment does not serve the client list.
PATCH/api/v1/platform/clients/{id}

Correct an organisation's display name

Parameters
  • id in path · required
Responses
  • 204 Renamed.
  • 400 An organisation needs a name.
  • 404
PUT/api/v1/platform/clients/{id}/suspension

Withdraw or restore an organisation's access

Parameters
  • id in path · required
Responses
  • 204 Recorded.
  • 400
  • 503 This deployment does not manage clients.
PUT/api/v1/platform/clients/{id}/subscription

Grant an organisation a plan directly

Parameters
  • id in path · required
Responses
  • 204 Recorded.
  • 400
  • 409 The organisation has a live Stripe subscription. Change the plan in Stripe.
GET/api/v1/platform/subscriptions

What every organisation subscribes to

Responses
  • 200 Every organisation with a subscription recorded.
POST/api/v1/billing/stripe/webhook

Receive a subscription change from Stripe

Parameters
  • Stripe-Signature in header · required · Stripe's timestamp and one or more v1 signatures. More than one appears while the endpoint secret is being rotated, and any match is accepted.
Responses
  • 204 Applied, already applied, superseded by a newer event, about something this platform does not model, or about a subscription that names no plan or no organisation of ours. All are acknowledgements: none of them should be sent again.
  • 400 The signature did not verify, the body is not a Snapshot event (a Thin event is refused naming Snapshot), or a subscription event carries no subscription.
  • 500 The event could not be applied for a reason that might not recur. Stripe should retry.
  • 503 This deployment accepts no Stripe webhooks.
GET/api/v1/platform/health

What each run-mode says about the dependencies it needs

Responses
  • 200 The deployment's component reports.
  • 503 This deployment records no component health, so nothing can be reported. Said rather than answered with an empty report, which would read as a healthy one.
GET/api/v1/platform/range-providers

List the range providers this deployment offers

Responses
  • 200 Every provider the platform knows about.
PUT/api/v1/platform/range-providers/{name}

Switch one range provider on or off

Parameters
  • in
Responses
  • 204 Switched.
  • 400
  • 404
GET/api/v1/platform/cloud-accounts

List the cloud subscriptions this deployment can build in

Responses
  • 200 Every account, retired ones included.
POST/api/v1/platform/cloud-accounts

Add a cloud subscription

Responses
  • 201 The account as recorded.
  • 400
  • 409
PUT/api/v1/platform/cloud-accounts/{id}

Edit a cloud subscription, or retire and reinstate it

Parameters
  • in
Responses
  • 204 Updated.
  • 400
  • 404
  • 409
DELETE/api/v1/platform/cloud-accounts/{id}

Remove a cloud subscription nothing was built in

Parameters
  • in
Responses
  • 204 Removed.
  • 409
GET/api/v1/platform/cloud-estates

List the standing cloud estates

Responses
  • 200 Every estate and the account it lives in, plus the platform modules that have no estate recorded and therefore build in whichever subscription the deployment was started with.
POST/api/v1/platform/cloud-estates

Record an environment built outside the platform

Responses
  • 201 The estate as recorded.
  • 400
  • 409
PUT/api/v1/platform/cloud-estates/{id}

Edit one estate, or mark it standing or taken down

Parameters
  • in
Responses
  • 204 Updated.
  • 400
  • 404
  • 409
DELETE/api/v1/platform/cloud-estates/{id}

Forget an estate recorded by mistake

Parameters
  • in
Responses
  • 204 Forgotten.
  • 404

preferences

GET/api/v1/preferences/

Read the signed-in member's own preferences

Responses
  • 200 The member's preferences, or the unsaved defaults when they have never saved any.
  • 401 Unauthenticated.
PUT/api/v1/preferences/

Save the signed-in member's own preferences

Responses
  • 200 The saved preferences.
  • 400 The body was not valid.
  • 401 Unauthenticated.
GET/api/v1/preferences/organisation

Read what the organisation has chosen for all of its members

Responses
  • 200 The organisation's choices, or the unsaved defaults when it has never chosen.
  • 401 Unauthenticated.
PUT/api/v1/preferences/organisation

Set what the organisation has chosen for all of its members

Responses
  • 200 The saved choices.
  • 400 The body was not valid.
  • 401 Unauthenticated.
  • 403 The caller does not hold the team.manage capability.

billing

The organisation's own plan: what it is on, what is for sale, buying a plan on the site and managing what was bought through Stripe (ADR-232). The platform holds no amount; what the offer shows is read from Stripe when it is asked.

GET/api/v1/public/offer

What is for sale, for somebody with no account

Responses
  • 200 What is for sale, or `available: false` with the sentence that says why nothing is.
  • 429 Too many requests from one place.
GET/api/v1/billing/plan

The caller's organisation's plan

Responses
  • 200 The organisation's plan.
  • 401 Unauthenticated.
GET/api/v1/billing/offer

What is for sale

Responses
  • 200 What is for sale, or why nothing is.
  • 401 Unauthenticated.
POST/api/v1/billing/checkout

Buy a plan on the site

Responses
  • 201 The purchase is recorded and Stripe has a page for it.
  • 400 `startNow` is missing or false, the interval is neither `month` nor `year`, or the currency is neither `eur` nor `usd`.
  • 403 The caller does not hold `billing.manage`.
  • 409 The organisation already holds an entitled plan. The detail says how it is changed: by contact for a plan Invictus set up, through Manage billing for one live through Stripe.
  • 422 The plan is not bought on the site, or it is not sold at that interval (Standard is sold monthly only); the detail names the plan and the interval.
  • 503 Buying a plan is not set up on this deployment, or a price is missing or mislabelled in Stripe.
GET/api/v1/billing/checkout/{sessionId}

Where a purchase stands, on the way back from Stripe

Parameters
  • sessionId in path · required · Stripe's id for the Checkout Session, as the success URL carries it.
Responses
  • 200 Where the purchase stands.
  • 403 The caller does not hold `billing.manage`.
  • 404
  • 503 Buying a plan is not set up on this deployment.
POST/api/v1/billing/portal

Open Stripe's customer portal

Responses
  • 201 Stripe has a portal page for the organisation.
  • 403 The caller does not hold `billing.manage`.
  • 409 Nothing was bought through Stripe, so there is no billing to manage.
  • 503 Buying a plan is not set up on this deployment.
POST/api/v1/billing/intent/take

Take what the person came to buy

Responses
  • 200 The organisation came to buy this.
  • 204 Nothing to send the person to: no intent was kept, it was taken already, the caller may not buy, or the organisation cannot buy now.

federation

Controls belonging to whoever operates the deployment rather than to any organisation on it. Guarded by the platform_admin realm role, never by org_admin: one organisation's administrator must not be able to change what the other twenty-seven can run or where it gets built.

GET/api/v1/tenant/federation

Read the organisation's single sign-on request and whether it works

Responses
  • 200 The organisation's request.
  • 401 Unauthenticated.
  • 404 The organisation has requested no federation.
PUT/api/v1/tenant/federation

Set the organisation's own identity provider up

Responses
  • 200 The recorded request.
  • 400 The request was not valid (kind, alias, endpoint or a domain).
  • 403 The caller does not hold the team.manage capability, or the organisation's plan does not include single sign-on (ADR-223), which the detail names.
DELETE/api/v1/tenant/federation

Withdraw the organisation's request

Responses
  • 204 Withdrawn.
  • 403 The caller does not hold the team.manage capability.
GET/api/v1/tenant/federation/microsoft

Offer to connect a Microsoft directory in one approval

Responses
  • 200 Whether it is on offer, and where the approval happens.
  • 403 The caller does not hold the team.manage capability, or the organisation's plan does not include single sign-on (ADR-223).
POST/api/v1/tenant/federation/microsoft/complete

Record a Microsoft directory that has just approved this platform

Responses
  • 200 The recorded provider, which is being written.
  • 400 The consent was declined, the state was not minted here or has expired, or Microsoft named no usable directory. Nothing was changed.
  • 403 The caller does not hold the team.manage capability, the organisation's plan does not include single sign-on (ADR-223), or the state was minted for a different organisation.
  • 404 This deployment has registered no Microsoft application of its own.
POST/api/v1/tenant/federation/check

Probe the declared provider and report what was found

Responses
  • 200 What the probe found. A reachable provider with no problems is sound.
  • 403 The caller does not hold the team.manage capability, or the organisation's plan does not include single sign-on (ADR-223).
  • 404 The organisation has requested no federation, so there is nothing to check.
GET/api/v1/tenant/domains

List the domains the organisation claims, and which are proven

Responses
  • 200 The claimed domains.
  • 401 Unauthenticated.
POST/api/v1/tenant/domains

Claim a domain and mint its verification challenge

Responses
  • 200 The claim, with the record to publish.
  • 400 The domain was not valid.
  • 403 The caller does not hold the team.manage capability.
DELETE/api/v1/tenant/domains/{domain}

Withdraw a claimed domain

Parameters
  • domain in path · required
Responses
  • 204 Withdrawn.
  • 403 The caller does not hold the team.manage capability.
POST/api/v1/tenant/domains/{domain}/verify

Look for the challenge in the domain's TXT records

Parameters
  • domain in path · required
Responses
  • 200 The domain, verified or not.
  • 403 The caller does not hold the team.manage capability.
  • 404 The organisation has not claimed that domain.

We use only essential and functional cookies to run the platform and remember your settings, with no tracking, analytics, or advertising. See our Cookie Policy.