Skip to content

IDs, Codes, and Canonicalization ​

This page defines the identifier types used across services, how they are formatted, how they are canonicalized, and how to obtain them. Treat all identifiers as opaque unless a specific rule is documented.

Canonical identifier table ​

IdentifierFormatCanonicalizationUsed inHow to obtain
orgcodeString (org-scoped code)Trim + uppercase (canonical)Headers, OFM, all org-scoped servicesOFM org create → orgcode; OFM resolve (/resolve/orgcode).
org_guidUUID-like stringCase-insensitive; treat as opaqueLegacy OFM identity field (see Naming standard)OFM resolve (/resolve/orgcode).
cccode^[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$UppercaseCost attribution + OFM cost centreOFM cost-centre create/list/resolve.
logical_guidUUID-like stringOpaqueLegacy facility identity field (see Naming standard)OFM logical create/list/resolve.
channel_codeLowercase snake_case (registry)LowercaseSales channel taxonomyOFM sales-channel declaration create/list; registry in OFM.
channel_guidUUID-like stringOpaqueLegacy sales-channel identity field (see Naming standard)OFM sales-channel create/list/resolve.
user_idOpaque stringOpaqueUAS/USM user identityUAS user create/snapshot.
user_guidOpaque stringOpaqueLegacy user identity in OFM edges (see Naming standard)OFM member/resolve; UAS user snapshot (if returned).
style_id / variant_idOpaque stringOpaquePVM styles/variantsPVM create/list/get endpoints.
vendor_id / manufacturer_idOpaque stringOpaquePVM supplier layerPVM vendor/manufacturer create/list/get.
product_idOpaque stringOpaquePMC published product identityPMC publish run outputs; PMC product get/list.
order_idOpaque stringOpaqueSCM ordersSCM order create/get/list.
po_id / receipt_id / invoice_idOpaque stringOpaquePCM procurement lifecyclePCM worksheet/PO/receipt/invoice endpoints.

If a format is UNCONFIRMED, the identifier is still treated as opaque and must be stored/echoed exactly as returned.

Naming standard (preferred going forward) ​

  • Canonical field name: use *_id for opaque record identifiers, even when the underlying value is a GUID/UUID.
  • Legacy *_guid: some existing surfaces still use *_guid as the canonical field name. Do not add *_id aliases and do not return dual fields. Renaming a *_guid field to *_id is a breaking change and must be explicit.
  • Codes remain *_code/orgcode/cccode and are never used as primary record identities.

No migration window: responses must never include both *_id and *_guid for the same record. Each surface exposes exactly one canonical identifier field.

Read-surface policy (anti-enumeration safe) ​

  • Direct GET/UPDATE/STATUS calls: require *_id (GUID/UUID value) and are org-gated. If the caller is not associated with the org, services return 404 to avoid existence leakage.
  • Resolve/lookups: non‑GUID identifiers (codes, barcodes, aliases, emails) are allowed only via explicit resolve or search endpoints, and must still enforce org membership.
  • Exceptions (by design):
    • UAS email subrecords are keyed by email (human identifier) and remain supported.
    • PVM resolve endpoints (barcode/alias/identifier) are required for integrations.
    • MRS container + record_id are string namespaces by contract.

This policy is about minimizing enumeration risk while keeping integration‑friendly resolve endpoints.

Codes vs IDs ​

Some endpoints accept code fields (human-friendly) and some require IDs (opaque):

  • Codes are stable, human-facing identifiers (examples: orgcode, cccode, channel_code, code fields for taxonomy).
  • IDs are opaque record identifiers (*_id, *_guid) returned by create/list/get calls.

Rules:

  • If an endpoint accepts both a code and an ID, they must refer to the same record or the request fails (validation-error or not-found, per service).
  • If you provide the wrong type (code in an ID field), expect validation-error or not-found.

Canonicalization rules (baseline) ​

  • Trim leading/trailing whitespace for all codes.
  • Uppercase: orgcode, cccode, most code fields unless the service explicitly states lowercase.
  • Lowercase: channel_code (registry-defined).
  • Emails: trim + lowercase (UAS/USM).

When in doubt, use the canonical form returned by the service.

How to obtain each ID (quick map) ​

  • Org: POST /ofm/org/create → org_guid, orgcode. Resolve by code: POST /ofm/resolve/orgcode.
  • Facility: POST /ofm/facility/logical/create → logical_guid.
  • Sales channel: POST /ofm/sales-channel/create → channel_guid; channel_code is provided by the caller but validated against the registry.
  • User: POST /uas/user/create (direct Lambda) → user_id; POST /uas/stat (API Gateway) for snapshots.
  • Product model: POST /pvm/style → style_id, POST /pvm/variant → variant_id.
  • Publish: POST /pmc/publish/run/start → run_id and resulting product_id in manifests.

See each service’s Surfaces and Calls pages for concrete examples.