Step 3 of 5

Invoices

Create a new invoice with the invoice service, or hand over an overdue one with the collection service, then validate the sums, use reservations and store only the returned id.

You create an invoice with one call to the Invoice Tools API. What you send decides which section of this page applies: a new invoice, which Waya issues and sends, or an invoice you already sent that is now overdue, which you hand over to Inkassogram. Waya validates the request in real time and answers 201 with the created invoice, or with an error code that tells you what to correct. Every call needs an authorization token, so authenticate first.

Invoice service

Create an invoice

Do not wrap the request in data

The request body is the invoice itself. Only the response is wrapped in data.

This minimal request invoices a mocked test individual for four hours of consultation. Waya looks the debtor up by national identifier and uses their registered address. The lookup operation (opens in a new tab) in Swagger lists the test identifiers.

Shell
curl --request POST \
  --url 'https://api.sandbox.waya.se/v4/rest/invoice' \
  --header 'Authorization: Bearer <authorization-token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "externalNumber": "INV-1001",
    "debtor": {
      "nationalIdentifier": {
        "number": "194107102222",
        "countryCode": "SE"
      }
    },
    "rows": [
      {
        "text": "Consultation services",
        "unit": "h",
        "unitPrice": 800.00,
        "quantity": 4,
        "vatPercentage": 25.0,
        "priceExcludingVat": true
      }
    ]
  }'

Change externalNumber each time you run it, because it must be unique. The identifier is a mocked individual that exists in non-production environments only, so use a real debtor in production. A successful call answers 201, and Response says which value to keep. You can also find the new invoice in Insight (opens in a new tab).

The due date must be after today, and the total at least 1 kr. If you leave dueDate out, Waya sets it from the invoice date and the client's settings.

Swagger describes every field of the request: the debtor, the rows and the optional fields (opens in a new tab), and the delivery methods (opens in a new tab).

Address lookup

Use the lookup operation to check an identifier, or to show the registered address, before you invoice.

GETLookup address given a national identifier/legal-entity/{country-code}/{national-identification-number}Lookup address given a national identifier in Swagger (opens in a new tab)
Shell
curl --request GET \
  --url 'https://api.sandbox.waya.se/v4/rest/legal-entity/SE/194107102222' \
  --header 'Authorization: Bearer <authorization-token>'

In non-production environments, only mocked individuals and a few real organizations can be looked up. The lookup operation (opens in a new tab) in Swagger lists them.

Where fields print

Invoices that Waya sends follow one template. The drawing shows its layout with placeholder text. The logo, the issuer, the payment details and the footer come from the client's settings, not from the request.

MarkerAPI fieldPrinted as
1debtor.name and debtor.billingAddressRecipient's name and address. Without an address, the registered address of debtor.nationalIdentifier is used
2debtor.externalNumberKundnummer
2yourReferenceEr referens
2ourReferenceVår referens
2yourOrderNumberErt ordernr
2ourOrderNumberVårt ordernr
2termsOfDeliveryLeveransvillkor
2referenceMärkning, recommended for general comments
2debtor.vatNumberMomsreg.nr
2debtor.nationalIdentifierPerson-/org.nr, when there is no VAT number
2debtor.phoneTelefon
3articleNumber, text, quantity, unit and unitPrice of each rowArtikelnr, Vara/tjänst, Antal, Enhet and À pris
4commentFree text at the bottom left of the totals box

Marker 2 is the reference grid. It prints only the fields you send, so a field that you leave out leaves no gap. The template applies a limit of 50 characters to each printed reference field, so keep the debtor's customer number (Kundnummer), your references, order numbers, terms of delivery and marking within it. yourReferenceId, ourReferenceId and project are not printed.

A row with only a text prints as a line of text, like the first row in the drawing. invoiceDate prints as Datum and dueDate as Förfallodag. Waya sets the invoice number and the OCR number.

For Peppol and other e-invoices, use edi.yourReference and edi.yourOrderNumber.

Collection service

Inkassogram by Waya

Inkassogram, Waya's reminder and collection service, takes over an invoice that you already sent from your own system. You hand the invoice over once it is overdue, and Inkassogram sends the reminders and collection letters. This is how a collection-service client integrates, and how an invoice-service client hands over an overdue invoice that it issued itself.

Hand over an overdue invoice

You hand over an invoice with the same call as a new one. Set sendAs to REMINDER or DEBT_COLLECTION, and send the data of the invoice you already sent. This example hands over an invoice for a payment reminder, after the debtor has paid 400 kr of it.

Shell
curl --request POST \
  --url 'https://api.sandbox.waya.se/v4/rest/invoice' \
  --header 'Authorization: Bearer <authorization-token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "externalNumber": "INV-0950",
    "debtor": {
      "nationalIdentifier": {
        "number": "194107102222",
        "countryCode": "SE"
      },
      "name": "Förnamn Efternamn",
      "email": "test@example.se",
      "phone": "+46701740605",
      "billingAddress": {
        "lines": ["Gatan 1"],
        "postalCode": "12345",
        "city": "Göteborg",
        "countryCode": "SE"
      },
      "type": "INDIVIDUAL"
    },
    "sendAs": "REMINDER",
    "dueDate": "2026-10-01",
    "rows": [
      {
        "text": "Faktura INV-0950",
        "unitPrice": 2000.00
      },
      {
        "text": "Avgår redan betalt/krediterat",
        "unitPrice": -400.00
      }
    ],
    "attachments": [
      {
        "base64": "<base64-of-the-original-pdf>",
        "md5": "<md5-of-the-original-pdf>"
      }
    ]
  }'

externalNumber is the number of the original invoice, and it must be unique. Send the debtor as on the original invoice. md5 is the MD5 hash of the original invoice PDF, the file you sent the debtor, taken before you base64-encode it, as 32 lowercase hexadecimal characters.

A handed-over invoice differs from a new one in these ways:

  • The due date must be today or earlier, and Waya rejects a later one. Hand an invoice over only once its due date has passed, because the claim must be overdue.
  • If the debtor has already paid part of the invoice, or you credited part of it, add a row with the reduction as a negative unitPrice, as in the example.
  • The total, after any reduction, must be at least 60 kr.
  • REMINDER starts at a payment reminder, and DEBT_COLLECTION at the collection letter.
  • A row carries the amount owed, VAT included. Leave vatPercentage out, so that no VAT is added on top.

The original invoice PDF

Waya did not produce the original invoice, so you supply its PDF. Waya makes the PDF available to the debtor online, and prints it on the back of reminders and collection letters. Send it in attachments when you hand over the invoice, as in the example above, or set it afterwards. A PDF may be at most 16 777 215 characters of base64, about 12 MB. Swagger (opens in a new tab) describes attachments.

After the invoice is created

You can also set the PDF afterwards, once the invoice is created.

Reserve the invoice if the PDF comes later

If the invoice is not reserved, the reminder or collection letter is sent without the PDF. Hand the invoice over with "reservation": true, set the PDF, and then finalize the invoice, as Reservations describes.

The body is the PDF file itself, not JSON:

PUTSet invoice PDF/invoice/{id}/pdfSet invoice PDF in Swagger (opens in a new tab)
Shell
curl --request PUT \
  --url 'https://api.sandbox.waya.se/v4/rest/invoice/<invoice-id>/pdf' \
  --header 'Authorization: Bearer <authorization-token>' \
  --header 'Content-Type: application/octet-stream' \
  --data-binary '@invoice.pdf'

After sending shows how to retrieve an invoice PDF.

Fees you already charged

If you already charged the debtor a reminder fee for the invoice, hand it over with the claim as a row with feeType set to reminder. Waya accepts this row only with DEBT_COLLECTION, not with REMINDER, and the fee must be positive. Include only a fee that you charged under your own terms of payment. Swedish law caps a reminder fee at 60 kr. Swagger (opens in a new tab) describes the row fields.

Settings per claim

Three fields set how Inkassogram handles the claim: overdueInterestRate, allowEnforcementAuthority (whether the claim may go to Kronofogden) and allowAmortization (whether the debtor may pay in installments). Without them, the client's settings apply. Swagger (opens in a new tab) describes the three fields.

Several invoices to one debtor

Good debt collection practice (god inkassosed) says that a debtor with several overdue claims from the same creditor should get one collection letter for them, where that is possible and suitable. Finansinspektionen gives this as general advice to 3 kap. 9 § in FFFS 2025:2 (opens in a new tab), and adds that the claims should not be combined while the time limit in a reminder for one of them is still running. So if you hand over several invoices to the same debtor, send them as one claim. Combine them like this:

  • Combine only invoices to the same debtor, with the same sendAs and the same currency. Limit it to debtors with a Swedish personal or organisation number, as Insight does when it combines claims.
  • Send one row per original invoice: its number as articleNumber, its description as text, the amount owed as unitPrice, and quantity 1. Swagger (opens in a new tab) describes the row fields.
  • Join the original numbers in externalNumber. It must still be unique.
  • Backdate the due date by the amount-weighted average number of days overdue, rounded up to whole days. The interest then comes out about as it would have on the separate invoices.
  • Attach the PDF of every original invoice. Waya merges them into one document, which may come to at most 16 777 215 characters of base64 together, so hand over a larger set as several claims.
  • The claim takes one interest rate and one set of settings.
Example: two invoices to one debtor

Invoice 1001 is for 1 000 kr and is 40 days overdue, and invoice 1002 is for 3 000 kr and is 20 days overdue. The weighted average is (1 000 × 40 + 3 000 × 20) ÷ 4 000 = 25, so the claim's due date is 25 days before today, and its total is 4 000 kr:

Shell
curl --request POST \
  --url 'https://api.sandbox.waya.se/v4/rest/invoice' \
  --header 'Authorization: Bearer <authorization-token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "externalNumber": "1001, 1002",
    "sendAs": "DEBT_COLLECTION",
    "dueDate": "<25-days-before-today>",
    "debtor": {
      "nationalIdentifier": {
        "number": "194107102222",
        "countryCode": "SE"
      }
    },
    "rows": [
      {
        "articleNumber": "1001",
        "text": "Invoice 1001",
        "unitPrice": 1000.00,
        "quantity": 1
      },
      {
        "articleNumber": "1002",
        "text": "Invoice 1002",
        "unitPrice": 3000.00,
        "quantity": 1
      }
    ],
    "attachments": [
      {
        "base64": "<base64-of-1001.pdf>",
        "md5": "<md5-of-1001.pdf>"
      },
      {
        "base64": "<base64-of-1002.pdf>",
        "md5": "<md5-of-1002.pdf>"
      }
    ]
  }'

Replace <25-days-before-today> with the date, as YYYY-MM-DD.

Before you hand over a claim

A claim that you hand over must meet the conditions of the general terms, §3.8 and §3.9 in version 2026:5. The claim:

  • is overdue;
  • comes from your ordinary business, for goods delivered or services performed;
  • is not disputed, and not subject to a dispute or a counterclaim;
  • is not part of a debtor's bankruptcy, reconstruction, liquidation or debt restructuring;
  • is not against a minor;
  • is not otherwise unclear;
  • can be substantiated on request;
  • is not subject to another ongoing collection action or a pending case at Kronofogden.

The API can't check these, so you answer for them.

Validate the sums

Send your own totals in sumValidation, and Waya compares them with its own calculation from the data in the request. It catches rounding differences between your system and Waya before an invoice goes out. You can validate the whole invoice, each row, or both.

The allowed difference is set for each client. Swagger (opens in a new tab) describes the totals that you can send.

Response

A successful call answers 201 with the invoice, wrapped in data. Swagger (opens in a new tab) describes the response fields.

Store only the id. It is the only value your system needs to keep, and you can fetch everything else when you need it, as After sending describes. Keep the entity type with the ID if you store IDs of several types, as Entity IDs (opens in a new tab) in Swagger explains.

Reservations

A reservation lets you create an invoice and hold it back. Create it with "reservation": true. Waya creates it, but does not send it until you finalize it. Until then you can replace or delete it:

DELETEDelete an invoice/invoice/{id}Delete an invoice in Swagger (opens in a new tab)
PUTFinalize a reserved invoice/invoice/{id}/finalizeFinalize a reserved invoice in Swagger (opens in a new tab)
Shell
curl --request PUT \
  --url 'https://api.sandbox.waya.se/v4/rest/invoice/<invoice-id>/finalize' \
  --header 'Authorization: Bearer <authorization-token>'

If a request fails, Errors explains how to read the error code.