---
title: Document Cursor and Incremental Sync
slug: devdocs/document-cursor-and-incremental-sync
docTags: 
createdAt: 2026-10-22T08:35:59.287Z
---

To keep your ERP in step with Expressoft, you read the documents that are new since your last sync. The API has three tools for it.

| **Tool**                    | **Use it to**                                                    |
| --------------------------- | ---------------------------------------------------------------- |
| `dateBegin` and `dateEnd`   | Read the documents of a period.                                  |
| `nOK`                       | Read the documents marked as NOK.                                |
| The document cursor         | Keep the position of your sync in Expressoft, per document type. |
| `lastModifiedOnGreaterThen` | Read only the products changed after a date (**Products**).      |

## Read the cursors

**Query**

```graphql
query GetDocumentCursors {
  miscellaneous {
    cursor {
      accountingDocumentType
      accountingDynamicEntityType
      dynamicEntityKey
      cursorValue
      cursorData
    }
  }
}
```

**cURL**

```bash
curl --location 'https://sandbox.expressoft.eu/connect/api/interopgql' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{"query": "query GetDocumentCursors { miscellaneous { cursor { accountingDocumentType accountingDynamicEntityType dynamicEntityKey cursorValue cursorData } } }"}'
```

**Response**

```json
{
  "data": {
    "miscellaneous": {
      "cursor": [
        {
          "accountingDocumentType": "PurchaseInvoice",
          "accountingDynamicEntityType": null,
          "dynamicEntityKey": null,
          "cursorValue": "<cursor value>",
          "cursorData": "<cursor data>"
        }
      ]
    }
  }
}
```

There is one cursor for each `accountingDocumentType`: `PurchaseInvoice`, `Transfer`, `ConsumptionNote`, `ProductionNote`, `InventoryAdjustment`, `SaleInvoice`, `BusinessDaySaleInvoice`, `BusinessDay`, `PMSSaleInvoice`, `PMSBusinessDay`, `Unknown`. A cursor can also belong to one entity (`accountingDynamicEntityType`: `ProductCategory`, `Product`, `Location`, `Warehouse`, `PMSPropertyCode`, with its `dynamicEntityKey`).

## Change a cursor

**Query**

```graphql
mutation ChangeDocumentCursor($payload: DocumentCursorInputType!) {
  miscellaneous {
    changeDocumentCursor(payload: $payload) {
      accountingDocumentType
      accountingDynamicEntityType
      dynamicEntityKey
      cursorValue
      cursorData
    }
  }
}
```

**Variables**

```json
{
  "payload": {
    "accountingDocumentType": "PurchaseInvoice",
    "cursorValue": "<cursor value>"
  }
}
```

**cURL**

```bash
curl --location 'https://sandbox.expressoft.eu/connect/api/interopgql' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{"query": "mutation ChangeDocumentCursor($payload: DocumentCursorInputType!) { miscellaneous { changeDocumentCursor(payload: $payload) { accountingDocumentType accountingDynamicEntityType dynamicEntityKey cursorValue cursorData } } }", "variables": {"payload": {"accountingDocumentType": "PurchaseInvoice", "cursorValue": "<cursor value>"}}}'
```

**Response**

```json
{
  "data": {
    "miscellaneous": {
      "changeDocumentCursor": {
        "accountingDocumentType": "PurchaseInvoice",
        "accountingDynamicEntityType": null,
        "dynamicEntityKey": null,
        "cursorValue": "<cursor value>",
        "cursorData": "<cursor data>"
      }
    }
  }
}
```

| **Field**                     | **Type**                      | **Required** |
| ----------------------------- | ----------------------------- | ------------ |
| `accountingDocumentType`      | `AccountingDocumentType!`     | yes          |
| `cursorValue`                 | `String!`                     | yes          |
| `accountingDynamicEntityType` | `AccountingDynamicEntityType` | no           |
| `dynamicEntityKey`            | `String`                      | no           |

:::BlockQuote
⚠️ **WARNING**
Changing a cursor changes what Expressoft considers already synced. Test it in sandbox first.
:::

