Appearance
Surfaces
Interactive API Explorer: Explorer
Body Auth — Not Header Auth
USM uses body auth: session_guid, api_key, and credentials are passed in the JSON body. Header auth (x-session-guid) is not used, except that POST /usm/api_key/validate accepts x-api-key. This differs from most other services which use header auth. See /common/headers-identity.html.
API Gateway base paths:
- Sessions:
https://api.g3nretailstack.com/usm/session - Service accounts:
https://api.g3nretailstack.com/usm/service_account - API keys:
https://api.g3nretailstack.com/usm/api_key
All requests/JSON responses share the envelope { success, data?, error?, build, stats? } with build ID + UTC timestamp in the footer. Errors carry tags/messages; payloads redact secrets.
Surface Types (explicit)
API Gateway
- Status: Available.
- Base:
https://api.g3nretailstack.com/usm - Notes: All documented USM routes are API Gateway (session/service_account/api_key).
Direct Lambda
- Status: Not offered.
- Notes: No direct Lambda surface is documented for USM.
CLI
- Status: Available.
- Command:
g3n usm ...(API Gateway). - Notes:
--profileis required by policy even though endpoints are public.
MCP
- Status: Available.
- Canonical protocol:
https://mcp.g3nretailstack.com/usm/PROTOCOL.md - Mirror:
https://doc.g3nretailstack.com/usm/PROTOCOL.md
Auth + tenancy
- USM is user/session scoped (no
orgcode). Auth fields live in the JSON body (session_guid,api_key) exceptPOST /usm/api_key/validate, which acceptsx-api-keyin headers. - Header auth is otherwise not required; always send
content-type: application/json.
Identifier policy
- Direct get/update/status calls require GUID/ID fields (
*_idor legacy*_guidwhere that is the canonical field name). Code-based lookups are resolve/search only. - Responses never include both
*_idand*_guidfor the same record (no dual-field output). - Exceptions (email-based UAS, PVM resolve, MRS
container+record_id) are listed in /common/ids-codes.html.
Request builder (API Gateway)
Method posture: POST for all routes (including reads/lists).
Headers (canonical)
bash
-H "content-type: application/json"Auth placement
- Session calls:
session_guidin the JSON body. - API-key management:
api_keyin the JSON body. - Only
POST /usm/api_key/validateacceptsx-api-keyin headers.
Template (session create)
bash
curl -sS -X POST "https://api.g3nretailstack.com/usm/session/create" \
-H "content-type: application/json" \
-d '{"email":"user@example.com","passcode":"Abcd!234","caption":"cli","session_label":"cli"}'Why POST for reads?
USM uses POST for reads/lists to keep credentials out of URLs, support structured JSON filters, and keep auth placement consistent with body-only fields. Treat reads as POST-only (no GET).
Retry guidance (endpoint class)
- Read-ish POSTs (get/list/validate/api_key/validate) are safe to retry with identical inputs.
- Write-ish POSTs (create/close/logout/revoke/policy_set) should only be retried when you can tolerate duplicates or the endpoint documents idempotency.
Public API (API Gateway)
Canonical curl headers
bash
-H "content-type: application/json"USM auth fields live in the JSON body (for example session_guid); the only auth header on this surface is x-api-key for api_key/validate. Method posture: USM uses POST for all routes (including reads/lists). Treat POST as canonical and pass inputs in the JSON body. See /common/http-methods.html.
POST /usm/session/create
- Use when issuing a new session for a verified user/email. Enforces per-user cap (default 1024 or UAS override 32–8192).
- Notes: email inputs are canonicalized (trim + lowercase) before UAS lookups.
- Request
json
{ "email": "user@example.com", "passcode": "Abcd!234", "caption": "iPhone", "session_label": "mobile", "ttl_seconds": 3600, "ttl_refresh_enabled": true, "actor": "ops-user", "reason": "login" }- Success 200
json
{
"success": true,
"data": {
"session_guid": "S123",
"user_id": "U1",
"status": "active",
"expires_at_utc": "2025-12-11T12:00:00.000Z",
"ttl_seconds": 3600,
"ttl_refresh_enabled": true,
"caption": "iPhone",
"label": "mobile"
},
"build": { "...": "..." },
"stats": { "...": "..." }
}- Errors:
validation-error(missing fields),invalid-passcode(401; also used for unknown emails),user-not-verified/email-not-verified(403),too-many-sessions(429),session-cap-invalid(500).
POST /usm/session/validate
- Use when touching a session to refresh sliding TTL.
- Request
json
{ "session_guid": "S123", "actor": "ops-user", "reason": "touch" }- Success 200: returns session; refreshes expiry when
ttl_refresh_enabled=true. - Errors:
session-not-found(404),session-doomed(410),ttl-expired/user-suspended/user-doomed/email-unverified/email-doomed(401).
POST /usm/session/close
- Use when logging out or revoking a session.
- Request
json
{ "session_guid": "S123", "actor": "ops-user", "reason": "logout" }- Success 200:
{ status: "doomed", doom_reason: "closed", doomed_at_utc } - Errors:
session-not-found(404),session-doomed(410).
POST /usm/session/get
- Use when retrieving a specific session, optionally from archive.
- POST read: this is a read endpoint; use POST (no GET).
- Request
json
{ "session_guid": "S123", "include_archived": true, "actor": "ops-user" }- Success 200: returns active/doomed session; if not present and
include_archived=true, returns archived copy when available. - Errors:
validation-error(missing guid),session-not-found(404).
POST /usm/session/list
- Use when paging sessions for the caller (requires an active
session_guid), optionally including archived copies. - POST read: this is a read endpoint; use POST (no GET).
- Request
json
{
"session_guid": "S123",
"status": "active",
"limit": 8,
"next_token": null,
"include_archived": false,
"label_prefix": "mob",
"label_contains": "mobile",
"caption_contains": "iphone",
"since_expires_at_utc": "2025-12-11T00:00:00.000Z",
"until_expires_at_utc": "2025-12-12T00:00:00.000Z",
"actor": "ops-user"
}- Success 200
json
{
"success": true,
"data": {
"sessions": [{ "session_guid": "S123", "user_id": "U1", "status": "active", "expires_at_utc": "2025-12-11T12:00:00.000Z", "ttl_seconds": 3600, "ttl_refresh_enabled": true, "caption": "iPhone", "label": "mobile" }],
"next_token": "eyJHU0kxUEsiOiJVU0VSIy4uLiJ9",
"archived_sessions": [],
"archive_next_token": null
},
"build": { "...": "..." },
"stats": { "...": "..." }
}Role requirements (by endpoint family)
- Session create/validate/get/list: no org roles; credentialed by email+passcode or session.
- Service account + API key management: owner or
service_account_admin(org-bound). - Operator-only: internal audits and admin flows (if documented).
Idempotency & retries
- Session create is not idempotent; retry only after verifying the session was not created.
- Logout/revoke operations are idempotent (repeating yields the same terminal state).
- API key revoke and revoke_all are idempotent (safe to retry).
Common pitfalls
- USM is POST-only, including reads and lists.
- Auth is in the body (not headers) except
api_key/validate. - Sessions are short-lived; handle
ttl-expiredandrevokedas expected outcomes.
Examples (core families)
Create a session
json
{ "email": "user@example.com", "passcode": "Abcd!234", "caption": "web", "session_label": "browser" }Response (shape):
json
{ "success": true, "data": { "session_guid": "S123" }, "build": { "...": "..." }, "stats": { "...": "..." } }Create an API key (service account)
json
{ "service_account_guid": "SVC_GUID", "caption": "Shopify connector", "actor": "owner", "reason": "integration" }Response (shape):
json
{ "success": true, "data": { "api_key": "REDACTED", "api_key_id": "KEY_ID" }, "build": { "...": "..." }, "stats": { "...": "..." } }- Notes: lists only sessions owned by the caller session’s user.
status∈active | doomed | all(defaultactive).limitclamped 1–256.next_token(ornext_token_active/next_token_doomedwhenstatus=all) is opaque; echo verbatim. Filters on label/caption are best-effort.include_archived=truereturns archived sessions witharchive_next_tokenand optionalarchived_since/archived_untilbounds. - Errors:
missing-session/invalid-status(400),session-not-found(404),session-doomed(410),ttl-expired/user-suspended/user-doomed/email-unverified/email-doomed(401).
POST /usm/session/logout_other_devices
- Use when revoking all other sessions for the same user (keep the current session).
- Request
json
{ "session_guid": "S123", "actor": "ops-user", "reason": "security" }- Success 200: sets a per-user
logout_other_devices_before_utcmarker and best-effort dooms other active sessions; sessions created before the marker are rejected onvalidate/listwith reasonrevoked. Returns counts only (no other users’ session GUIDs). - Errors: same session validity errors as
session/list/session/validate(includingrevokedwhen the caller session predates the user revoke marker).
POST /usm/session/logout_everywhere
- Use when revoking all sessions for the same user (including the current session).
- Request
json
{ "session_guid": "S123", "actor": "ops-user", "reason": "compromise suspected" }- Success 200: sets a per-user revoke marker and best-effort dooms active sessions; subsequent
validate/listcalls for older sessions fail withrevoked. - Errors: same session validity errors as
session/list/session/validate.
Service accounts (API Gateway)
Service accounts are org-bound non-human identities (e.g., connectors/automation). They carry a set of roles and own one or more API keys.
Canonical curl headers
bash
-H "content-type: application/json"POST /usm/service_account/create
- Use when creating a service account for an org (requires a valid owner
session_guid; org must beverified). - Request
json
{ "session_guid": "S123", "orgcode": "ACME", "caption": "Shopify connector", "roles": ["pvv","vca"], "actor": "ops-user", "reason": "bootstrap" }- Success 200: returns
service_account_guid,org_guid,roles, timestamps. - Roles: allowed values are
pvv,pma,vca,owner(synonyms are accepted and canonicalized). Unknown roles are rejected.
POST /usm/service_account/list
- Use when listing service accounts for an org (requires owner session).
- POST read: this is a read endpoint; use POST (no GET).
- Request
json
{ "session_guid": "S123", "orgcode": "ACME", "status": "active", "limit": 8, "next_token": null }POST /usm/service_account/status
- Use when dooming a service account (terminal; revokes all API keys).
- Request
json
{ "session_guid": "S123", "orgcode": "ACME", "service_account_guid": "SA1", "status": "doomed", "reason": "revoke" }API keys (API Gateway)
API keys are long-lived credentials owned by a service account. Secrets are returned only once on create; store securely.
Canonical curl headers
bash
-H "content-type: application/json"
-H "x-api-key: $API_KEY" # required for api_key/validate onlyPOST /usm/api_key/create
- Use when creating a new API key for a service account (requires owner session; org must be
verified). - Request
json
{ "session_guid": "S123", "orgcode": "ACME", "service_account_guid": "SA1", "caption": "prod key" }- Success 200: returns
api_key(secret),api_key_id,api_key_fingerprint, timestamps.
POST /usm/api_key/list
- Use when listing API keys for a service account (requires owner session).
- POST read: this is a read endpoint; use POST (no GET).
- Request
json
{ "session_guid": "S123", "orgcode": "ACME", "service_account_guid": "SA1", "status": "active", "limit": 8, "next_token": null }POST /usm/api_key/revoke
- Use when revoking (dooming) a single API key (requires owner session).
- Request
json
{ "session_guid": "S123", "orgcode": "ACME", "api_key_id": "K1", "reason": "rotate" }POST /usm/api_key/revoke_all
- Use when revoking all keys for a service account without dooming the service account (requires owner session).
- Semantics: sets a service-account
revoke_before_utcmarker; keys withcreated_at < revoke_before_utcwill failapi_key/validatewith401even if theirstatusis stillactive. - Request
json
{ "session_guid": "S123", "orgcode": "ACME", "service_account_guid": "SA1", "reason": "compromise suspected" }POST /usm/api_key/revoke_all_org
- Use when revoking all API keys across the org (emergency kill switch; requires owner session).
- Semantics: sets an org-level
revoke_before_utcmarker; all keys in the org withcreated_at < revoke_before_utcwill failapi_key/validatewith401even if theirstatusis stillactive. - Request
json
{ "session_guid": "S123", "orgcode": "ACME", "reason": "org-wide compromise suspected" }POST /usm/api_key/policy_set
- Use when setting org-level API-key expiry policy (requires owner session; org must be
verified). Default is no expiry. - Semantics: when
api_key_max_age_secondsis set, keys withcreated_atolder thannow - api_key_max_age_secondswill failapi_key/validatewith401(invalid-api-key, reasonexpired) even if theirstatusis stillactive. - Request (enable expiry)
json
{ "session_guid": "S123", "orgcode": "ACME", "api_key_max_age_seconds": 7776000, "reason": "90d rotation policy" }- Request (disable expiry)
json
{ "session_guid": "S123", "orgcode": "ACME", "api_key_max_age_seconds": null, "reason": "no-expiry" }POST /usm/api_key/validate
- Use when authenticating as a service account (callers send the secret as header
x-api-key). - POST read: this is a read endpoint; use POST (no GET).
- Request
json
{ "actor": "connector", "reason": "healthcheck" }- Success 200: returns
orgcode,org_status,roles,service_account_guid, andapi_key_fingerprint.
Rules (behavioral)
- Only verified users logging in with a verified email can create sessions.
- Sliding expiry: validate/touch refreshes when
ttl_refresh_enabled=true; otherwise expiry is fixed. Expired sessions doom withttl-expired. - Doom reasons:
ttl-expired,closed,logout-other-devices,logout-everywhere,revoked,user-suspended,user-doomed,email-unverified,email-doomed,manual.doomed_at_utcalways set. - Session cap: default 1024 active per user; per-user override 32–8192 via UAS
userConfigSet. Cap reached →too-many-sessions. - Archival: doomed sessions retained briefly, then archived;
include_archived=trueenables retrieval/listing by guid/user with date bounds.
CLI (API Gateway wrapper)
g3n usm commands call the same API Gateway routes. --profile is required (even though endpoints are public); --base-url overrides the default per command.
Common commands:
g3n usm session-create --email ... --passcode ... [--caption ...] [--session-label ...] [--ttl-seconds ...] [--ttl-refresh-enabled true|false] [--actor ...] [--reason ...] --profile ...g3n usm session-validate --session-guid ... [--actor ...] [--reason ...] --profile ...g3n usm session-close --session-guid ... [--actor ...] [--reason ...] --profile ...g3n usm session-get --session-guid ... [--include-archived] [--actor ...] --profile ...g3n usm session-list --session-guid ... [--status active|doomed|all] [--limit 8] [--next-token ...|--next-token-active ...|--next-token-doomed ...] [--include-archived] [--archive-next-token ...] [--label-prefix ...] [--label-contains ...] [--caption-contains ...] [--since-expires-at-utc ...] [--until-expires-at-utc ...] [--archived-since ...] [--archived-until ...] [--actor ...] --profile ...g3n usm session-logout-other-devices --session-guid ... [--actor ...] [--reason ...] --profile ...g3n usm session-logout-everywhere --session-guid ... [--actor ...] [--reason ...] --profile ...- Service accounts + API keys:
g3n usm service-account-create --orgcode ... --roles pvv vca --session-guid ... [--caption ...] [--actor ...] [--reason ...] --profile ...g3n usm service-account-list --orgcode ... --session-guid ... [--status active|doomed|all] [--limit 8] [--next-token ...] --profile ...g3n usm service-account-doom --orgcode ... --service-account-guid ... --session-guid ... [--reason ...] --profile ...g3n usm api-key-create --orgcode ... --service-account-guid ... --session-guid ... [--caption ...] --profile ...g3n usm api-key-list --orgcode ... --service-account-guid ... --session-guid ... [--status active|doomed|all] [--limit 8] [--next-token ...] --profile ...g3n usm api-key-revoke --orgcode ... --api-key-id ... --session-guid ... [--reason ...] --profile ...g3n usm api-key-revoke-all --orgcode ... --service-account-guid ... --session-guid ... [--reason ...] --profile ...g3n usm api-key-revoke-all-org --orgcode ... --session-guid ... [--reason ...] --profile ...g3n usm api-key-policy-set --orgcode ... --session-guid ... (--api-key-max-age-seconds ... | --clear) [--reason ...] --profile ...g3n usm api-key-validate --api-key ... [--actor ...] [--reason ...] --profile ...
Best practices: reuse the same session_guid downstream, include actor/reason for audit clarity, and copy pagination cursors exactly as returned.
Service-account guidance: create one service account per integration instance, grant only the minimal roles needed (pvv/pma/vca), avoid owner unless it is tightly-controlled internal automation, and use api_key/revoke_all_org (org marker), api_key/revoke_all (service-account marker), or service-account doom as the emergency kill switch.
Error envelope example (canonical)
json
{
"success": false,
"error": {
"error_code": "usm.conflict_revision",
"http_status": 409,
"retryable": false,
"request_id": "req-123",
"trace_id": "trace-abc",
"major": { "tag": "conflict", "message": { "en_US": "Expected revision does not match the current record." } },
"details": { "expected_revision": "3", "current_revision": "4" },
"conflict_snapshot": { "revision": 4 }
},
"build": { "...": "..." },
"stats": { "call": "example", "service": "usm", "timestamp_utc": "2026-01-21T00:00:00Z", "request_id": "req-123" }
}The error block includes the following optional fields (matching the ICS/PPM/SCM canonical pattern):
error_code(string, optional) — machine-readable error code (e.g.usm.conflict_revision).http_status(number, optional) — HTTP status code.retryable(boolean, optional) — whether the caller should retry.request_id(string, optional) — correlation request ID.trace_id(string, optional) — distributed tracing ID.
These fields are present when available; callers should not depend on their presence.