Skip to content

Create a console login certificate request

POST
/api/certs/console
curl --request POST \
--url https://example.com/api/certs/console \
--header 'Content-Type: application/json' \
--data '{}'

Unauthenticated. Returns a short user_code for a human to type into the web UI, the page that accepts it, and expires_at — the deadline the client should bound its own wait by.

Username is the local account being logged into, reported by the caller and used for display and audit only. The certificate’s principals are accounts the approver holds and selects at approval; the module on the host matches them against that local account, directly or through its principals-map. The remaining context fields are equally self-reported and are shown to the approver as claims.

Set cert_options.console.require to restrict who may approve one, and cert_options.console.allowed_networks to refuse creation from outside named networks — that refusal happens here, before any human is asked.

The public key to sign, the local account being logged into, and the console context

Media typeapplication/json
One of:
object

Example generated

{}

Request created

Media typeapplication/json
object
data
required
object
approval_url
required
string
events_url
required
string
expires_at

ExpiresAt is when this request stops being approvable, from its own type’s budget (cert_options..client_timeout, falling back to cert_options.client_timeout). Populated for every type.

A client bounds its wait by this rather than by a local guess, and a console displays the time remaining from it. Without it, the client’s timeout and the server’s budget are two numbers an operator keeps in agreement by hand, and disagreement surfaces as a client still waiting on a request the server already killed. RFC 8628 carries expires_in for the same reason.

string
request_id
required
string
user_code

UserCode is the short code a human types into the web UI, grouped for display (“K7M4-QP2X”). Console requests only; empty for every other type, so no existing consumer changes.

This is the only response it ever appears in. It is not in the SSE stream, not in the request detail, and not in any audit record.

string
verification_url

VerificationURL is the page that accepts UserCode; VerificationURLComplete embeds the code so a device with a camera or a keyboard can skip the code box entirely. Relative, like the two URLs above, and console requests only.

Complete is kept short (/c/, not /approve/) because it is what a QR code drawn in an 80x24 terminal has to encode.

string
verification_url_complete
string
error
string

Example generated

{
"data": {
"approval_url": "example",
"events_url": "example",
"expires_at": "example",
"request_id": "example",
"user_code": "example",
"verification_url": "example",
"verification_url_complete": "example"
},
"error": "example"
}

Malformed body, or a public key that will not parse

Media typeapplication/json
object
data

Data is always null on an error response.

error
required

Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.

string
error_code
required

ErrorCode is a machine-readable error classifier. One of the error_code constants from internal/apitypes; use this to decide whether to retry or branch on the failure mode.

string

Example

{
"error": "certificate request \"9f1c…\" not found",
"error_code": "not_found"
}

The source address is outside cert_options.console.allowed_networks

Media typeapplication/json
object
data

Data is always null on an error response.

error
required

Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.

string
error_code
required

ErrorCode is a machine-readable error classifier. One of the error_code constants from internal/apitypes; use this to decide whether to retry or branch on the failure mode.

string

Example

{
"error": "certificate request \"9f1c…\" not found",
"error_code": "not_found"
}