Developer Docs
Sandbox · API v2PlaygroundGet API keys

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: 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.