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/createorg_guid, orgcode. Resolve by code: POST /ofm/resolve/orgcode.
  • Facility: POST /ofm/facility/logical/createlogical_guid.
  • Sales channel: POST /ofm/sales-channel/createchannel_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/stylestyle_id, POST /pvm/variantvariant_id.
  • Publish: POST /pmc/publish/run/startrun_id and resulting product_id in manifests.

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