Integration guide
The Partner API is driven by events. Kivra tells you when a company activates an integration with you, when that company receives content, and when it deactivates the integration, and you respond to each with a few API calls. This guide follows that lifecycle in order. Read Webhooks first for how to verify and acknowledge the deliveries themselves.
1. A company activates an integration with you
Section titled “1. A company activates an integration with you”A user with the right to act for a company opens the company’s settings in
Kivra, picks you from the list of available partners, and activates the
integration. Kivra then sends you an integration.created event:
{ "data": { "company_key": "1560774336a57b73569d594df5abad7fd2575c1070", "vat_number": "SE556000475501" }, "data_version": 1, "event_created_at": 1788177600, "event_type": "integration.created", "id": "event_9c1d2e3f4a5b4c6d8e9f0a1b2c3d4e5f"}The vat_number lets you match the company to a customer in your system,
and company_key is what every request about the company is made under.
Later events about the company carry the key too.
2. Content arrives
Section titled “2. Content arrives”When a company that has an integration with you receives content, Kivra sends a
content.created event:
{ "data": { "company_key": "1560774336a57b73569d594df5abad7fd2575c1070", "content_key": "1756718042a9813e08f783496382b0bff743ec34ae", "vat_number": "SE556000475501" }, "data_version": 1, "event_created_at": 1788254042, "event_type": "content.created", "id": "event_3f62fc97907a4212af028c30f1ea1927"}The event carries only keys. Use them to fetch the content with
GET /v3/partner/company/{companyKey}/content/{contentKey}, which returns its metadata:
curl -X GET \ "https://sender.sandbox-api.kivra.com/v3/partner/company/$COMPANY_KEY/content/$CONTENT_KEY" \ -H "Authorization: Bearer $KIVRA_ACCESS_TOKEN"{ "created_at": "2026-09-01T00:00:00Z", "interpreted_fields": [], "key": "1756718042a9813e08f783496382b0bff743ec34ae", "labels": { "governmental": false, "handled": false, "interpreted": false, "reminder": false, "trashed": false, "viewed": false }, "origin": "kivra", "parts": [ { "content_type": "application/pdf", "name": "faktura-12345.pdf", "sha256": "f6c21611a855ce116943c15c49e963957775fb67595b54435a956610eefd231f", "size": 48213, "url": "https://sender.sandbox-api.kivra.com/v3/partner/company/1560774336a57b73569d594df5abad7fd2575c1070/content/1756718042a9813e08f783496382b0bff743ec34ae?part=1" } ], "payment_options": [ { "account": "5050-1055", "amount": 150000, "currency": "SEK", "description": "Total", "due_at": "2026-09-30T00:00:00Z", "interpreted": false, "reference": "123456789", "reference_type": "OCR", "type": "bankgiro", "vat_amount": null } ], "received_at": "2026-09-01T09:14:02Z", "receiver_name": "Cornelias Café AB", "receiver_vat_number": "SE556000475501", "references": null, "sender_contact_info": null, "sender_icon_url": "https://sandbox-static.kivra.com/img/tenant/1341573157b3a1c55f220f4007b2e44789d2d04015/icon.png", "sender_name": "Lenas Konditori AB", "sender_vat_numbers": [ "SE556123456701" ], "subject": "Faktura 12345", "transaction_at": "2026-09-01T00:00:00Z", "type": "invoice"}The API reference describes every field in the response.
Download the files
Section titled “Download the files”A content has one or more parts, listed in parts with a content_type,
size, sha256, and a ready-made url. The simplest way to download a file
is to request that URL with your bearer token. It is the same endpoint with
part=N, where N is the 1-based position in parts:
curl -X GET \ "https://sender.sandbox-api.kivra.com/v3/partner/company/$COMPANY_KEY/content/$CONTENT_KEY?part=1" \ -H "Authorization: Bearer $KIVRA_ACCESS_TOKEN" \ -o faktura-12345.pdfThe response body is the file, and Content-Type is the part’s
content_type. The part’s sha256 and size let you verify the download.
Not every document is a PDF. Kivra also lets senders deliver a letter as plain
text or HTML, which arrives as a part with content_type text/plain or
text/html and is downloaded the same way.
Mark the content as handled or read
Section titled “Mark the content as handled or read”The handled and viewed labels are the same ones the company’s users see
and change in Kivra, and PATCH /v3/partner/company/{companyKey}/content/{contentKey} lets your system
change them too. Use that to keep Kivra and your system in step: when your
system has processed the content, for example booked or paid an invoice,
mark it as handled, and the company’s users see it as handled, so nobody pays
it twice:
{ "labels": { "handled": true }}curl -X PATCH \ "https://sender.sandbox-api.kivra.com/v3/partner/company/$COMPANY_KEY/content/$CONTENT_KEY" \ -H "Authorization: Bearer $KIVRA_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data-binary @mark-handled.jsonThe same request can set viewed, which the company’s users see as read.
Your system can also offer these as actions to its own users, such as a
“Mark as read in Kivra” or “Mark as handled in Kivra” button, so they do not
need to open Kivra to tidy up the inbox. Both labels can be set back to
false.
3. A company deactivates the integration
Section titled “3. A company deactivates the integration”A company can deactivate the integration at any time from its settings in
Kivra. When it does, Kivra sends an integration.deleted event:
{ "data": { "company_key": "1560774336a57b73569d594df5abad7fd2575c1070", "vat_number": "SE556000475501" }, "data_version": 1, "event_created_at": 1790841600, "event_type": "integration.deleted", "id": "event_7a8b9c0d1e2f4a3b9c8d7e6f5a4b3c2d"}You can no longer read anything under that company key, so stop making requests for it. The data you have already stored is yours to handle according to your agreement with the company.
Beyond the webhook flow
Section titled “Beyond the webhook flow”The flow above is all a typical integration needs. For anything beyond it, the API reference describes a few more operations, such as listing the companies that have an integration with you.