HalsenPayHalsenPay

HalsenPay API

Integrer betalinger med kort og Vipps i din applikasjon. Vår REST API gjør det enkelt å ta imot betalinger på vegne av dine kunder.

Enkel integrasjon

Kom i gang på minutter med vårt enkle API

Flere betalingsmetoder

Støtte for kort (Stripe) og Vipps

Base URL
https://pay.halsenpay.no/api/v1

Autentisering

Alle API-kall må autentiseres med en API-nøkkel. Send nøkkelen iX-HalsenPay-ApiKeyheaderen.

Sikkerhet: Hold API-nøkkelen hemmelig. Ikke eksponer den i frontend-kode eller offentlige repositories.

Hvor finner jeg API-nøkkelen?

Gå til Dashboard → API-nøkler for å opprette og administrere nøkler.

Header
X-HalsenPay-ApiKey: hp_live_xxxxxxxxxxxxxxxx
Eksempel med cURL
curl https://pay.halsenpay.no/api/v1/payments \
  -H "X-HalsenPay-ApiKey: hp_live_xxx"

Hurtigstart

Følg disse stegene for å ta imot din første betaling:

  1. 1

    Opprett en betaling

    Send en POST-forespørsel med beløp og redirect-URLer

  2. 2

    Redirect kunden

    Bruk checkoutUrl fra responsen

  3. 3

    Kunden betaler

    De velger kort eller Vipps på HalsenPay checkout

  4. 4

    Motta webhook

    Vi sender en webhook når betalingen er fullført

1. Opprett betaling
const response = await fetch(
  'https://pay.halsenpay.no/api/v1/payments',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-HalsenPay-ApiKey': 'hp_live_xxx'
    },
    body: JSON.stringify({
      amount: 9900,
      currency: 'NOK',
      description: 'Premium abonnement',
      successUrl: 'https://example.com/success',
      cancelUrl: 'https://example.com/cancel'
    })
  }
);

const { checkoutUrl } = await response.json();
2. Redirect kunden
// Redirect til HalsenPay checkout
window.location.href = checkoutUrl;
POST/api/v1/payments

Opprett betaling

Oppretter en ny betalingssesjon. Returner en checkout-URL som kunden skal redirectes til.

Request body

ParameterTypeBeskrivelse
amount*integerBeløp i øre (9900 = 99,00 kr)
currencystringValuta, default "NOK"
description*stringBeskrivelse (maks 500 tegn)
successUrl*stringRedirect ved suksess
cancelUrl*stringRedirect ved avbrudd
customer.externalIdstringDin kunde-ID
customer.emailstringKundens e-post
customer.namestringKundens navn
metadataobjectEgendefinert data

Response

ParameterTypeBeskrivelse
id*stringUnik betalings-ID
checkoutUrl*stringURL for checkout
status*stringCREATED
expiresAt*stringUtløpstid (30 min)
Request
{
  "amount": 49900,
  "currency": "NOK",
  "description": "Pro-abonnement",
  "successUrl": "https://example.com/success",
  "cancelUrl": "https://example.com/cancel",
  "customer": {
    "externalId": "user_123",
    "email": "kunde@example.com",
    "name": "Ola Nordmann"
  },
  "metadata": {
    "orderId": "order_456"
  }
}
Response201 Created
{
  "id": "pay_abc123xyz",
  "checkoutUrl": "https://pay.halsenpay.no/checkout/pay_abc123xyz",
  "amount": 49900,
  "currency": "NOK",
  "status": "CREATED",
  "expiresAt": "2025-12-08T18:30:00.000Z",
  "createdAt": "2025-12-08T18:00:00.000Z"
}
GET/api/v1/payments

List betalinger

Henter en paginert liste over alle betalinger.

Query parameters

ParameterTypeBeskrivelse
limitintegerAntall (default 20, maks 100)
offsetintegerSkip for paginering
statusstringFilter: SUCCEEDED, FAILED, etc.
providerstringFilter: STRIPE, VIPPS
Request
curl "https://pay.halsenpay.no/api/v1/payments?limit=10&status=succeeded" \
  -H "X-HalsenPay-ApiKey: hp_live_xxx"
Response200 OK
{
  "data": [
    {
      "id": "pay_abc123",
      "amount": 49900,
      "currency": "NOK",
      "status": "SUCCEEDED",
      "provider": "STRIPE",
      "description": "Pro-abonnement",
      "fees": {
        "providerFee": 1497,
        "halsenpayFee": 250,
        "partnerNet": 48153
      },
      "createdAt": "2025-12-08T18:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 42,
    "limit": 10,
    "offset": 0,
    "hasMore": true
  }
}
GET/api/v1/payments/:id

Hent betaling

Henter fullstendige detaljer om en spesifikk betaling.

Path parameters

ParameterTypeBeskrivelse
id*stringBetalings-ID (pay_xxx)
Response200 OK
{
  "id": "pay_abc123xyz",
  "amount": 49900,
  "currency": "NOK",
  "status": "SUCCEEDED",
  "type": "ONE_TIME",
  "provider": "STRIPE",
  "providerReference": "pi_3abc123",
  "description": "Pro-abonnement",
  "customer": {
    "externalId": "user_123",
    "email": "kunde@example.com",
    "name": "Ola Nordmann"
  },
  "fees": {
    "providerFee": 1497,
    "halsenpayFee": 250,
    "partnerNet": 48153
  },
  "refundedAmount": 0,
  "createdAt": "2025-12-08T18:00:00.000Z",
  "completedAt": "2025-12-08T18:05:00.000Z"
}
POST/api/v1/subscriptions

Opprett abonnement

Oppretter et nytt gjentakende abonnement.

Request body

ParameterTypeBeskrivelse
amount*integerBeløp per periode i øre
productName*stringNavn på abonnementet
intervalUnitstringday, week, month, year
intervalCountintegerAntall perioder (default 1)
trialDaysintegerGratis prøveperiode
successUrl*stringRedirect ved suksess
cancelUrl*stringRedirect ved avbrudd
Request
{
  "amount": 29900,
  "productName": "Pro-abonnement",
  "productDescription": "Tilgang til alle funksjoner",
  "intervalUnit": "month",
  "intervalCount": 1,
  "trialDays": 14,
  "successUrl": "https://example.com/welcome",
  "cancelUrl": "https://example.com/pricing",
  "customer": {
    "email": "bruker@example.com"
  }
}
Response201 Created
{
  "id": "sub_xyz789",
  "amount": 29900,
  "currency": "NOK",
  "productName": "Pro-abonnement",
  "intervalUnit": "month",
  "intervalCount": 1,
  "status": "PENDING",
  "checkoutUrl": "https://pay.halsenpay.no/subscribe/sub_xyz789",
  "createdAt": "2025-12-08T18:00:00.000Z"
}
GET/api/v1/subscriptions

List abonnementer

Henter en liste over alle abonnementer med cursor-basert paginering.

Query parameters

ParameterTypeBeskrivelse
limitintegerAntall (default 20, maks 100)
cursorstringCursor for neste side
statusstringACTIVE, CANCELED, etc.
customer_idstringFilter på kunde
Response200 OK
{
  "data": [
    {
      "id": "sub_xyz789",
      "amount": 29900,
      "currency": "NOK",
      "productName": "Pro-abonnement",
      "status": "ACTIVE",
      "intervalUnit": "month",
      "currentPeriodEnd": "2026-01-08T18:00:00.000Z",
      "customer": {
        "externalId": "user_123",
        "email": "bruker@example.com"
      }
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

Webhooks

Webhooks lar deg motta sanntidsvarsler når hendelser skjer. Konfigurer webhooks i Dashboard → Webhooks.

Webhooks sendes med opptil 5 forsøk ved feil, med eksponentiell backoff.
Webhook payload
{
  "id": "evt_abc123",
  "type": "payment.completed",
  "created_at": "2025-12-08T18:05:00.000Z",
  "data": {
    "payment": {
      "id": "pay_abc123xyz",
      "amount": 49900,
      "currency": "NOK",
      "status": "SUCCEEDED",
      "provider": "STRIPE",
      "fees": {
        "providerFee": 1497,
        "halsenpayFee": 250,
        "partnerNet": 48153
      }
    }
  }
}

Webhook-hendelser

Velg hvilke hendelser du vil motta i webhook-konfigurasjonen.

EventBeskrivelse
payment.createdBetaling opprettet
payment.completedBetaling fullført
payment.failedBetaling feilet
payment.refundedBetaling refundert
subscription.createdAbonnement opprettet
subscription.activatedAbonnement aktivert
subscription.canceledAbonnement avsluttet
Eksempel: payment.completed
{
  "id": "evt_xyz789",
  "type": "payment.completed",
  "created_at": "2025-12-08T18:05:00.000Z",
  "data": {
    "payment": {
      "id": "pay_abc123",
      "amount": 49900,
      "status": "SUCCEEDED"
    }
  }
}

Webhook-verifisering

Alle webhooks signeres med HMAC-SHA256. Verifiser signaturen for å sikre autentisitet.

Signatur-header

X-HalsenPay-Signature: t=1702054200,v1=abc123...

Avvis forespørsler med ugyldig signatur eller for gammelt timestamp (>5 min).
Verifiser signatur (Node.js)
import crypto from 'crypto';

function verifyWebhook(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const parts = signature.split(',');
  const timestamp = parts[0].split('=')[1];
  const hash = parts[1].split('=')[1];
  
  // Sjekk at timestamp ikke er for gammelt
  const age = Date.now() / 1000 - parseInt(timestamp);
  if (age > 300) return false; // 5 min
  
  // Verifiser signatur
  const baseString = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(baseString)
    .digest('hex');
    
  return hash === expected;
}

Feilkoder

API-et returnerer standard HTTP-statuskoder med strukturerte feilmeldinger.

HTTPKodeBeskrivelse
400VALIDATION_ERRORUgyldig request
401INVALID_API_KEYUgyldig API-nøkkel
403WRITE_PERMISSION_REQUIREDMangler skrivetilgang
403READ_PERMISSION_REQUIREDMangler lesetilgang
404NOT_FOUNDRessurs ikke funnet
500INTERNAL_ERRORServerfeil
Feilrespons400 Bad Request
{
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "details": {
    "fieldErrors": {
      "amount": ["Must be positive"]
    }
  }
}

Statuser

Betalingsstatuser

CREATEDVenter på kunde
PENDINGHos betalingsleverandør
SUCCEEDEDFullført
FAILEDFeilet
CANCELLEDAvbrutt
EXPIREDUtløpt
REFUNDEDRefundert

Abonnementsstatuser

PENDINGVenter på godkjenning
ACTIVEAktivt
PAST_DUEForfalt
CANCELEDAvsluttet

Bruk webhooks for å lytte på statusendringer i sanntid.