API
Alt som kan gjøres i panelet kan gjøres via API-et. Oppslagssiden i panelet bruker de samme endepunktene. API-nøkler lages under API i panelet og krever Senter-pakken eller større.
Autentisering
Send nøkkelen som Bearer-token. Kall går mot virksomhetens egen adresse, eller mot hvilken som helst adresse under declarely.app; nøkkelen avgjør hvilken virksomhet det gjelder.
curl "https://<slug>.declarely.app/api/v1/lookup?phone=%2B4791234567" \ -H "Authorization: Bearer dk_live_…"
Nøkler har rettighetene read og/eller write. Alle svar er JSON. Feil returnerer { error, message, details? } med passende HTTP-status.
Endepunkter
/api/v1/lookup?phone=+4791234567scope: readSjekk om et telefonnummer har en gyldig erklæring. Nummeret kan skrives med eller uten landskode; norske numre er standard.
Svar
{
"phone": "+4791234567",
"found": true,
"declaration": {
"id": "…", "fullName": "Kari Nordmann", "firstName": "Kari",
"birthDate": "1988-03-14", "phone": "+4791234567", "email": "kari@example.com",
"signedAt": "2026-09-05T10:12:00Z", "expiresAt": "2027-09-05T10:12:00Z",
"locale": "nb", "source": "kiosk",
"children": [{ "id": "…", "fullName": "Ola Nordmann", "birthDate": "2016-05-01", "signedAt": "…" }]
}
}/api/v1/declarations?query=&page=1&page_size=25&include_expired=false&since=scope: readListe over erklæringer, nyeste først. query matcher telefon, navn eller e-post. since er et ISO-tidspunkt.
Svar
{ "items": [ … ], "total": 128, "page": 1, "pageSize": 25 }/api/v1/declarations/{id}scope: readÉn erklæring med barn, IP-adresse og nettleser.
/api/v1/declarationsscope: writeRegistrer en erklæring på vegne av en gjest. Samme felter som skjemaet. termsVersionId må være gjeldende publiserte versjon (se /terms). accepted må være true.
Body
{
"phone": "912 34 567",
"birthDate": "1988-03-14",
"fullName": "Kari Nordmann",
"email": "kari@example.com",
"locale": "nb",
"termsVersionId": "…",
"accepted": true,
"children": [{ "fullName": "Ola Nordmann", "birthDate": "2016-05-01" }],
"childrenConfirmed": true
}Svar
201 { "declaration": { … } }/api/v1/declarations/{id}scope: writeTrekk tilbake en erklæring. Raden beholdes til utløp for sporbarhet, men regnes som ugyldig.
/api/v1/terms?locale=nbscope: readGjeldende publiserte vilkår i ønsket språk, med versjons-ID til bruk ved registrering.
/api/v1/tenantscope: readInnstillinger, pakke, abonnementsstatus og bruk.
/api/v1/statsscope: readTall for dashbord: aktive, signert siste 7 og 30 dager, utløper neste 30 dager, barn, kilder.
/api/v1/passes/scanscope: readKrever kortmodulen. Løs inn QR-koden fra gjestens telefon: { token }. Svaret gir korthavere, kort med saldo og gyldige egenerklæringer i ett kall. Endrer ingenting - trekk skjer med /passes/use.
/api/v1/passes/lookup?phone=%2B4791234567scope: readSamme svar som skanning, men fra telefonnummer. Reserveløsningen når QR-koden ikke lar seg lese.
/api/v1/passes/card?uid=04A23B5Cscope: readSlå opp et fysisk kort - brikken, armbåndet eller plastkortet gjesten legger på NFC/RFID-leseren. Samme svar som skanning, med scannedPassId som peker på kortet brikken hører til. Skilletegn og små bokstaver spiller ingen rolle; 404 card_unknown betyr at brikken ikke er registrert hos dere.
/api/v1/passes/usescope: writeTrekk gavekortsaldo eller klipp, eller registrer årskortbesøk. Års- og klippekort bruker { passId, quantity, idempotencyKey }. Gavekort bruker { passId, amountMinor, externalRef?, idempotencyKey }. Beløpet er i øre. Samme idempotencyKey to ganger trekker bare én gang.
/api/v1/passes/reversescope: writeAngre et trekk eller et besøk: { eventId }. Klippene kommer tilbake, og angringen blir stående i historikken. Svarer som /use med 200 og ok:false dersom hendelsen allerede er angret (already_reversed) eller ikke kan angres (not_reversible).
/api/v1/passes?query=&kind=&page=1&page_size=25scope: readKort for virksomheten, nyeste først. query treffer navn, eget eller foresatts telefonnummer, kortnummer eller fysisk brikkenummer. Treffer på en voksen tar også med barnas kort. Sidestørrelsen er 25 som standard og maks 100, så en full eksport må bla med page.
Feilkoder
| invalid_phone | Telefonnummeret kunne ikke tolkes. |
| too_young | Gjesten er under minstealderen. details.minAge. |
| email_required | Virksomheten krever e-post. |
| child_too_old | Et barn er 18 år eller eldre og må signere selv. |
| too_many_children | Flere barn enn tillatt. details.max. |
| children_confirm_required | childrenConfirmed må være true når barn er med. |
| terms_outdated | termsVersionId er ikke gjeldende versjon. Hent /terms på nytt. |
| no_terms | Virksomheten har ikke publisert vilkår. |
| plan_limit | Pakkens grense for aktive erklæringer er nådd. |
| card_unknown | Brikken er ikke registrert på noe kort hos dere. |
| invalid_card_uid | uid kunne ikke leses som et kortnummer. |
| rate_limited | For mange kall. Vent og prøv igjen. |
| unauthorized | Manglende eller ugyldig API-nøkkel. |
| forbidden | Nøkkelen mangler rettigheten, eller pakken inkluderer ikke API. |
| plan_no_api | Pakken inkluderer ikke API-tilgang. |
| module_off | Kortmodulen er ikke slått på for virksomheten. |
| invalid_token | QR-koden er utløpt eller er ikke et Declarely-kort. Be gjesten hente den fram på nytt. |
| wrong_tenant | QR-koden hører til en annen virksomhet. |
Avslag på kortbruk
/api/v1/passes/use og /reverse svarer 200 med { ok: false, reason } når kortet finnes, men handlingen ikke kan utføres. Et ugyldig quantity er derimot en vanlig 400 med error validation. Det er ikke en feil i kallet, og forsøket blir stående i historikken på kortet, slik at kunden kan se at noen prøvde. Vis grunnen til operatøren.
| blocked | Kortet er sperret. |
| refunded | Kortet er refundert. |
| expired | Kortet er utløpt. |
| not_started | Kortet gjelder fra en senere dato. |
| insufficient | Færre klipp igjen enn det som ble forsøkt trukket. |
| wrong_type | Handlingen passer ikke korttypen. |
| already_reversed | Hendelsen er allerede angret. |
| not_reversible | Hendelsen kan ikke angres. |
Innbygging
Skjemaet kan bygges inn på egen nettside. Rammen tilpasser høyden automatisk.
<iframe src="https://<slug>.declarely.app/embed" class="declarely-embed"
style="width:100%;border:0;min-height:640px" title="Egenerklæring"></iframe>
<script src="https://<slug>.declarely.app/embed.js" async></script>