Skip to main content
    Skip to content
    NorruvaDeveloper Docs
    Sandbox · verified 2026-07-29
    This page
    Whole docs
    Machine formats

    PlaygroundGet API keys
    IntroductionQuickstartAuthenticationErrors & conventionsSandbox & environments
    Entity modelProducts & categoriesPassports & versionsDigital Link & resolutionCompliance & regulationsWebhooks & eventsAutoID print loopImport jobsObservability & audit
    OverviewAuth & API keysProductsCompliance & regulationsPassportsResolver & publicWebhooksPrint jobs & devicesImport / bulkObservabilityBeyond happy path
    Integration playbookWebhook receiver guideRun a print deviceDeviations & gotchas
    EN 18222 API methodsAnnex ZA — ESPR correspondence
    Docs/Playbook/Deviations & gotchas

    Deviations & gotchas

    These are documented as the current contract, not bugs to wait on. Code around them; they will only change with a versioned update.

    Auth & resolution

    1. Resolver 401 to anonymous scanners. GET /api/v2/01/{gtin}/21/{serial} currently returns 401 when no Authorization header is present. Send Authorization: Bearer edge-gate-placeholder until fixed.
    2. publish-dpp returns 403 FORBIDDEN, not API_SCOPE_DENIED, on a missing scope — a different auth wrapper. Branch on both.
    3. Public passport is edge-gated though treated as public; draft/unpublished uids return 404 "not found or not published".
    4. No refresh tokens. OAuth issues access tokens only; request a fresh one on expiry. Cross-tenant token binding fails closed.
    5. POST /compliance/export/evidence-pack is not callable with an API key. It passes its own compliance:view gate, then delegates to a server action wrapped in withAuthentication(), which requires a Supabase user session. An API key has none, so the action throws and the route answers 500 "Authentication required" — not a typed 401/403. Use the dashboard export until the route calls its use case directly. Pinned by the journey probe (Step 14) so the day it starts returning 2xx, the probe fails and this note gets deleted.
    6. The credentials surface spans two scope families that are not aliases. POST /credentials/issue, GET /credentials and POST /credentials/commands are gated on compliance:manage / compliance:view; POST /credentials/verify and POST /credentials/{id}/revoke are gated on credential:verify / credential:manage. The alias table bridges plural and synonym forms within a family (credentials:read → credential:read, credential:manage → credential:write) but never between credential:* and compliance:*. A key minted only from the credential:* family gets 403 API_SCOPE_DENIED on the first three. Mint keys covering both families.

    Data & lifecycle

    1. Category hints can advertise unresolvable categories (e.g. dpp, vehicle) that then 422 SCHEMA_NOT_FOUND. Confirm with a real create.
    2. Compliance is fail-closed: absent data → Indeterminate (score 0), never FullyCompliant. Findings cite obligations from the requirements SSOT (ESPR_ART<N>_<TOPIC>); the bare …/compliance/espr path is a deliberate 410 tombstone — use POST /compliance/validate.
    3. passports/{id}/validations returns the anchored validation chain plus the derived readyToPrint flag (= validated ∧ published). An empty chain just means nothing is anchored yet — readyToPrint stays false until a validation is anchored AND the passport is published.
    4. as-of takes an ISO 8601 date query param and returns the version valid at that instant; a date before the first version is a typed 404 NOT_FOUND, not an empty object.
    5. Product ≠ Passport and publish ≠ register. Registering the resolvable Digital Link is the separate publish-dpp step (dpp_identifiers 0 → 1).
    6. Serial split: alphanumeric serials may yield a valid Digital Link/QR while EPC carrier generation refuses; numeric serials must fit ≤ 238.

    Scope of the current build

    Carrier batch allocation, EPCIS capture, and the print-confirmation loop (carriers/print-status + the carrier.generated / print.confirmed / print.failed events) are live HTTP surfaces. Print-job orchestration and label verification (verify-label) are still missing at the HTTP layer — print execution belongs to the printer partner. Rate limiting is enforced (per-tier budgets, 429 RATE_LIMITED). Check the Beyond happy path reference before depending on anything outside the core journey.

    Was this page helpful?
    Thanks — noted.Feedback goes to the docs team by email.
    ← PreviousRun a print device
    On this page
    Auth & resolutionData & lifecycleScope of the current build
    Norruva DPP API · sandbox developer docsGenerated 2026-07-29 · PRD-aligned (TSC roadmap rev 2) · statuses reflect E2E-verified sandbox behaviour — not marketing