Business Gateway
For platforms

Sending

Submit documents on behalf of the companies under your account.

Sending is one call. You do not name the company: the sender participant determines it, and we refuse a sender that is not under a company your credential reaches.

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\"?>…"
  }'

Exactly one of payload (the XML as a string) and payloadObjectKey (see below). type is a short alias; pass documentTypeId and processId instead if you need a document type that has no alias.

Both participants matter. The sender must be READY or ACTIVE with a matching SEND capability. The receiver is looked up on the network, and if it is not registered for that document type the send fails — usually the recipient's fault, but it will surface as your customer's problem.

202 does not mean valid

The response is 202 with status QUEUED_VALIDATION for any document that has validation rules. Peppol validation runs after your request returns, not inside it, so a slow validator never becomes your latency.

What you get back is a document id and a promise to tell you the verdict. That verdict arrives as VALID or VALIDATION_FAILED on a webhook or on a later GET /v1/messages/{id}.

StatusWhere it is
QUEUED_VALIDATIONAccepted, waiting for validation
VALIDATION_FAILEDRejected by the Peppol rules. validationErrors says what failed
QUEUEDValid, waiting to go to the network
SENDING / SEND_RETRYOn its way, or being retried
AS4_ACCEPTEDThe recipient's access point took it. This is delivery
SEND_FAILEDTerminal. lastErrorCode and lastErrorMessage say why
DISCOVERY_FAILEDThe recipient could not be found on the network

AS4_ACCEPTED means the other access point accepted the document — that is as far as Peppol guarantees. Whether the recipient's finance system then processes it is between them and their provider, and a Message Level Status may follow.

Idempotency

Idempotency-Key is optional and worth setting on every send. Same key with the same body returns the original document and 200 instead of creating a second one; same key with a different body is 409 IDEMPOTENCY_CONFLICT. Keys are unique per account forever, up to 128 characters.

Without the header, a retried request creates a second document — and your customer's trading partner gets the invoice twice.

Large documents

Inline payload is capped at about 1 MB. Above that, upload the bytes separately:

# 1. ask for a URL
curl -sS -X POST https://api.businessgateway.se/v1/messages/uploads \
  -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
  -d '{"companyId":"'"$COMPANY_ID"'","bytes":4200000}'
# → {"payloadObjectKey":"…","uploadUrl":"https://…","expiresAt":"…"}

# 2. PUT the bytes straight at uploadUrl

# 3. submit, naming the key instead of the payload
curl -sS -X POST https://api.businessgateway.se/v1/messages \
  -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
  -d '{"sender":"…","receiver":"…","type":"invoice","payloadObjectKey":"…"}'

The hard ceiling for a document is about 40 MB, inbound and outbound alike.

Checking on a document

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

Or list them. GET /v1/messages takes direction, status, companyId, from/to, q, and cursor pagination; format=csv gives the same filter as a download, and counts=true adds a breakdown by status. Across your whole account, without companyId, you see every company at once — which is the view worth putting in front of your support team.

On this page