Appearance
Surfaces
Interactive API Explorer: Explorer
Body Auth Accepted
UTL tenant endpoints accept session_guid in the JSON body. While x-session-guid is the canonical header, body auth is also accepted for UTL tenant routes. This differs from most other org-scoped services which use header-only auth. See /common/headers-identity.html.
The authoritative surface is the OpenAPI spec:
/utl/openapi.yaml
Additional surfaces are available: MCP (/utl/mcp.html) and CLI (g3n utl ...; see cli/README.md).
Surface Types (explicit)
API Gateway
- Status: Available.
- Base:
https://api.g3nretailstack.com/utl - Notes: Primary tenant surface for offboarding/export request flows.
Direct Lambda
- Status: Available (owner + operator).
- Notes: Owner direct flows and operator admin/maintenance Lambdas are IAM-gated.
CLI
- Status: Available.
- Command:
g3n utl ...(API Gateway + direct Lambda). - Notes: See
cli/README.mdfor owner/operator direct commands.
MCP
- Status: Available.
- Canonical protocol:
https://mcp.g3nretailstack.com/utl/PROTOCOL.md - Mirror:
https://doc.g3nretailstack.com/utl/PROTOCOL.md
Auth + tenancy
- API Gateway calls require
x-session-guid(including/stat). - Tenant endpoints require
orgcodein the request body (health checks do not). - Header auth is canonical for
session_guid; body auth is accepted for UTL tenant endpoints. See /common/headers-identity.html.
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)
Headers (canonical)
bash
-H "x-session-guid: $SESSION_GUID"
-H "content-type: application/json"Template
bash
curl -sS -X POST "https://api.g3nretailstack.com/utl/offboarding/status" \
-H "content-type: application/json" \
-H "x-session-guid: $SESSION_GUID" \
-d '{"orgcode":"ORGCODE"}'Notes
- Tenant routes require
orgcodein the JSON body. GET /utl/statis a health check and does not requireorgcode.
Error envelope example (canonical)
json
{
"success": false,
"error": {
"error_code": "utl.invalid_state",
"http_status": 409,
"retryable": false,
"request_id": "req-123",
"trace_id": "trace-abc",
"major": { "tag": "invalid-state", "message": { "en_US": "Export window not open." } },
"details": { "status": "requested" }
},
"build": { "...": "..." },
"stats": { "call": "offboarding/export/start", "service": "utl", "timestamp_utc": "2026-01-26T00:00:00Z", "request_id": "req-123" }
}API Gateway (owner request stage)
GET /utl/stat— health check.POST /utl/offboarding/request— primary owner requests offboarding window (30–90 days out).POST /utl/offboarding/cancel— cancel request until export begins.POST /utl/offboarding/status— owner-visible status + export manifest when available.POST /utl/export/request— owner requests export-only snapshot (no freeze).POST /utl/export/status— export-only status + progress.POST /utl/export/download/start— signed URLs for export artifacts.
Request bodies include orgcode and session_guid (validated via USM).
Direct Lambda (operator + owner)
- Owner direct:
utl_offboarding_request,utl_offboarding_cancel,utl_offboarding_status. - Owner direct (export-only):
utl_export_only_request,utl_export_only_status,utl_export_only_download_start. - Operator approval:
utl_offboarding_request_admin,utl_offboarding_approve. - Window control:
utl_offboarding_window_sweep,utl_offboarding_overdue_sweep. - Export:
utl_offboarding_export_start,utl_offboarding_export_worker,utl_offboarding_export_finalize. - Purge:
utl_offboarding_purge_start,utl_offboarding_purge_worker,utl_offboarding_purge_verify. - Archive:
utl_offboarding_archive_sweep,utl_offboarding_archive_delete. - Restore:
utl_offboarding_archive_restore,utl_offboarding_archive_restore_complete. - Legal hold:
utl_offboarding_legal_hold_set. - Notifications:
utl_offboarding_notification_log(internal logging hook).
Status lifecycle
requested → approved → export_window_open → exporting → exported → purge_pending → purgedexported → archived → archived_deleted(operator-only archive delete)- Archive delete requires purge verification to pass.
archived → archive_restore_pending → archive_restored(operator-only restore flow)requested → canceled(owner-only; only before export begins)
Export artifacts
- Exports are written to S3 under
utl/offboarding/<orgcode>/<request_id>/<run_id>/. - Status response includes
export_manifestand a computedexport_locationprefix when available.
Role requirements (by endpoint family)
- Owner-only: offboarding request/status/cancel.
- Operator-only: approvals, purge, archive/restore, legal hold.
Idempotency & retries
- Offboarding request is not idempotent; use status to confirm before retrying.
- Status polling is safe to retry.
Common pitfalls
- Offboarding blocks writes once the freeze window starts.
- Purge is irreversible and requires operator approval.
Examples (core families)
Offboarding request
json
{ "orgcode": "ORGCODE", "reason": "contract end" }Response (shape):
json
{ "success": true, "data": { "request_id": "REQ_ID", "status": "requested" }, "build": { "...": "..." }, "stats": { "...": "..." } }