Tenant API - Payment Webhooks

Payment webhook

This webhook notifies you when payment events occur such as when payments are settled, scheduled, or failed. Each webhook includes information about the payment including account details, amount, and event timing.

Standard

Kivra Payments follows Standard Webhooks for delivering webhooks.

Authentication

Kivra Payments signs webhooks with HMAC signatures that you can verify to ensure the request came from Kivra. When Kivra sends a webhook, the following headers will be included:

  • webhook-id: A unique identifier for the webhook delivery
  • webhook-timestamp: Unix timestamp when the webhook was sent
  • webhook-signature: Signature(s) used to verify the payload

The signature header contains one or more signatures in the format: v1,<signature1> v1a,<signature2>

The signature is generated by concatenating the following fields with a full stop between them: msg_id.timestamp.payload

For instance:

3f62fc97-907a-4212-af02-8c30f1ea1927.1674087231.{
  "type": "contact.created",
  "timestamp": "2022-11-03T20:26:10.344522Z",
  "data": {
    "id": "3f62fc97-907a-4212-af02-8c30f1ea1927"
  }
}

To verify the signature, use the raw body without any modification. Here are some examples on verification using the Standard Webhooks libraries:

// go
import standardwebhooks "github.com/standard-webhooks/standard-webhooks/libraries/go"

wh, err := standardwebhooks.NewWebhook(secret)
wh.Verify(webhook.Body, webhook.Headers)
// java
import com.standardwebhooks.Webhook;

Webhook webhook = new Webhook(secret);
webhook.verify(webhookBody, webhookHeaders);
// C#
using StandardWebhooks;

var wh = new Webhook(secret);
wh.Verify(webhookBody, webhookHeaders);

Retries

Kivra Payments will retry delivery of the webhook in the case of a non-200 response. The schedule is as follows:

AttemptDelayTime since start
1Immediately00:00:00
25 seconds00:00:05
35 minutes00:05:05
430 minutes00:35:05
52 hours02:35:05
65 hours07:35:05
710 hours17:35:05
814 hours31:35:05
920 hours51:35:05
1024 hours75:35:05

If the delivery is unsuccessful on the 10th attempt, the delivery will be cancelled and no more attemps will be done.

postWebhookpayment.webhook

Headers

webhook-idstring uuid required
Example:3f62fc97-907a-4212-af02-8c30f1ea1927

Unique identifier for this webhook delivery

webhook-timestampinteger required
Example:1674087231

Unix timestamp when the webhook was sent

webhook-signaturestring required
Example:v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4= v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg==

Signatures used to verify the webhook

Payload

idstring uuid required

Unique identifier for the webhook event

timestampstring date-time required

Timestamp when the webhook was generated

type'payment_callback' | 'invoice_declined' | 'payment_callback_retry (deprecated, use the same type as for the original webhook with the knowledge that it can be a retry)' required

Type of notification - original webhook or a retry

Example payload

{
  "id": "3f62fc97-907a-4212-af02-8c30f1ea1927",
  "timestamp": "2025-04-24T13:45:10Z",
  "data": {
    "content_key": "1691677075a9813e08f783496382b0bff743ec34ae",
    "due_date": "2025-05-01",
    "pay_date": "2025-04-24",
    "destination_account": "12345-6789",
    "remittance_string": "426523791",
    "option_title": "Full payment",
    "option_id": "option_1",
    "event_time": "2025-04-24T13:44:58Z",
    "swish_alias": "1234567890",
    "swish_payment_reference": "652ED6A2BCDE4BA8AD11D7334E9567B7",
    "amount": "123.50",
    "currency": "SEK"
  }
}

Response

Return a 200 status to acknowledge receipt of the webhook. Any other response will cause Kivra to retry the delivery, which will happen up to 10 times with increasing intervals.

Changes

Webhooks have no change history: a webhook is keyed by its event name rather than a path and method, so no recorded change can name it.