Business Gateway
For businesses

Over SFTP

Drop a file to send it, collect files that arrive.

If your system already writes invoice files, this is the shorter path: no HTTP client, no key handling in your code. You connect over SFTP, put a file in out/, and it goes. Documents addressed to you appear in in/.

Connecting

Hostsftp.businessgateway.se
Port2222 — port 22 is closed
Username and passwordGiven to you when your login was set up

Pin the host key fingerprint in your client before you connect. Whoever set you up has it, and GET /v1/sftp/connection returns it together with the host, port and the directory each login sees.

The fingerprint matters. It is what proves you are talking to us and not to something that answered instead, and it does not change. A client that accepts any host key will connect happily to an impostor.

sftp -P 2222 kinnefrukt@sftp.businessgateway.se

What you see

PathWho writes itWhat it is
out/<name>.xmlYouA document to send
out/<name>.jsonYou, optionalWho sends it, who receives it and what it is, when the document cannot say — see below
out/sent/<name>.xmlUsYour upload, moved here once it was sent
out/failed/<name>.xml + <name>.xml.error.jsonUsYour upload, moved here because it was refused, and why
in/<documentId>.xml + <documentId>.jsonUsA document that arrived for you, and a description of it

You may write into out/ and read from in/; that is the whole permitted surface. It is not a general file system, and anything else is refused.

If your login covers more than one company, or was set up per Peppol address, you will step through one or two directories named after the company or the address before reaching in/ and out/. What your login sees is fixed when it is created.

Sending

Copy the XML into out/. For an ordinary Peppol invoice, that is all.

Who sends and who receives

Without anything alongside it, we read both out of the document itself — its endpoint ids (cbc:EndpointID):

  • Sender: if your company has one Peppol address, that one — provided the document names it. If it has several, the one address of yours the document names. Addresses that have been deactivated or rejected do not count.
  • Receiver: the one endpoint id in the document that is not the sender.

That covers almost every invoice. It does not cover a document that names nobody else (a company invoicing itself), one that names more than one other party (a delivery party with its own endpoint id), or one that names two of your own addresses. For those, say who is who in a JSON file.

When the document is not enough

Put a JSON file with the same base name next to the document — invoice.xml pairs with invoice.json:

{
  "sender": "0007:5561234567",
  "receiver": "0007:5569876543",
  "type": "invoice"
}

Every field is optional and unknown fields are refused; state only what the document cannot settle, and the document fills in the rest. type is a document type alias; instead of it you can give the full documentTypeId and processId. A sender you state must be one of your company's addresses.

Upload the JSON file first, then the document. The document's arrival is what starts the processing, and the JSON file is read at that moment — one that arrives later is not seen. The JSON file is not itself treated as a document.

What happens next

Once the file has been picked up it moves out of out/:

  • Sent → out/sent/, keeping its name, so you can find it again.
  • Failed → out/failed/, with <name>.error.json beside it. Read that file before resending; a validation failure will fail again unchanged.

The .error.json carries reason, a short summary, and error, the precise cause. When the problem is about who sends or receives, it also lists the endpoint ids the document names and the addresses your company has, so you can see the mismatch:

{
  "file": "invoice.xml",
  "reason": "the sending participant could not be resolved",
  "error": "cannot determine the sending participant: 2 of the document's endpoint ids belong to this company",
  "documentEndpoints": ["0007:5561234567", "0007:5560001111"],
  "companyParticipants": ["0007:5561234567", "0007:5560001111"],
  "occurred": "2026-10-13T09:12:44Z"
}

GET /v1/files lists every upload, newest first, with its status — queued, processing, sent or failed — and, once it became a document, its documentId. From there GET /v1/messages/{id} says how far the document got, including whether the recipient's system confirmed it.

Uploading safely

Do not leave half-written files where we can see them. Files whose names end in .tmp, .part or .filepart, and files whose names begin with a dot, are ignored — so the reliable pattern is to upload as invoice.xml.part and rename to invoice.xml when the transfer is complete. Most SFTP clients can be told to do exactly this.

Sending the same document twice is recognised as a repeat and will not produce two documents — whatever the file is called. It is the content that counts: a new invoice under a file name you have used before is a new document.

Receiving

Documents that arrive for you appear in in/, named {documentId}.xml unless a different pattern was configured for your account. Depending on setup they may be organised into date directories — in/2026/09/12/.

Beside each one is a JSON file with the same base name, written before the document appears, so you never see one without the other:

{
  "sender": "0007:5569876543",
  "receiver": "0007:5561234567",
  "documentType": "busdox-docid-qns::urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##…",
  "processId": "cenbii-procid-ubl::urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
  "receivedAt": "2026-10-13T09:15:02.118Z",
  "sha256": "…"
}

It is on by default. If your system has no use for it, ask for it to be turned off for your account — as with the naming pattern and the date directories, that is set up for you rather than by you.

Collect documents on whatever schedule suits you. They are not deleted because you have not collected them yet.

If you want to know the moment something lands rather than waiting for your next poll, add a webhook — it works alongside SFTP.

If something does not move

SymptomLook at
The file sits in out/Is it still named .part or .tmp? Is it in the right directory for the company?
It landed in out/failed/The .error.json beside it — and the two errors below
Nothing ever arrives in in/Your trading partner may be sending to the wrong address, or you may not be registered to receive that document type
The connection is refusedPort 22 instead of 2222, wrong host key pinned, disabled login, or a source address that is not allowed

The two refusals you are most likely to meet:

error in .error.jsonWhat to do
cannot determine the receiver from the document: no endpoint other than the senderThe seller and the buyer in the document are the same address. Send it to someone else, or state receiver in a JSON file
cannot determine the sending participant: 2 of the document's endpoint ids belong to this companyThe document names two of your own addresses, so we cannot tell which one sends. State sender in a JSON file

Your login can be restricted to particular source addresses, and repeated failed attempts lock it temporarily. If you have changed office network, that is the first thing to check.

On this page