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/Concepts/Compliance & regulations

    Compliance & regulations

    A compliance evaluation is a version-pinned execution of every applicable rule — including explicit not-evaluated outcomes. Compliance is a passing result for a named, complete evaluation set. It is not publication, and it is never guessed.

    Fail-closed by design

    • A product with no compliance data scores 0 / Indeterminate, with findings naming exactly what is missing — never FullyCompliant.
    • Unknown means evidence was unavailable or execution failed. It is never synonymous with "safe" or "zero".
    • Sector projectors are exposed per category under /products/{id}/compliance/<sector>/full (ESPR among them), each returning score, status, and findings sourced from the requirements SSOT (obligation IDs ESPR_ART<N>_<TOPIC>).

    Selecting regulations

    POST /api/v2/compliance/regulations/select
    { "context": { "region": "EU", "productCategory": "battery",
                   "lifecycleStage": "production", "effectiveDate": "2026-07-20T00:00:00Z" },
      "minimumPriorityLevel": "HIGH" }
    curl -X POST "$BASE_URL/api/v2/compliance/regulations/select" \
      -d '{
      "context": {
        "region": "EU",
        "productCategory": "battery",
        "lifecycleStage": "production",
        "effectiveDate": "2026-07-20T00:00:00Z"
      },
      "minimumPriorityLevel": "HIGH"
    }'
    const baseUrl = process.env.NORRUVA_BASE_URL;
    
    const res = await fetch(`${baseUrl}/api/v2/compliance/regulations/select`, {
      method: "POST",
      headers: {
    
      },
      body: JSON.stringify({
        "context": {
          "region": "EU",
          "productCategory": "battery",
          "lifecycleStage": "production",
          "effectiveDate": "2026-07-20T00:00:00Z"
        },
        "minimumPriorityLevel": "HIGH"
      })
    });
    
    if (!res.ok) {
      const err = await res.json();      // typed envelope: { error: { code, message, details? } }
      throw new Error(`${res.status} ${err.error?.code}: ${err.error?.message}`);
    }
    const data = await res.json();
    import os, uuid, requests
    
    base_url = os.environ["NORRUVA_BASE_URL"]
    
    resp = requests.post(
        f"{base_url}/api/v2/compliance/regulations/select",
        headers={
    
        },
        json={
          "context": {
            "region": "EU",
            "productCategory": "battery",
            "lifecycleStage": "production",
            "effectiveDate": "2026-07-20T00:00:00Z"
          },
          "minimumPriorityLevel": "HIGH"
        },
    )
    resp.raise_for_status()   # error body is the typed envelope: {"error": {"code", "message", "details"}}
    data = resp.json()
    package main
    
    import (
    	"bytes"
    	"fmt"
    	"net/http"
    	"os"
    )
    
    func main() {
    	baseURL := os.Getenv("NORRUVA_BASE_URL")
    	url := fmt.Sprintf("%s/api/v2/compliance/regulations/select", baseURL)
    
    	payload := []byte(`{
      "context": {
        "region": "EU",
        "productCategory": "battery",
        "lifecycleStage": "production",
        "effectiveDate": "2026-07-20T00:00:00Z"
      },
      "minimumPriorityLevel": "HIGH"
    }`)
    	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
    
    	resp, err := http.DefaultClient.Do(req)
    	if err != nil {
    		panic(err)
    	}
    	defer resp.Body.Close()
    	fmt.Println(resp.Status) // non-2xx bodies use the typed envelope {error:{code,message,details}}
    }

    Regulations are versioned rule packs identified by CELEX id + semver, with an effective/draft/superseded lifecycle. A pack is never edited in place — new versions supersede old ones, which are retained immutably.

    Reserved verdict semantics

    ◆
    Validation chain + ready-to-print (PRD F6): GET /passports/{id}/validations returns the anchored validation chain ({ upi, validations[], readyToPrint }; each entry carries eventId, occurredAt, digest, signatureAlgorithm, jrcAnchor) plus the derived readyToPrint flag = validated ∧ published — true only when at least one validation result is anchored AND the passport is currently published. Publish itself is not validation-gated; treat readyToPrint as the go/no-go signal before printing carriers.
    Was this page helpful?
    Thanks — noted.Feedback goes to the docs team by email.
    ← PreviousDigital Link & resolutionNext →Webhooks & events
    On this page
    Fail-closed by designSelecting regulationsReserved verdict semantics
    Norruva DPP API · sandbox developer docsGenerated 2026-07-29 · PRD-aligned (TSC roadmap rev 2) · statuses reflect E2E-verified sandbox behaviour — not marketing