Skip to content
Apier

Apier.no

Sandbox

A permanent, no-signup test surface that mirrors the production request and response shapes against deterministic synthetic data — and never calls a government system. Use it to rehearse the full authenticated flow, including failures, before you go live. There are two ways in.

How to use the sandbox

1 · Public, zero-auth

The public mirror (/api/v1/sandbox/public/*) needs no key at all and serves org 999999999. Best for a first look at the response shapes.

2 · No-signup synthetic bearer

Pass Authorization: Bearer apier_sandbox_test_<uuid> to reach the eight non-public routes and the richer fixtures. The <uuid> suffix is your private, isolated session namespace — generate a fresh one per agent or run.

Every response is tagged _meta.is_sandbox: true. You can shape behaviour with deterministic knobs — ?simulate_error= for the eight failure modes, ?simulate_latency= to pause a response, and ?mock_date= to pin the clock — and force filing outcomes with magic payload values. Every synthetic org, token, knob, and magic value lives in the fixtures reference.

Synthetic test org numbers

Paste any of these into live Apier.no calls. The 999xxxxxxx range is reserved for synthetic testing and 123456789 is the docs-standard mock used across the OpenAPI manifest and capability examples. For the full sandbox fixture catalogue — reserved test orgs, the realistic graph, reserved error orgs, and more — see the fixtures reference.

Org numberNameEntityData tierScenario
999111114Synthetic AS with Full DelegationAStier_1+2AS with full Tier 2 delegation
999222226Synthetic ENK Sole ProprietorENKtier_1ENK sole proprietor, no employees
999333338Synthetic DA PartnershipDAtier_1DA partnership (delt ansvar)
123456789Docs-standard mock orgNUFtier_1NUF (foreign branch)
999444008Sandbox unknown-org placeholderAStier_1sandbox-unknown-org

Magic state fixtures

Eight reserved org numbers, each one deterministically returning a single documented company state on the authenticated read surface — the regulatory edge cases an agent must learn to handle. Pass the no-signup synthetic bearer and hit /api/v1/sandbox/company/<org>/verify (or /authority, /obligations). This table is generated from the same source as GET /api/v1/sandbox/fixtures.

Org numberStateEntity/verify/authorityMVAObligations
999660010Bankrupt (konkurs)ASfailsoleyesnone (company is bankrupt)
999660029Struck from register (slettet)ASfailsolenonone (company is deleted)
999660037Forced liquidation (tvangsavvikling)ASfailsoleyesnone (company is in forced liquidation)
999660045No registered rolesASwarnno_authorityyesMVA-melding (bimonthly)
999660053Not VAT-registeredASpasssolenonone (not MVA-registered)
999660061Enkeltpersonforetak (ENK)ENKpasssolenoSkattemelding for næringsdrivende (annual)
999660088Aksjeselskap (AS)ASpasssoleyesMVA-melding (bimonthly)
999660096Registered <30 days agoASpasssoleyesMVA-melding (bimonthly)

Try it — public endpoints

Zero-auth, permanently rate-limited per-IP at 1000 req/min (Category A). Every cURL runs against the live production API.

Norwegian business deadlines for a given calendar year

GET /api/v1/public/deadlines

Request
curl https://www.apier.no/api/v1/public/deadlines?year=2026
Response
{
  "success": true,
  "data": {
    "year": 2026,
    "deadlines": [
      {
        "obligation_id": "mva-termin-1-2026",
        "obligation_name": "MVA-melding, 1. termin 2026",
        "period": "Januar–februar 2026",
        "deadline": "2026-04-10T23:59:59+02:00",
        "submission_window_closes": "2026-04-10T23:59:59+02:00",
        "timezone": "Europe/Oslo",
        "adjusted_from": null,
        "legal_reference": "Skatteforvaltningsloven § 8-3",
        "applies_to_entity_types": ["AS", "ENK", "ANS", "DA", "NUF"]
      },
      {
        "obligation_id": "amelding-2026-05",
        "obligation_name": "A-melding — mai 2026",
        "period": "Mai 2026",
        "deadline": "2026-06-05T23:59:59+02:00",
        "submission_window_closes": "2026-06-05T23:59:59+02:00",
        "timezone": "Europe/Oslo",
        "adjusted_from": null,
        "legal_reference": "A-opplysningsloven § 3",
        "applies_to_entity_types": ["AS", "ENK", "ANS", "DA", "NUF"]
      }
    ]
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-04-21T00:00:00.000Z",
    "last_verified": "2026-04-21T00:00:00.000Z",
    "source": "apier.no",
    "data_source": "Apier Universal Rulebook",
    "legal_basis": "NLOD — public registry reuse",
    "schema_version": "1.0.0"
  }
}

Every deadline is ISO 8601 with the Europe/Oslo offset baked in. `adjusted_from` is non-null when the legal date fell on a weekend or holiday — agents do not need to reimplement Oslo business-day math.

Generic Norwegian business obligations by entity type

GET /api/v1/public/obligations

Request
curl https://www.apier.no/api/v1/public/obligations?entity_type=AS
Response
{
  "success": true,
  "data": {
    "entity_type": "AS",
    "obligations": [
      {
        "obligation_id": "mva-registration",
        "obligation_name": "Registrering i Merverdiavgiftsregisteret",
        "category": "registration",
        "frequency": "one-time",
        "required": "conditionally",
        "condition": "Påkrevd når samlet omsetning overstiger 50 000 NOK i en 12-måneders periode.",
        "tier_2_required": true,
        "legal_reference": "Merverdiavgiftsloven § 2-1",
        "source_url": "https://lovdata.no/lov/2009-06-19-58/%C2%A72-1"
      },
      {
        "obligation_id": "skattemelding-annual",
        "obligation_name": "Skattemelding for formues- og inntektsskatt",
        "category": "tax",
        "frequency": "annual",
        "required": "always",
        "condition": null,
        "tier_2_required": false,
        "legal_reference": "Skatteforvaltningsloven § 8-2",
        "source_url": "https://lovdata.no/lov/2016-05-27-14/%C2%A78-2"
      }
    ],
    "notes": []
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-04-21T00:00:00.000Z",
    "last_verified": "2026-04-21T00:00:00.000Z",
    "source": "apier.no",
    "data_source": "Apier Universal Rulebook",
    "legal_basis": "NLOD — public registry reuse",
    "schema_version": "1.0.0"
  }
}

`tier_2_required: true` marks obligations that need a Tier 2 delegation before producing a company-specific verdict. Without delegation the `/company/*` endpoints return `insufficient_data` with an `upgrade_path`.

Official Norges Bank NOK exchange rate for a currency and date

GET /api/v1/tools/exchange-rate

Request
curl 'https://www.apier.no/api/v1/tools/exchange-rate?currency=EUR&date=2026-04-10'
Response
{
  "success": true,
  "data": {
    "base": "NOK",
    "quote": "EUR",
    "rate": 11.5234,
    "date": "2026-04-10",
    "requested_date": "2026-04-10",
    "source": "Norges Bank",
    "cached": false
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-04-10T00:00:00.000Z",
    "last_verified": "2026-04-10T16:00:00.000Z",
    "source": "apier.no",
    "served_from": "live",
    "schema_version": "1.0.0"
  }
}

`date` is the actual publication day Norges Bank resolved the rate from — on weekends/holidays it falls back to the previous banking day and `requested_date` records what you originally asked for.

Altinn 2 → Altinn 3 migration map

GET /api/v1/tools/altinn-migration

Request
curl https://www.apier.no/api/v1/tools/altinn-migration?altinn2_code=A0208
Response
{
  "success": true,
  "data": {
    "deprecation_deadline": "2026-06-19T23:59:59+02:00",
    "timezone": "Europe/Oslo",
    "days_remaining": 57,
    "deadline_passed": false,
    "entry": {
      "altinn2_code": "A0208",
      "altinn2_name": "A-melding",
      "altinn3_resource": "altinn:serviceowner:skatteetaten:a-melding",
      "verified": true,
      "migration_notes": "A-melding consumed via the Altinn 3 resource model. Requires a System User delegation with scope altinn:accessmanagement/authorizedparties.read.",
      "last_verified_against_digdir": "2026-04-15"
    }
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-04-15T00:00:00.000Z",
    "last_verified": "2026-04-15T00:00:00.000Z",
    "source": "apier.no",
    "schema_version": "1.0.0"
  }
}

Omit `altinn2_code` to receive the full `mappings` array. The `deadline_passed` flag flips to `true` at 2026-06-19T23:59:59+02:00 Europe/Oslo — agents should branch on the boolean, not reimplement the date math.

Machine-readable capability manifest (agent discovery)

GET /api/v1/capabilities

Request
curl https://www.apier.no/api/v1/capabilities
Response
{
  "success": true,
  "data": {
    "service": "apier.no",
    "version": "1",
    "rulebook_version": "1.0.0",
    "locale": "nb-NO",
    "capabilities": [
      {
        "id": "public.obligations",
        "name_en": "Generic obligations by Norwegian entity type",
        "endpoint": { "method": "GET", "path": "/api/v1/public/obligations" },
        "auth": "none",
        "tier_minimum": null,
        "category": "public-tool",
        "openapi_operation_id": "getPublicObligations",
        "example_request": "GET /api/v1/public/obligations?entity_type=AS",
        "data_sources": ["internal-static"],
        "freshness": "static"
      },
      {
        "id": "auth.permissions",
        "name_en": "Check delegation status for an organisation",
        "endpoint": { "method": "GET", "path": "/api/v1/auth/permissions/{org}" },
        "auth": "api_key",
        "tier_minimum": "free",
        "category": "auth",
        "openapi_operation_id": "getPermissionState",
        "example_request": "curl -H 'Authorization: Bearer <API_KEY>' https://www.apier.no/api/v1/auth/permissions/999111114",
        "data_sources": ["altinn", "internal-supabase"],
        "freshness": "live"
      }
    ]
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-04-20T00:00:00.000Z",
    "last_verified": "2026-04-20T00:00:00.000Z",
    "source": "apier.no",
    "schema_version": "1.0.0"
  }
}

Every authenticated surface is listed with its `auth`, `tier_minimum`, and OpenAPI operation id. Parse this instead of hard-coding endpoint lists in agent prompts.

Qualitative Apier-vs-direct-integration comparison

GET /api/v1/comparison/direct-integration

Request
curl https://www.apier.no/api/v1/comparison/direct-integration
Response
{
  "success": true,
  "data": {
    "dimensions": [
      {
        "dimension": "authentication",
        "apier": "Consumers authenticate with an API key over HTTPS; Maskinporten client registration, key management, and machine-to-machine token exchange against government endpoints are operated by Apier.",
        "direct_integration": "The integrator registers their own Maskinporten client, manages an asymmetric key pair, and implements the signed-JWT token exchange for each government scope they need."
      },
      {
        "dimension": "delegation_and_authority",
        "apier": "Registered signature and prokura roles from the Brønnøysund registers and Altinn delegation state are exposed through normalised endpoints with a single response envelope.",
        "direct_integration": "The integrator queries the Brønnøysund role registers and the Altinn delegation APIs separately and combines the results themselves."
      },
      {
        "dimension": "audit_trail",
        "apier": "API activity is recorded in an append-only audit log, and every response carries provenance metadata (response hash and wire timestamp) for later reconstruction.",
        "direct_integration": "Consumer-side audit logging is the integrator's responsibility; the government APIs do not provide one on the caller's behalf."
      },
      {
        "dimension": "legal_grounding",
        "apier": "Obligation and deadline answers are produced by a versioned rulebook whose rules carry references to the underlying regulations, and responses state which rulebook version produced them.",
        "direct_integration": "The integrator maps regulations to API behaviour themselves and tracks regulatory changes on their own."
      },
      {
        "dimension": "error_handling",
        "apier": "Upstream errors are normalised to one structured error format with machine-readable codes, an explanation, and remediation steps.",
        "direct_integration": "Each government API surfaces its own error format; the integrator implements per-API error mapping and retry handling."
      },
      {
        "dimension": "deadline_intelligence",
        "apier": "Regulatory deadlines are computed in Europe/Oslo time with weekend and Norwegian public-holiday adjustment, versioned by the rulebook.",
        "direct_integration": "Deadline rules must be implemented and maintained by the integrator from the published regulations; the government APIs do not compute them."
      },
      {
        "dimension": "cross_agency_orchestration",
        "apier": "One API surface spans Brønnøysund, Altinn, Skatteetaten, and NAV data behind a common envelope and a single authentication model.",
        "direct_integration": "Each agency is a separate integration with its own authentication, schemas, and lifecycle."
      },
      {
        "dimension": "maintenance_burden",
        "apier": "Upstream schema and policy changes are monitored by Apier and surfaced through an append-only change archive; the consumer response contract is append-only.",
        "direct_integration": "The integrator monitors each agency's changelogs and migration timelines (for example the Altinn 2 to Altinn 3 transition) and updates their integration accordingly."
      },
      {
        "dimension": "time_to_first_call",
        "apier": "Public endpoints and a zero-auth sandbox work without any government onboarding; company-data endpoints require an API key only.",
        "direct_integration": "A first production call requires Maskinporten client registration plus the relevant government scope or delegation grants before any data is returned."
      }
    ],
    "methodology": "Qualitative comparison based on Apier product documentation and the publicly documented integration requirements for the Norwegian government APIs (Maskinporten, Altinn, Brønnøysund Register Centre, Skatteetaten). Quantitative performance claims (success rates, latency) are intentionally omitted until they can be backed by measured live telemetry.",
    "source": [
      "Apier product documentation and OpenAPI specification",
      "Public Norwegian government integration documentation (Digdir/Maskinporten, Altinn, Brønnøysund Register Centre, Skatteetaten)"
    ],
    "last_updated": "2026-06-12T00:00:00.000Z"
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-06-12T00:00:00.000Z",
    "last_verified": "2026-06-12T00:00:00.000Z",
    "source": "apier.no internal comparison",
    "served_from": "static",
    "schema_version": "2.0.0"
  }
}

Designed to be parsed, not rendered — each dimension carries one factual statement per column so agents can weigh Apier against building the direct integration at planning time. The methodology and source fields state the comparison basis on the wire.

Rehearse the full MVA write loop

The five steps a binding VAT filing goes through, run for real against your own account: validate (production dry-run), stage (a real 412 human-in-the-loop suspension), approve (a real single-use token), execute (mock receipt — the submitter is hardcoded to mock, so no government system can ever be reached), and inspect the append-only audit evidence. Every response below is rendered verbatim — including the error responses, which are part of the loop's guarantees.

Before you start

You need a real Apier API key — the no-signup synthetic bearer cannot drive this loop, because every step writes real rows (pending action, token consume, audit trail, signed receipt) keyed to your account. The default key from signup carries the read:* wildcard, which grants all three scopes the loop touches: read:actions (steps 1, 2, 4), read:altinn (step 3) and read:audit (step 5). Nothing here can reach a government system: the rehearsal endpoint hardcodes the mock submitter.

1 · Validate — production dry-run

Runs the real five-check precondition engine (company exists, delegation active, scopes delegated, data format, deadline) without submitting anything. 200 is the success path even when checks fail — verdicts are content. With the synthetic org 999999999 expect company_exists: false; the loop continues regardless: steps 2–5 rehearse the write mechanics, not the precondition verdicts.

Paste your API key above first.

curl -X POST 'https://www.apier.no/api/v1/actions/execute?dry_run=true' \
  -H "Authorization: Bearer $APIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "org_number": "999999999",
  "action_type": "mva_melding",
  "period": "2026-T3",
  "payload": {
    "total_revenue_nok": "500000.00",
    "total_outgoing_vat_nok": "125000.00",
    "total_incoming_vat_nok": "25000.00"
  }
}'

2 · Stage — rehearsal execute, no token → 412

Calls the rehearsal endpoint WITHOUT an approval token. The action is staged as a REAL pending_actions row (15-minute TTL) and suspended with 412 HITL_PENDING_APPROVAL. Re-running this step reuses the same Idempotency-Key — the cached 412 replays with the SAME pending_action_id (the Rule 5 replay guarantee, live).

Paste your API key above first.

curl -i -X POST 'https://www.apier.no/api/v1/sandbox/rehearsal/execute' \
  -H "Authorization: Bearer $APIER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "org_number": "999999999",
  "action_type": "mva_melding",
  "period": "2026-T3",
  "payload": {
    "total_revenue_nok": "500000.00",
    "total_outgoing_vat_nok": "125000.00",
    "total_incoming_vat_nok": "25000.00"
  }
}'

3 · Approve — mint a one-time approval token

Mints a real single-use approval token bound to (org_number, filing.submit) via the production endpoint. The plaintext is shown ONCE below — only its SHA-256 hash is stored server-side. In production, a human operator performs this step; the approval_url in step 2's response is the production approval surface.

Paste your API key above first.

curl -X POST 'https://www.apier.no/api/v1/auth/approval-token' \
  -H "Authorization: Bearer $APIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"org_number": "999999999", "action_id": "filing.submit"}'

4 · Execute — re-send with X-Approval-Token → mock receipt

Re-sends the same request WITH the token and a NEW Idempotency-Key. The token is consumed exactly-once through the atomic CAS — then the HARDCODED mock submitter produces a receipt (MOCK-ALT-… id, government_response_raw._mock: true), HMAC-signed and persisted. No government system is ever called from this surface. Re-running with the same token shows the real APPROVAL_TOKEN_USED rejection — single-use, demonstrated live.

Run step 3 to mint a token first.

curl -X POST 'https://www.apier.no/api/v1/sandbox/rehearsal/execute' \
  -H "Authorization: Bearer $APIER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Approval-Token: $APPROVAL_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "org_number": "999999999",
  "action_type": "mva_melding",
  "period": "2026-T3",
  "payload": {
    "total_revenue_nok": "500000.00",
    "total_outgoing_vat_nok": "125000.00",
    "total_incoming_vat_nok": "25000.00"
  }
}'

5 · Evidence — pending-action status + audit chain

Reads the staged pending action via the production status endpoint. On the token path the pending row is not flipped — the consumed token plus the audit rows ARE the authorization record, and the row lapses to EXPIRED after its 15-minute TTL (production semantics, mirrored exactly). The receipt from step 4 embeds audit_log_id and correlation_id — the keys into the append-only audit_log evidence.

Run step 2 to stage an action first.

curl 'https://www.apier.no/api/v1/actions/pending/$PENDING_ACTION_ID' \
  -H "Authorization: Bearer $APIER_API_KEY"

Sandbox test checklist

The end-to-end sandbox rehearsal, as a check-off list — from fetching the fixtures table to injecting an infrastructure failure and time-traveling a deadline. Check-off state is in-page only and resets on reload.

0 / 7 done