The caller's approved service enrollments
const url = 'https://example.com/api/certs/service/enrollments';const options = {method: 'GET', headers: {'X-Ssoossh-Key-Secret': '<X-Ssoossh-Key-Secret>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://example.com/api/certs/service/enrollments \ --header 'X-Ssoossh-Key-Secret: <X-Ssoossh-Key-Secret>'What each enrollment code will hand out and how long it stays redeemable: the principals and options fixed at approval, the keypair it is bound to, when it was approved, when it stops working, and how often it has been redeemed.
The code itself is never returned. service enroll prints it once, and
a browser session is not a way to mint service certificates.
Scoped by the caller’s users row, with no parameter to widen it.
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Approved enrollments, newest first
object
object
object
ApprovedByUsername is who approved this code. Provenance, not ownership — the reader may well not be them. Empty if that user’s record has since gone.
CertificateRequestID is the request this enrollment was approved from, and the id the retrieval log at /api/certs/requests/{id}/retrievals is keyed on. Omitted for an enrollment with no request linked to it.
CertificateValidSeconds is how long each redeemed certificate is valid for, measured from its own redemption rather than from approval. Omitted for an enrollment created before the code and certificate lifetimes were split, where ExpiresAt bounded both.
CreatedAt is when the enrollment was approved.
ExpiresAt bounds the code, not the certificates it produces: past it
service retrieve stops redeeming, and the unattended job behind it
needs a fresh enrollment.
FirstRedeemedAt is the first successful redemption, absent for a code that has never produced a certificate.
KeyID is likewise fixed at approval and lands verbatim in every certificate, which is what a target host’s logs record.
LastRetrievedAt is the most recent redemption attempt, successful or not. Together with RetrievalCount it is how the approver tells a code still driving a cron job from one nothing has used in months.
NotificationEmail is where notifications about this enrollment go instead of to every holder of the service account. Empty means they fan out, which is the default. Any holder may change it.
Options are the certificate options fixed at approval, already narrowed by server config: what a redemption actually grants, not what the client asked for.
object
Principals is what every certificate this code produces carries. For a service enrollment that is the single service account the approver picked, fixed at approval time and never re-derived at redemption.
PublicKeyFingerprint identifies the keypair the code is bound to.
service retrieve never sends a public key, so a code lifted without
this keypair produces nothing usable.
Empty if the stored key could not be parsed — a display gap, not a reason to withhold the rest of the row.
RetrievalCount counts every logged redemption attempt, including those that failed at signing — someone held the code either way.
ServiceAccount is the account this code was approved for, and who owns it: everyone holding the account (see https://mnestor.github.io/ssoossh/concepts/service-certificates/). It is what the service codes page groups by, which is why it is its own field rather than left to be read out of Principals.
ExpiringSoonSeconds is how far ahead of a code’s expiry the page calls it expiring soon: mail.expiry_reminder_lead, so the page and the first reminder mail agree, or a week when that is zero.
Example generated
{ "data": { "enrollments": [ { "approved_by_username": "example", "certificate_request_id": "example", "certificate_valid_seconds": 1, "created_at": "example", "expires_at": "example", "first_redeemed_at": "example", "id": "example", "key_id": "example", "last_retrieved_at": "example", "notification_email": "example", "options": { "extensions": [ "example" ], "force_command": "example", "no_touch_required": true, "source_addresses": [ "example" ] }, "principals": [ "example" ], "public_key_fingerprint": "example", "retrieval_count": 1, "service_account": "example" } ], "expiring_soon_seconds": 1 }, "error": "example"}No valid session
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"}