Jurisdiction rules

Jurisdiction rules add regional content restrictions to your project's policy. Your integration supplies the viewer's country and performs any required age check. Global mandatory rules continue to apply everywhere.

Jurisdictions served

The policy editor shows global rules under Mandatory rules and regional rules under Jurisdiction rules, with a country or European Union badge on each rule. Both groups are read-only.

Select the jurisdictions your project serves in project settings. global always applies and cannot be removed. Other jurisdictions are opt-in. Mandatory rules only raise a decision: a regional age restriction cannot weaken a policy block, and a regional block does not delete content for viewers elsewhere.

Existing assets and rollout

Changing the jurisdictions served starts a background refresh of completed assets that still have stored bytes or extracted text. Existing evidence may already support a newly applicable rule. Otherwise, requests for that jurisdiction are withheld with 403 / asset/regional-evidence-required until usable evidence is available. This is not a finding that the asset is harmful, and it does not turn its base status into a global block.

Before enabling a jurisdiction on a live library, retain the originals you will need, test representative viewer countries, and prepare an unavailable/pending notice during the refresh. Retrieve affected assets with region to check readiness. If classification fails, use processing-failure recovery. Assets whose content was removed are not included in this background refresh: submit a fresh copy from your storage with a new externalId if the existing evidence is insufficient. Do not treat missing evidence as permission to serve your own copy.

Regional content rules

The regional catalogue currently includes:

JurisdictionAdditional outcomeOfficial sources
Germany (DE)Withhold qualifying Nazi symbols and public Holocaust denial, with supported lawful-purpose exceptions.StGB §§86, 86a and 130 .
Austria (AT)Withhold qualifying Nazi symbols and public Holocaust denial; non-promotional pictorial and other statutory exceptions are assessed separately.Abzeichengesetz §§1–2  and Verbotsgesetz §3h .
France (FR)Withhold qualifying public Holocaust denial. A blanket online Nazi-symbol rule is not included.Law of 29 July 1881, Article 24 bis .
United Kingdom (GB)Age-restrict pornographic images and video; your app must confirm a reliable age check.Ofcom: age checks to protect children online .
European Union (EU)Age-restrict pornographic images and video with a reliable age check as an opted-in product standard.European Commission: protection-of-minors guidelines under DSA Article 28 .
Australia (AU)Age-restrict pornographic images and video, qualifying high-impact violent media and material promoting or instructing suicide, self-injury or disordered eating. Your app must confirm a reliable age check.eSafety: Age-Restricted Material Codes .
Brazil (BR)Age-restrict pornographic images and video; your app must confirm a reliable age check.ECA Digital, Law 15,211, Article 9 .

Non-pornographic nudity alone does not activate the pornography rules. A topic mention, recovery or support alone is insufficient for Australia's self-harm rule.

The opted-in EU adult-content rule is a product standard informed by DSA guidance, not a claim that every service has the same legal obligations. This catalogue covers specific content and delivery rules; it does not automate every duty in a jurisdiction. Regional rules can affect custom policies that otherwise allow the material.

Sources checked on 27 October 2026. The linked legislation and regulator guidance describe their own service scope and exceptions; the table describes the controls implemented by CalmLens.

Decisions and precedence

Global matches record decision.source: "mandatory-rule" and the stable decision.rule key. Stricter regional outcomes appear in decision.regions; they do not change the base decision. EU rules apply to viewers in its member states when EU is selected. See Mandatory and regional decisions for the report fields.

The effective action is the strongest of the base decision, the matching country entry and an opted-in EU entry for an EU member. A country entry wins a tie with EU. With no applicable regional entry, use the base decision. A regional block withholds the asset even if the request has a signed URL or API key. A regional age-restrict uses the existing age-restricted delivery opt-in. Global blocks and safety holds still apply everywhere.

Viewer region

Pass optional viewerClaims on the CDN request or SDK media component. The asset API returns the stored classification and policy decisions; it does not return a viewer-specific delivery object, and you do not need an asset lookup before requesting media.

ClaimWhen omittedWhen supplied
viewerClaims.regionCountry inferred from the connection reaching CalmLens.Your viewer's uppercase ISO country code, such as DE or GB. EU is a jurisdiction, not a viewer country.
viewerClaims.ageConfirmedfalse, including requests with API keys or signed URLs.Your application's confirmation that age-restricted content may be delivered.

Claims are customer assertions. CalmLens does not verify physical location, age or the method your application used. Your application chooses how to establish and enforce those facts. Claims do not override blocks, safety holds or private-asset permissions. Passing a country does not enable additional jurisdictions: configure the jurisdictions your project serves first.

SDK media component

import type { Asset } from "@calmlens/sdk/app";
import { CalmLensMedia } from "@calmlens/sdk/react";

// Claims are optional customer assertions evaluated by the CDN.
// ageConfirmed stays false until your app completes the required age check.
export function RegionalPhoto({
  asset,
  region,
  ageConfirmed,
}: {
  asset: Asset;
  region: string;
  ageConfirmed: boolean;
}) {
  return (
    <CalmLensMedia asset={asset} viewerClaims={{ region, ageConfirmed }} alt="Uploaded photo" />
  );
}

Pass viewerClaims directly to the component. Without an explicit region, the CDN infers it when the browser requests the media. A stored base status of allowed can still result in a regional refusal. The component shows its unavailable state if media cannot load; a failed image load alone does not identify the reason. The reveal callback asks your application to decide whether to set viewerClaims.ageConfirmed; it does not set it automatically.

Explain a regional restriction

The stored report's classification.moderation.policy.decision.regions describes recorded regional actions. The CDN evaluates the current asset and project rules for each request, including cache hits. It returns an error rather than restricted media. A proxy or SDK cdn.serve caller can inspect the status and JSON error code; ordinary image elements expose a load failure, not the JSON body.

Error codeMeaning
viewer/invalid-claimsThe supplied claims are malformed, contain an invalid country or a non-boolean age confirmation.
viewer/region-requiredRegional controls apply, but neither an explicit country nor a usable connection country is available.
viewer/age-confirmation-requiredThis content is age-restricted and ageConfirmed is omitted or false.
asset/regional-evidence-requiredThe asset needs classification evidence for an applicable jurisdiction. See Existing assets and rollout.
asset/not-availableDelivery is refused, including regional blocks and other asset restrictions.

Proxies and request country

When the browser requests CalmLens directly, the fallback country comes from its connection. When your backend proxies media, the fallback may identify your backend instead. Forward the country from the incoming viewer request as viewerClaims.region. A VPN can change the visible connection country; CalmLens does not recover physical location behind it. The HTTP Origin header is not used for country detection.

SDK CDN methods accept the claims object. At the HTTP level, send either a JSON-encoded viewerClaims query parameter or the X-CalmLens-Viewer-Claims header containing JSON. The query parameter takes precedence if both are present. Media elements use the URL form; proxies can use the header form.

const response = await fetch(assetRenderedUrl, {
  headers: {
    "X-CalmLens-Viewer-Claims": JSON.stringify({
      region: viewerCountry,
      ageConfirmed: false,
    }),
  },
});
if (!response.ok) return new Response(await response.text(), { status: response.status });
return new Response(response.body, {
  headers: { "Content-Type": response.headers.get("Content-Type") ?? "application/octet-stream", "Cache-Control": "private, no-store" },
});

For an application that never uses age-restricted content, leave age confirmation omitted or explicitly false on every path, including server-side downloads and processing jobs. Authentication does not confirm age.

Signed URLs and caching

Supply viewerClaims when creating a signed URL and forward the returned URL unchanged. Claims are included in its signature; do not append or change them afterwards. Unsigned public requests also accept claims. Signing is an access option, not a requirement for claims.

A proxy cache must not bypass delivery checks. The simplest integration forwards each request to CalmLens and honours its cache headers. A cache separated only by country and age confirmation can still serve stale permissions after moderation or project settings change. Viewer-dependent content responses use private, no-store for downstream caches; CalmLens can reuse its own bytes after checking the current request.

Self-hosted content

If you serve your own bytes, your application must apply the stored base and matching country/EU decisions, plus any age check, before returning them. Base-status webhooks alone do not describe regional eligibility. Subscribe to asset.region-restricted to invalidate recorded decisions, and refresh after project jurisdiction settings change. An event is not an exhaustive access list. Keep delivery unavailable if required classification evidence is missing.

Age-check responsibilities

Your app performs age assurance. Use the age-check standard listed for the applicable jurisdictions above: verified requires a reliable check rather than a self-declared age; any permits your ordinary age check. Apply the stricter standard when both EU and a member country apply, including when the base policy already age-restricts and decision.regions is empty. Set viewerClaims.ageConfirmed: true only after confirming the viewer passed. CalmLens does not receive age-provider results or verify a person's age. See native age checks.

Signing in

Signing out

Cookies on CalmLens

We use essential cookies for sign-in and security. With your permission, functional cookies remember your preferences and Google Analytics measures website use and signups. Optional ad measurement cookies link Google ad clicks to signups. Personalised advertising stays off. Manage cookies