Sandbox

Sandbox mirror of /api/v1/auth/approval-token (API key or sandbox bearer)

Zero-auth deterministic mint of a sandbox-scoped approval token bound to (org_number, action). The returned token is exactly 49 characters: 17-char sandbox-approval- prefix + 32-char lowercase-hex HMAC-SHA-256 suffix. Same input → same token, every time. Production approval-token validators MUST treat any token bearing this prefix as invalid in production code paths.

expires_at is INFORMATIONAL ONLY — sandbox /actions/execute does NOT enforce it against wall-clock time (sandbox is deterministic-by-construction; expires_at is metadata for the agent's UI). Sandbox does not write to the production approval_tokens table — there is no DB row backing the returned token. The token is purely an HMAC-derived string.

The HMAC secret used here is SANDBOX_RECEIPT_HMAC_KEY (env var, REQUIRED when VERCEL_ENV=production; falls back to a known-public dev literal in non-production environments). SANDBOX_RECEIPT_HMAC_KEY is by design fully separable from the production RECEIPT_HMAC_SECRET — sandbox tokens cannot be cross-verified as production receipts and vice versa.

post/api/v1/sandbox/auth/approval-token

Request

  • Base URL: https://www.apier.no
  • URL: https://www.apier.no/api/v1/sandbox/auth/approval-token
  • Auth: one of:
    • HTTP bearer
    • HTTP bearer

Query parameters

simulate_error'missing_delegation' | 'invalid_token' | 'validation_error' | 'scope_missing' | 'altinn_timeout' | 'invalid_certificate' | 'malformed_payload' | 'upstream_5xx' | 'AUTH_MISSING_DELEGATION' | 'AUTH_EXPIRED_TOKEN' | 'VALIDATION_FAILED' | 'SCOPE_MISSING'

Force the sandbox to return a structured error response. tokens (Apier-edge failures) — missing_delegation → 403 AUTH_MISSING_DELEGATION; invalid_token → 401 AUTH_EXPIRED_TOKEN; validation_error → 400 VALIDATION_FAILED; scope_missing → 403 SCOPE_MISSING. upstream-failure tokens — altinn_timeout → 504 EXECUTION_DEADLINE_EXCEEDED (Altinn 3 instances endpoint timed out, response body carries the Altinn RFC 7807 envelope); invalid_certificate → 502 MASKINPORTEN_AUTH_FAILED (Maskinporten OAuth2 error_object — invalid_client); malformed_payload → 422 GOVERNMENT_VALIDATION_REJECTED (Skatteetaten validation errors with nested path[] arrays); upstream_5xx → 502 GOVERNMENT_UNAVAILABLE (generic government 5xx). The 500 INTERNAL_ERROR path is reserved for unexpected internal failures. Accepts BOTH lowercase public tokens (primary contract) AND uppercase internal explainer codes (back-compat). Wins precedence over reserved-org defaults.

Headers

Idempotency-Keystring

Accepted for cross-client header parity with production but NOT enforced (no idempotency cache lookup, no per-key replay binding) — sandbox is deterministic by construction, so the same body always produces the same token regardless of whether an Idempotency-Key was supplied. Charset / length validated at the boundary so a malformed header still 400s before any HMAC computation. Production /v1/auth/approval-token enforces single-use binding via idempotency_keys table; sandbox does not write to that table.

X-Correlation-IDstring uuid

Optional request-scope UUID v4 that the client can set to thread its own trace across multiple requests. A valid UUID v4 is reused verbatim on the server; anything malformed or absent is replaced with a fresh crypto.randomUUID(). The canonical value is echoed back on the X-Correlation-ID response header AND persisted on every matching audit_log row — so a forensic query can reconstruct "every row from request X" without timestamp-based correlation. Accepted on every /api/v1/* operation via the proxy middleware; no per-operation opt-in required. The header is also emitted on every /api/v1/* response — see the X-Correlation-ID response-header component.

Request body

org_numberstring required

9-digit reserved synthetic org. Must appear in the data.sandbox.reserved_test_org_numbers array on the response body of GET /api/v1/capabilities (or 999000901-904 for reserved error orgs). Any other 9-digit value returns 400 VALIDATION_FAILED — distinct from the read-side which 404s on unknown orgs (sandbox write-side invariant).

action'mva_melding' | 'a_melding' required

Closed enum mirroring production /api/v1/actions/execute's ActionTypeEnum.

Response

Token minted. data.approval_token is the 49-char string the agent passes to /api/v1/sandbox/actions/execute via the body's approval_token field.

successunknown required

Changes

No recorded changes to this operation across all 1 revision of this API.