Business Gateway
For businesses

Over the API

Send a document, collect what arrives, with HTTP calls.

Your key goes in X-API-Key on every request. Keys start with pap_.

curl -sS -H "X-API-Key: $KEY" https://api.businessgateway.se/v1/account

That call is worth making first: it tells you the account and company your key belongs to, which is a quick way to confirm the key works before you build anything on it.

Keep the key on a server. It is not safe in a browser, a mobile app or anything else a customer of yours can read out.

Sending a document

curl -sS -X POST https://api.businessgateway.se/v1/messages \
  -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "sender": "0007:5561234567",
    "receiver": "0007:5569876543",
    "type": "invoice",
    "payload": "<?xml version=\"1.0\"?>…"
  }'

sender is your Peppol address, receiver is your trading partner's, payload is the document XML as a string, and type says what kind of document it is — invoice, credit-note, order. The full list is in Document types.

Documents larger than about 1 MB are uploaded separately: POST /v1/messages/uploads gives you a URL to PUT the bytes at, then you submit with payloadObjectKey instead of payload. The ceiling is about 40 MB.

Always send an Idempotency-Key

Idempotency-Key is a value you make up — a UUID is fine — that makes it safe to retry. If the same key arrives again with the same document, you get the original back instead of a second copy. If your network drops the response and you retry without one, your customer receives the invoice twice.

What happens after you submit

You get 202 back with a document id, and a status of QUEUED_VALIDATION. That is not "valid". It means we accepted the document and will now check it against the Peppol rules.

The check takes a moment, which is why it does not happen inside your request. The verdict arrives on a webhook, or you read it later:

curl -sS -H "X-API-Key: $KEY" \
  "https://api.businessgateway.se/v1/messages/$ID"
StatusWhat it means for you
QUEUED_VALIDATIONAccepted, being checked
VALIDATION_FAILEDRejected. validationErrors lists what failed — fix the XML and send again
QUEUEDPassed, waiting to go out
SENDING / SEND_RETRYOn its way
AS4_ACCEPTEDDelivered to the recipient's provider. This is success
SEND_FAILEDTerminal. lastErrorMessage says why
DISCOVERY_FAILEDThe recipient's address could not be found on the network

AS4_ACCEPTED is as far as Peppol's guarantee goes: the recipient's access point has the document. What their finance system does with it afterwards is theirs, and may come back as a Message Level Status.

Collecting documents

Ask what is waiting:

curl -sS -H "X-API-Key: $KEY" \
  "https://api.businessgateway.se/v1/messages?direction=INBOUND&status=CUSTOMER_DELIVERY_QUEUED"

Fetch the XML:

curl -sS -H "X-API-Key: $KEY" \
  "https://api.businessgateway.se/v1/messages/$ID/payload"

Then acknowledge it, once you have stored it somewhere you trust:

curl -sS -X POST -H "X-API-Key: $KEY" \
  "https://api.businessgateway.se/v1/messages/$ID/ack"

Acknowledge after your own system has the document, not before. Until you do, the document stays in the waiting list — so if your import crashes halfway, it is still there on the next run. Acknowledging twice is harmless.

Listing and searching

GET /v1/messages takes direction (INBOUND or OUTBOUND), status, from and to as dates, and q as a search string. Results are paginated: read nextCursor from the response and pass it back as cursor until it stops appearing.

format=csv returns the same filter as a download, which is often the fastest way to answer a question from your finance team.

Errors

Failures come back in one shape:

{ "error": { "code": "VALIDATION_FAILED", "message": "…" } }

The code is stable and safe to branch on; message is for people and may change. The full list is in Error codes.

On this page