WinShopAPI docs
ConceptsDocuments

Document lifecycle

Create, update, lock and process a document, create one document from another, and print it.

This page follows a document from creation to processing. The examples use a delivery note, the document that issues goods from a warehouse to a customer. Other document types work the same way under their own route; see Anatomy of a document for the list.

Create

POST the header, with or without items, to the collection route.

curl -X POST https://<your-instance>/api/documents/expedition/delivery-notes \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": 1042,
    "warehouseId": 1,
    "formNumber": "DN-2026-0418",
    "items": [
      {
        "productId": 733,
        "quantityIssued": 4,
        "unitIdIssued": 1,
        "priceWoVat": 100,
        "price": 121,
        "vatRate": 21
      }
    ]
  }'

What happens on the server:

  1. Validation comes first. The whole request is checked before anything is written. If it is invalid you get 400 and messages lists every violation at once, so you can fix them all in one go. See Errors.
  2. An internal number is reserved. On insert the server assigns the next internalNumber of that document type. You cannot choose it. Put your own reference in formNumber.
  3. The stored document comes back. The response body is the document as saved, including its new id, the ids of its items and the calculated totals. Keep the id: every later call needs it.

Which fields are required depends on the document type. For delivery notes and orders the header needs a customerId and a warehouseId. An item needs a productId, a quantity and, as a group, a unit, a price and a VAT rate. The request examples on each create endpoint's reference page show the minimal valid bodies.

Update

PUT /api/documents/…/{documentId} updates the header and the items you send. The body has the same shape as on create.

  • Header fields you send are written. Header fields you leave out keep their stored value.
  • An item in the body with an id updates that stored item.
  • An item without an id is added as a new item.
  • Stored items that are missing from the body are kept, unless you add ?removeItemsNotInRequest=true. Then they are deleted, and the body becomes the complete list of items.
curl -X PUT "https://<your-instance>/api/documents/expedition/delivery-notes/77120" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "Deliver to the back entrance",
    "items": [
      { "id": 301555, "note": "Fragile" }
    ]
  }'

Do not send back the fields the server maintains itself, such as isProcessed, isLocked, lockOwner, createdAt, lastModify and the totals. They are calculated, not stored from your request.

Some header fields are fixed once the document exists. The warehouse of a delivery note cannot be changed, for example. The server answers 400 and says which field it objects to.

Change single items

To touch only the items, you do not have to send the whole document:

RequestEffect
POST …/{documentId}/itemsAdd items. The body is an array of items.
PUT …/{documentId}/items/{itemId}Update one item.

The document totals are recalculated after each of them. To remove items, see Deleting.

Locks

A lock marks a document as being edited. When a user opens a document in WinShop, it is locked in their name until they close it. The lock exists so that two parties do not overwrite each other's changes.

RequestEffect
GET …/{documentId}/lockReturns the lock state.
POST …/{documentId}/lockLocks the document in the name of your API client. Fails with 400 if it is already locked.
DELETE …/{documentId}/lockReleases the lock. Fails with 400 if the lock belongs to someone else.

The lock state is a DocumentLockState:

{ "isLocked": true, "lockOwner": "Jana Novakova" }

A locked document cannot be changed

While a document is locked, PUT, the item endpoints and process fail. The answer is 400 Bad Request, not 409, and it carries no code. You recognise it by the message:

"messages": ["Document is locked by Jana Novakova. Document needs to be closed."]

What this means for an integration:

  • Before a change, or when a change fails with the message above, read the lock state. If the document is locked, a person has it open. Wait and retry later; do not try to break the lock.
  • The lock blocks changes no matter who holds it. If your own client locked the document, release the lock before you send the change.
  • For a long-running interactive edit in your own user interface, take the lock when the user opens the document and release it when they are done, so that WinShop users see the document as in use.

Process

POST …/{documentId}/process posts the document. What that means depends on the type: processing a delivery note takes the goods off stock, processing an intake puts them on stock, processing an internal transfer moves them between warehouses.

curl -X POST https://<your-instance>/api/documents/expedition/delivery-notes/77120/process \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Processing cannot be undone

There is no "unprocess" endpoint. After processing, isProcessed is true and the document is closed for changes: a PUT or an item change fails with 400 and the message Cannot update an already processed document.

  • Processing fails if the document is already processed or is locked.
  • Only document types that move stock have process: intakes, delivery notes, write-offs and internal transfers. Orders and claims have no such step.
  • Some types still have an older POST …/{documentId}/finish route. It is a deprecated alias of process and will be removed. Use process.

Create one document from another

Some documents are created from an existing one instead of from scratch. The main case is invoicing a delivery note:

curl -i -X POST https://<your-instance>/api/documents/expedition/delivery-notes/77120/invoice \
  -H "Authorization: Bearer $ACCESS_TOKEN"
HTTP/1.1 201 Created
Location: https://<your-instance>/api/documents/invoices/5120

The answer is 201 Created, and the Location header points at the new invoice. Follow it to read the invoice.

To put several delivery notes on one invoice, use POST /api/documents/expedition/delivery-notes/invoice with their ids in deliveryNoteIds. See Create an invoice from delivery notes.

Print

GET …/{documentId}/pdf returns the document as a PDF file, rendered with the print template the customer has configured for that document type.

curl https://<your-instance>/api/documents/expedition/delivery-notes/77120/pdf \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -o delivery-note-77120.pdf

The response is binary (application/pdf), not JSON. If the document has no printable output, the answer is 404.

Reference

The delivery note endpoints used on this page:

On this page