Create a console login certificate request
const url = 'https://example.com/api/certs/console';const options = {method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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.
Request Bodyrequired
Section titled “Request Bodyrequired”The public key to sign, the local account being logged into, and the console context
object
The public key to sign, the local account being logged into, and the console context
object
Same fields, same trust, as PAMRequestBody’s — and they matter more here, because a console certificate authorizes a whole session.
object
Extensions are the SSH certificate extensions requested (e.g. “permit-pty”, “permit-agent-forwarding”).
ForceCommand is the SSH “force-command” critical option request.
NoTouchRequired requests the OpenSSH “no-touch-required” extension. Only meaningful for service enrollment of a hardware-backed sk- key.
SourceAddresses are the caller’s own interface addresses, unioned server-side with the address the request was observed from.
The rest of the host context; see PAMRequestBody for each field.
Example generated
{}Responses
Section titled “Responses”Request created
object
object
ExpiresAt is when this request stops being approvable, from its own
type’s budget (cert_options.
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.
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.
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/
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
object
Data is always null on an error response.
Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.
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.
Example
{ "error": "certificate request \"9f1c…\" not found", "error_code": "not_found"}The source address is outside cert_options.console.allowed_networks
object
Data is always null on an error response.
Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.
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.
Example
{ "error": "certificate request \"9f1c…\" not found", "error_code": "not_found"}