# List All Transactions
Source: https://docs.procuros.io/en/api/v2/all-transactions/list-all-transactions
/en/api/v2/openapi-v2.yaml get /v2/all-transactions
List all existing transactions to and from your trade partners.
# Show Transaction
Source: https://docs.procuros.io/en/api/v2/all-transactions/show-transaction
/en/api/v2/openapi-v2.yaml get /v2/all-transactions/{procurosTransactionId}
Show a single transaction.
# Basics
Source: https://docs.procuros.io/en/api/v2/api-concepts
## API Versioning
We are constantly improving and expanding our API. In order to give you the choice of when (or if) you want to benefit from these changes, we are versioning our API. Our API follows standard [semantic versioning](https://semver.org/), which means we will introduce a new major version number in case new, backwards-incompatible changes are introduced to the Procuros API.
The API version is included in the path of every endpoint. Example: `https://api.procuros.io/v2/transactions` (`v2` shows this endpoint uses version 2)
Keep in mind, that purely additive changes are not considered backwards-incompatible, which means your system needs to
be able to handle new properties added to the JSON data returned by our API.
Use the version selector in the top lefthand corner of this page to adjust the API documentation to an older version.
## Date and Time
For datetime attributes, we are using the ISO8601 format. However, we recommend sending datetime attributes using the `Europe/Berlin` timezone. Furthermore, **all** datetime attributes returned by our API will be in `Europe/Berlin` timezone, regardless of what timezone was used when storing the record.
## Testing
You can use our **Staging environment** to test your interaction with the Procuros API, which protects you from accidentally sending transactions to your Trade Partners.
Our Staging and Production environments can easily be distinguished by the domain.
* Staging: `https://api.procuros-staging.io/v2`
* Production: `https://api.procuros.io/v2`
# Authentication
Source: https://docs.procuros.io/en/api/v2/concept-authentication
The Procuros API uses API tokens to authenticate requests. Please contact `[email protected]` to request an API token.
In order to perform an authenticated request, use the `Authorization` header to provide your API token as a "bearer token" like this: `Authorization: Bearer `.
All requests to all endpoints of our API have to be made using the above authentication method. Unauthenticated calls will fail with a `401` status code.
## Testing your Connection
Below are examples of how to ping the API to ensure your credentials are correct.
If you get a successful response from the enpoint, your authorization is confirmed. If you receive a `401 Unauthorized` error then your API key is not correct for this environment.
```bash bash theme={null}
curl --request GET \
--url 'https://api.procuros.io/v2/ping' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '
```
```php php theme={null}
$client = new \GuzzleHttp\Client();
$client->request('POST', 'https://api.procuros.io/v2/ping', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '
]
]);
$response->getStatusCode(); // => 200
```
## SSL Encryption
Requests to the Procuros API can only be made over HTTPS. Unsecured requests using HTTP will fail.
# Error Handling
Source: https://docs.procuros.io/en/api/v2/concept-error-handling
Standard HTTP response status codes are used to indicate the success or failure of a request made to the Procuros API. Status codes in the `2XX` range indicate success, codes in the `4XX` and `5XX` range indicate failure.
HTTP status codes that can be returned by the Procuros API:
| HTTP Status Code | Meaning |
| - | - |
| **400** - Bad Request | There was an issue with the request sent, such as a duplicate payload was sent. |
| **401** - Unauthorized | The API token is missing or invalid. |
| **403** - Forbidden | The API token doesn't have permission to perform this action. |
| **404** - Not Found | The requested entity (e.g. Transaction) could not be found. |
| **422** - Validation Failed | The request data is invalid. Responses contain `errors` that show what field failed validation and why. |
| **429** - Too Many Requests | You are calling the API too much. Check if you can use our bulk endpoints, otherwise contact support to get your rate limit increased. (won't happen to >99% of customers) |
| **500**, **502**, **503**, **504** - Server Error | An error occurred on Procuros side (rare cases) |
## Error Responses
To help you troubleshoot your interactions with the Procuros API, we've included further information within the responses returned from failed requests to the API.
| Property | Type | Description |
| - | - | - |
| `message` | string | Short error descriptions |
| `errors` | object | (Only on 422 "Validation Failed" Errors) Map of fields that failed validation including the corresponding validation error |
### Message
`4xx` range responses will always include the `message` property. For example in the case of a `400`, the `message` property will give you the reason why in English.
```json json theme={null}
{
"message": "Payload already received"
}
```
### Errors
For "Validation Failed" Client Errors (HTTP status code `422`), responses include an additional property `errors`, which list all request fields that failed validation and why.
Example:
```json json theme={null}
{
"message": "Invalid data provided.",
"errors": {
"type": [
"The selected type is invalid."
]
}
}
```
### Handling an Error
```php php theme={null}
$client = new \GuzzleHttp\Client();
$response = $client->request(...);
$statusCode = $response->getStatusCode();
if ($statusCode < 200 || $statusCode > 299) {
// handle error
// you likely want to check for the exact error codes
}
```
### Example
```php php theme={null}
$headers = [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
];
$transaction = [...]; // A transaction payload
$client = new \GuzzleHttp\Client();
$client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
'json' => $transaction,
]);
$statusCode = $response->getStatusCode();
if ($statusCode < 200 || $statusCode > 299) {
if ($statusCode === 400) {
\Sentry\captureMessage('BadPayloadSent', $transaction);
}
if ($statusCode === 422) {
\Sentry\captureMessage('ValidationError', $transaction);
}
if ($statusCode === 500) {
markDocumentForLaterRetry($transaction);
}
\Sentry\captureMessage('UnknownApiError', $transaction);
}
markDocumentAsProcessed($statusCode, $transaction);
```
### Error Handling Best Practises
The most common errors are related to missing or misconfigured data. Here is an example on how to handle these with the [Report Outgoing Error Request](/en/api/v2/outgoing-transactions/report-outgoing-error) endpoint.
```php php theme={null}
$client = new \GuzzleHttp\Client(); $client->request('POST', 'https://api.procuros.io/v2/errors', [
'headers' => $headers, 'json' => [ 'errorReason' => 'Data XYZ could not be found.', 'errorType' => 'INTERNAL',
'errorContext' => [ 'meta' => 'value' ], 'transactionIdentifier' => 'bestellung-20231203-001', 'transactionType' =>
'ORDER', ], ]);
```
#### Best Practise: Missing GTIN
* Set `errorType` to: `DATA`.
* Set the `errorReason` to: `The GTIN/EAN :gtin couldn't be found` and set up the gtin variable accordingly
# Pagination
Source: https://docs.procuros.io/en/api/v2/concept-pagination
For some of our resources (eg. transactions), a "list" endpoint exists to fetch resources in bulk.
These endpoints use a "cursor-based pagination", which means you can use the `per_page` and `cursor` query parameters to step through large collections page by page.
### Requests
Requests to paginated "list" endpoints accept the following query parameters:
| Parameter | Type | Description |
| - | - | - |
| `cursor` | String (optional) | Cursor pointing to the beginning of a page |
| `per_page` | Integer (optional) | Amount of resources that should be returned. (1-100. Default: 25) |
### Responses
All requests to those paginated "list" endpoints have the following response properties:
| Property | Type | Description |
| - | - | - |
| `items` | Array | Array containing the listed resources (eg. transactions) |
| `hasMore` | Boolean | Whether or not there are more resources to be fetched after this page |
| `perPage` | Integer | Amount of resources returned per page |
| `count` | Integer | Amount of resources on the current page |
| `nextCursor` | String \| Null | Cursor pointing to the beginning of the next page (Use the `cursor` query parameter value to get the next page of resources) |
| `nextPageUrl` | String \| Null | URL pointing to the next page of resources (prebuilt for your convenience) |
**Example Response:**
```json json theme={null}
{
"items": [
{...},
{...}
],
"hasMore": true,
"perPage": 50,
"count": 50,
"nextCursor": "kdfhh87sdkfjslasdf7hsbadf",
"nextPageUrl": "https://api.procuros.io/v2/transactions?cursor=kdfhh87sdkfjslasdf7hsbadf"
}
```
### Workflow
1. Make a request to the "list" endpoint without the `cursor` query parameter to fetch the first page of resources. Optionally use the `per_page` query parameter to limit the number of resources to fetch. Example: `GET https://api.procuros.io/v2/transactions`
2. From the response, read the `hasMore` property to determine if there are more resources to fetch on subsequent pages.
3. If more resources are available, use the `nextCursor` property on the response to build the URL of your next request. Alternatively, use the `nextPageUrl` that we've prebuilt for you. Example: `GET https://api.procuros.io/v2/transactions?cursor=kdfhh87sdkfjslasdf7hsbadf`
4. Continue with step 2.
# Bulk Mark Transactions Processed
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/bulk-mark-transactions-processed
/en/api/v2/openapi-v2.yaml post /v2/transactions/bulk/mark-processed
Mark a list of incoming transactions as processed in a single request.
For each item, set `success` to `true` once the transaction has been processed, or `false` if processing failed (optionally with an `errorReason`, `errorType`, and `errorContext`).
Transactions previously reported as failed can be recovered by including them again with `success: true` once the issue has been resolved on your side. They move to the delivered state and their associated errors are resolved automatically.
# List Incoming Transactions
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/list-incoming-transactions
/en/api/v2/openapi-v2.yaml get /v2/transactions
List unprocessed incoming transactions from your trade partners.
# Mark Transaction Processed
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/mark-transaction-processed
/en/api/v2/openapi-v2.yaml put /v2/transactions/{procurosTransactionId}
Report whether your system processed an incoming transaction.
Set `success` to `true` once the transaction has been processed, or `false` if processing failed (optionally with an `errorReason`, `errorType`, and `errorContext`).
If a transaction was previously reported as failed, you can recover it by calling this endpoint again with `success: true` once the issue has been resolved on your side (for example, after correcting missing master data in your system). The payload is reused from your system, so there is no need to fetch the transaction again: it moves to the delivered state and its associated error is resolved automatically.
# Test connection to API
Source: https://docs.procuros.io/en/api/v2/misc/test-connection-to-api
/en/api/v2/openapi-v2.yaml get /v2/ping
Send an authorized request to the API to test the connectivity.
# Report Outgoing Error
Source: https://docs.procuros.io/en/api/v2/outgoing-transactions/report-outgoing-error
/en/api/v2/openapi-v2.yaml post /v2/errors
If you encounter an error while building an outgoing transaction payload, you can report it here. The error will enter the same exception handling process as an error reported while processing incoming transactions.
# Send Transaction
Source: https://docs.procuros.io/en/api/v2/outgoing-transactions/send-transaction
/en/api/v2/openapi-v2.yaml post /v2/transactions
Create and send a new transaction to one of your trade partners.
# Overview
Source: https://docs.procuros.io/en/api/v2/overview
Welcome to the Procuros API. You are currently reading the documentation for API V2.
The Procuros API is the recommended way of integrating with the Procuros Network in order to exchange business transactions with your Trade Partners.
Our API follows RESTful patterns, accepts and returns JSON-encoded data and uses standard HTTP verbs and response codes.
## OpenAPI Specification
The complete OpenAPI specification for the Procuros API v2 is available in raw format for easy integration with your development tools:
Access the complete OpenAPI specification file to use with tools like Postman, Insomnia, or other API development tools.
## Incoming Transactions
### Retrieving and Processing Transactions
To retrieve unprocessed incoming transactions from Procuros, we recommend using a cron job/interval for simplicity.
Looping through the list of retrieved transactions, you will try to process/import them. See our [Quick Start Guide](/en/api/v2/quick-start) for an example how this can be done.
### Reporting Processing Status
Once you have looped through the unprocessed transactions and attempted to process them you will report back whether processing was successful or not.
If a transaction could not be processed, you will send across an error reason and level. This will trigger the exception handling flow:
* An e-mail notification will be sent to the responsible party for resolution
* The error will show up in the Procuros Portal together with the error reason for self-service resolution by the responsible party.
## Outgoing Transactions
### Retrieving and Preparing Documents
To retrieve new unprocessed documents from the ERP system that should be sent via Procuros we recommend using a cron job/interval that runs every 10-30 minutes for simplicity reasons, but you are free to make this event-based as well.
To know which documents should be sent via Procuros, a list of “enabled” customers and suppliers needs to be maintained. This is explained in detail on [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners). Generally, all outgoing documents for an “enabled” Trade Partner (shipping notices, invoices, etc. for customers and orders for suppliers) should be sent via Procuros. We will handle routing and inactive trade relationships. More on that later.
For every document that fulfils the above criteria, you will build the “transaction payload” according to the [API specification](/en/api/v2/incoming-transactions/list-incoming-transactions)) corresponding to the document type (order, shipping notice, etc.).
### Sending Transactions
If you are able to successfully build and send a transaction payload to Procuros, we will respond in one of three ways:
1. For documents Procuros intends to forward to the receiving trade partner, the Procuros API responds with an `201: Created` status code and you should mark the document as `TRANSMITTED`.
2. If we determine the transaction should **not** be forwarded to the trade partner (eg. because the trade relationship is not yet active or documents of that type are not currently accepted by the receiving trade partner), the Procuros API will respond with an `202: Accepted` status code and you will mark the document as `NO_ACTION` to indicate to users that the document was accepted by Procuros but will not be forwarded. More on this in [Tracking Document Status](/en/api/v2/features-tracking-document-status).
3. If the transaction payload sent by you contains errors, the Procuros API will respond with a `422: Validation Error`. More on this below.
4. If a different error occurs, such as `PayloadAlreadyReceived` then this will be reported back via the status code `400: Bad Request`.
### Handling Errors
If you were not able to successfully build the transaction payload to be sent via Procuros you will send an error payload instead to trigger the Exception Handling flow and allow the responsible parties to fix the underlying issue (i.e. change or add information in the unprocessed document). Error reasons could be e.g. missing GLNs or GTIN/EAN codes.
When you send an error payload to the Procuros API, we will respond with an **Error Url** that points to the error within the Procuros Portal. You can attach the Link to the document for which you were unable to build the transaction payload giving your user an easy way to resolve the error fast.
You will also receive an Error Url in case the transaction payload you sent is invalid and the Procuros API responds with `422: Validation Error`.
In any case, you will re-try sending the document until it succeeds.
## Transport Labels
Transport units on Shipping Notice and Dispatch Instruction Response transactions can carry a Procuros-generated SSCC transport label. It is returned as a `transportLabel` object with a `zplUrl` and a `pdfUrl`, giving you the raw ZPL and the rendered PDF version of the same label.
To download the file content, call the [Download Transport Label](/en/api/v2/all-transactions/download-transport-label) endpoint using the value of either URL as the `transportLabelUrl` path parameter. The endpoint requires the same API token as the other endpoints and streams the file content back for download.
# Quick Start
Source: https://docs.procuros.io/en/api/v2/quick-start
In this guide, we will go through the process of setting up an API connection, and a few basic endpoints that you can use for EDI document management.
We will use PHP as the example language but you can translate the examples to any programming language you desire.
## Connecting to the API
We assume for this PHP example that `Guzzle` is installed and available to the script.
```php php theme={null}
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', '', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
## Listing Documents
Following on from this, you can use the connection to list orders from your trade partners.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
All types of documents are returned from this API call. In order to filter for a specific type, you may pass the `filter` URL parameter. For example:
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER', [
'headers' => $headers,
]);
```
For a list of all available parameters, please see the [List Incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) API reference.
## Sending Documents
Similar to listing documents, you can use the connection to send documents to your trade partners.
```php php theme={null}
$transaction = [
"type": "ORDER",
"content": [
"header": [
"orderIdentifier": "bestellung-20231203-001",
"orderDate": "2023-12-03",
"currency": "EUR",
"requestedDeliveryDate": "2023-12-06",
"buyer": ["identifiers": [["domain": "GS1", "identifier": "3220010000001" ]]],
"supplier": ["identifiers": [["domain": "GS1", "identifier": "3220010000013" ]]],
"billTo": ["identifiers": [["domain": "GS1", "identifier": "3220010000001" ]]],
"shipTo": ["identifiers": [["domain": "GS1", "identifier": "3220010000003" ]]],
],
"items": [
[
"identifiers": [["domain": "GS1", "identifier": "2330000000007" ]],
"lineNumber": 1,
"quantity": 10,
"isDepositItem": false,
"unitOfMeasure": "EA",
"description": "A description of the item",
"requestedDeliveryDate": null,
"unitPrice": 1.23
]
]
]
];
$client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
'json' => $transaction,
]);
```
For a list of all available document types that can be created, as well as the JSON body format for each, please see the [Send Transaction](/en/api/v2/outgoing-transactions/send-transaction) API reference.
# Credit Notes
Source: https://docs.procuros.io/en/api/v2/receiving-credit-notes
This is the right section for you if you are acting as a customer and looking to receive credit notes from your suppliers.
In this guide you will learn how to receive new credit notes from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the credit notes.
It is important to mark the credit notes as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Credit Notes
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `CREDIT_NOTE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=CREDIT_NOTE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `CREDIT_NOTE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'CREDIT_NOTE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Credit Note as Processed
To mark an credit note as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Credit Notes as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Credit Note
In the event an credit note was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these credit notes as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the credit note not being processed, which will be used for solving the issue.
### Single Credit Note
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Dispatch Instruction Responses
Source: https://docs.procuros.io/en/api/v2/receiving-dispatch-instruction-responses
This is the right section for you if you are acting as a supplier and looking to receive dispatch instruction responses from a fulfillment provider.
In this guide you will learn how to receive new dispatch instruction responses from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the dispatch instruction responses.
It is important to mark the dispatch instruction responses as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Dispatch Instruction Responses
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `DISPATCH_INSTRUCTION_RESPONSE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=DISPATCH_INSTRUCTION_RESPONSE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `DISPATCH_INSTRUCTION_RESPONSE` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'INVOICE' || $item->type === 'DISPATCH_INSTRUCTION_RESPONSE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Dispatch Instruction Response as Processed
To mark an dispatch instruction response as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Dispatch Instruction Responses as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing Dispatch Instruction Response
In the event an dispatch instruction response was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these dispatch instruction responses as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the dispatch instruction response not being processed, which will be used for solving the issue.
### Single Dispatch Instruction Response
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Dispatch Instructions
Source: https://docs.procuros.io/en/api/v2/receiving-dispatch-instructions
This is the right section for you if you are acting as a fulfillment provider and looking to receive dispatch instructions from suppliers.
In this guide you will learn how to receive new dispatch instructions from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the dispatch instructions.
It is important to mark the dispatch instructions as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Dispatch Instructions
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `DISPATCH_INSTRUCTION`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=DISPATCH_INSTRUCTION', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `DISPATCH_INSTRUCTION` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'INVOICE' || $item->type === 'DISPATCH_INSTRUCTION';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Dispatch Instruction as Processed
To mark an dispatch instruction as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Dispatch Instructions as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing Dispatch Instruction
In the event an dispatch instruction was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these dispatch instructions as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the dispatch instruction not being processed, which will be used for solving the issue.
### Single Dispatch Instruction
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Invoices
Source: https://docs.procuros.io/en/api/v2/receiving-invoices
This is the right section for you if you are acting as a customer and looking to receive invoices from your suppliers.
In this guide you will learn how to receive new invoices from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the invoices.
It is important to mark the invoices as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Invoices
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `INVOICE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=INVOICE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `INVOICE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'INVOICE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Invoice as Processed
To mark an invoice as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Invoices as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Invoice
In the event an invoice was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these invoices as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the invoice not being processed, which will be used for solving the issue.
### Single Invoice
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Order Responses
Source: https://docs.procuros.io/en/api/v2/receiving-order-responses
This is the right section for you if you are acting as a customer and looking to receive Order Responses from your suppliers.
In this guide you will learn how to receive new Order Responses from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the Order Responses.
It is important to mark the Order Responses as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Order Response Types
Order Responses can have one of three types:
* **ACCEPT**: The order was accepted exactly as ordered
* **REJECT**: The order was fully rejected
* **CHANGE**: Part of the order was accepted but either line item quantities or delivery date are changed
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Order Responses
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `ORDER_RESPONSE`.
In this case, the easiest way to achieve the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER_RESPONSE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `ORDER_RESPONSE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'ORDER_RESPONSE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Order Response as Processed
To mark an Order Response as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Order Responses as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Order Response
In the event an Order Response was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these Order Responses as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the Order Response not being processed, which will be used for solving the issue.
### Single Order Response
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Unknown order identifier referenced'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Unknown order identifier referenced'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Orders
Source: https://docs.procuros.io/en/api/v2/receiving-orders
This is the right section for you if you are acting as a supplier and looking to receive orders from your customers.
Throughout this guide you will learn how to pull new orders from the Procuros API, as well as how to paginate over them, mark them as processed, or report errors with the orders.
It is important to mark the orders as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as "processing failed".\*\*\*\*
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/incoming-transactions/list-incoming-transactions).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Process
Incoming orders retrieved from the Procuros API can be imported into the ERP System.
These are usually the steps taken:
1. Uniquely identify customer (see [Trade Partner + Party Identification](/en/api/v2/features-trade-partner-party-identification))
2. Uniquely identify every product ordered (see [Product Identification](/en/api/v2/features-product-identification))
3. Handle Bottle Deposits (see [Bottle Deposits](/en/api/v2/features-bottle-deposits))
4. Resolve customer-specific prices for products (if not done automatically by ERP-System)
### Rules
As a general rule of thumb: An order retrieved from Procuros and one manually entered by a user should be exactly the same. One exception could be some way to indicate the “source” of the order being “Procuros” instead of “Manual”, “Shopify”, or something else.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a 2xx status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Orders
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
The Order response includes all header and item level fields, including:
* **Header level**: `attachments`, `finalRecipient` party, `technicalRecipient` party, `technicalSender` party, and other party information
* **Item level**: `attachments`, product specifications, dimensions, certifications, and other item details
Refer to the OpenAPI schema documentation for the complete list of available fields.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark Orders as Processed
To mark an order as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Orders as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check the request was successful
```
## Report an Error Processing Orders
In the event an order was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these orders as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the order not being processed, which will be used for solving the issue.
### Single Order
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Missing shipping details in order'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Missing shipping details in order'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Product Catalogs
Source: https://docs.procuros.io/en/api/v2/receiving-product-catalogs
This is the right section for you if you are acting as a customer and looking to receive Product Catalogs from your suppliers.
In this guide you will learn how to receive new Product Catalogs from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the Product Catalogs.
It is important to mark the Product Catalogs as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Product Catalog
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `PRODUCT_CATALOG`.
In this case, the easiest way to achieve the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=PRODUCT_CATALOG', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `PRODUCT_CATALOG` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'PRODUCT_CATALOG';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Product Catalog as Processed
To mark an Product Catalog as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Product Catalogs as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing a Product Catalog
In the event an Product Catalog was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these Product Catalogs as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the Product Catalog not being processed, which will be used for solving the issue.
### Single Product Catalog
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Price missing on line item 10'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Price missing on line item 10'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Sales Reports
Source: https://docs.procuros.io/en/api/v2/receiving-sales-report
This is the right section for you if you are acting as a supplier and looking to receive sales reports from your buyers.
Throughout this guide you will learn how to pull new sales reports from the Procuros API, as well as how to paginate over them, mark them as processed, or report errors with the sales reports.
It is important to mark the sales reports as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as "processing failed".\*\*\*\*
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/incoming-transactions/list-incoming-transactions).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a 2xx status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Sales Reports
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=SALES_REPORT', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark Sales Reports as Processed
To mark a sales report as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Sales Reports as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check the request was successful
```
## Report an Error Processing Sales Reports
In the event a sales report was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these sales reports as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the sales report not being processed, which will be used for solving the issue.
### Single Sales Report
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Missing location details in sales report'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Missing location details in sales report'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Shipping Notices
Source: https://docs.procuros.io/en/api/v2/receiving-shipping-notices
This is the right section for you if you are acting as a customer and looking to receive shipping notices from your suppliers.
In this guide you will learn how to receive new shipping notices from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the shipping notices.
It is important to mark the shipping notices as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Shipping Notices
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `SHIPPING_NOTICE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=SHIPPING_NOTICE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `SHIPPING_NOTICE` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'INVOICE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Shipping Notice as Processed
To mark a shipping notice as processed, and take it out of the incoming transactions queue, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Shipping Notices as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Shipping Notice
In the event a shipping notice was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these shipping notices as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the shipping notice not being processed, which will be used for solving the issue.
### Single Shipping Notice
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Order Responses
Source: https://docs.procuros.io/en/api/v2/sending-order-responses
This is the right section for you if you are acting as a supplier and looking to send Order Responses to your customers in response to their orders.
Throughout this guide you will learn how to send Order Responses to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Order Response Types
Order Responses can have one of three types:
* **ACCEPT**: Use when the order is accepted exactly as ordered. The `items` array is optional — omit it to confirm all lines as-is, or include it to selectively confirm specific items with adjusted quantities or dates.
* **REJECT**: Use when the order is fully rejected. The `items` array must not be included.
* **CHANGE**: Use when part of the order is accepted but either line item quantities or delivery date are changed. The `items` array is required and must contain ALL order line items.
Omitting `type` (or setting it to `null`) is treated identically to `REJECT` — the `items` array is prohibited and the order is considered fully rejected. Always provide an explicit `type` to avoid unintended rejections.
## Process
These are usually the steps taken when sending an Order Response to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Order Responses
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including Order Responses.
The following fields are required:
* `type` (Transaction type. In this case `ORDER_RESPONSE`)
* `content` (The details of the Order Response)
Inside the `content` you will need to build the Order Response header and optionally items. All details can be found in the `ORDER_RESPONSE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
### Example: ACCEPT Response
Use this when accepting an order exactly as ordered:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'ACCEPT',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'requestedDeliveryDate' => '2024-01-20',
'confirmedDeliveryDate' => '2024-01-20',
'confirmedShipmentDate' => '2024-01-18',
'currency' => 'EUR'
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
### Example: REJECT Response
Use this when fully rejecting an order:
```php php theme={null}
$transaction = [
'type' => 'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'REJECT',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'currency' => 'EUR',
'comments' => 'Order rejected due to product unavailability'
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
### Example: CHANGE Response
Use this when partially accepting an order with quantity or delivery date changes. The items array must contain ALL order line items, showing both ordered and confirmed quantities:
```php php theme={null}
$transaction = [
'type' => 'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'CHANGE',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'requestedDeliveryDate' => '2024-01-20',
'confirmedDeliveryDate' => '2024-01-22',
'confirmedShipmentDate' => '2024-01-20',
'currency' => 'EUR',
'comments' => 'Partial fulfillment due to limited stock'
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
['domain' => 'GS1', 'identifier' => '4300348765432']
],
'isDepositItem' => false,
'orderedQuantity' => 20.0,
'confirmedQuantity' => 15.0,
'unitOfMeasure' => 'EA',
'description' => 'First product description',
'unitPrice' => 0.15,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100
],
[
'lineNumber' => 2,
'identifiers' => [
['domain' => 'GS1', 'identifier' => '4300348765433']
],
'isDepositItem' => false,
'orderedQuantity' => 19.0,
'confirmedQuantity' => 19.0,
'unitOfMeasure' => 'EA',
'description' => 'Second product description',
'unitPrice' => 1.50,
'pricingUnitOfMeasure' => 'CT'
'pricingUnitQuantity' => 100,
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
When using the `CHANGE` type, the `items` array must contain ALL order line items, regardless of whether `orderedQuantity` and `confirmedQuantity` are equal. This allows the buyer to see the complete picture of what will be delivered.
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Orders
Source: https://docs.procuros.io/en/api/v2/sending-orders
This is the right section for you if you are acting as a customer and looking to send orders to your suppliers.
Throughout this guide you will learn how to send new orders to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an order to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Orders
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including orders.
The following fields are required:
* `type` (Transaction type. In this case `ORDER`)
* `content` (The details of the order items.)
Inside the `content` you will need to build all order items. All details can be found in the `ORDER` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
The example below shows commonly used fields. The Order schema supports many additional optional fields including:
* **Header level**: `deliveryInformation`, `purchasingInformation`, `legalInformation`, `attachments`, `finalRecipient` party, `technicalRecipient` party, `technicalSender` party
* **Item level**: `size`, `dimension`, `hsCode`, `cnCode`, `colorCode`, `colorName`, `fscNumber`, `deliveryGracePeriodInDays`, `certificationsRequired`, `attachments`
**Date format**: All date fields (e.g. `orderDate`, `requestedDeliveryDate`) must use ISO 8601 format: `YYYY-MM-DD` (e.g. `2023-12-06`).
For the complete list of available fields, refer to the OpenAPI schema documentation.
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'ORDER',
'content' => [
'header' => [
'orderIdentifier' => 'bestellung-20231203-012',
'orderDate' => '2023-12-03',
'currency' => 'EUR',
'requestedDeliveryDate' => '2023-12-06',
'type' => 'STANDARD',
'comments' => 'Please deliver to loading dock 3',
'contractReference' => 'CONTRACT-2023-ABC',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000003']
]
],
'billTo' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'shipTo' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000011']
]
],
'technicalRecipient' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'technicalSender' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000012']
]
],
'AdditionalOrderIdentifiers' => [
'supplierOrderIdentifier' => 'SUP-ORDER-789',
'shipToOrderIdentifier' => 'SHIP-REF-456'
],
'paymentTerms' => [
[
'payInNumberOfDays' => 30,
'percentage' => 5
]
]
],
'items' => [
[
'identifiers' => [
['domain' => 'GS1', 'identifier' => '2330000000083']
],
'lineNumber' => 1,
'quantity' => 10,
'isDepositItem' => false,
'unitOfMeasure' => 'EA',
'description' => 'Premium Organic Coffee Beans 1kg',
'comments' => 'Please handle with care - fragile packaging',
'requestedDeliveryDate' => null,
'requestedEarliestDeliveryDate' => '2023-12-05',
'requestedLatestDeliveryDate' => '2023-12-08',
'minimumRemainingShelfLifeInDays' => 90,
'unitPrice' => 1.23,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'recommendedRetailPrice' => 1.85,
'netWeight' => 1000,
'grossWeight' => 1050,
'originCountryCode' => 'BR',
'tax' => [
'percentage' => 7,
'description' => 'Umsatzsteuer'
],
'brand' => 'kela',
'assortment' => 'ME_GEN',
'consumerGroup' => 'Unisex',
'category' => '1008',
'subCategory' => 'Beverages',
'organicControlPointNumber' => 'DE-ÖKO-006',
'certificationsRequired' => [
'fairtrade' => true,
'supplierQa' => false,
'eudr' => true
],
'contractReference' => 'ITEM-CONTRACT-XYZ',
'promotionCode' => 'WINTER2023',
'attachments' => [
[
'fileName' => 'technical_datasheet.pdf',
'url' => 'https://example.com/attachments/technical_datasheet.pdf',
'mimeType' => 'application/pdf',
'type' => 'TECHNICAL_DATASHEET'
],
[
'fileName' => 'product_label.pdf',
'url' => 'https://example.com/attachments/product_label.pdf',
'mimeType' => 'application/pdf',
'type' => 'PRODUCT_LABEL'
]
],
'modificationGroups' => [
[
'basis' => 12.30,
'level' => 1,
'modifications' => [
[
'type' => 'ALLOWANCE',
'calculationType' => 'RELATIVE',
'reasonCode' => 'DISCOUNT',
'description' => 'Contract trade discount',
'percentage' => 7
]
]
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Product Catalogs
Source: https://docs.procuros.io/en/api/v2/sending-product-catalogs
This is the right section for you if you are acting as a supplier and looking to send product catalogs to your customers.
Throughout this guide you will learn how to send product catalogs to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an product catalog to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send product catalogs
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including product catalogs.
The following fields are required:
* `type` (Transaction type. In this case `PRODUCT_CATALOG`)
* `content` (The details of the product catalogs items.)
Inside the `content` you will need to build all product catalogs items. All details can be found in the `PRODUCT_CATALOG` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"PRODUCT_CATALOG",
"content" => [
"header" => [
"sender" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Test Sender GmbH",
"street" => "Musterstraße 1",
"addressExtra" => "c/o Max Mustermann",
"city" => "Entenhausen",
"postalCode" => "123456",
"countryCode" => "DE"
],
"name" => "Test Sender GmbH"
],
"receiver" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Test Receiver GmbH",
"street" => "Lilienstraße 36",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
],
"name" => "Test Receiver GmbH"
],
"catalogNumber" => "Summer 2025",
"catalogDate" => "2024-06-01"
],
"items" => [
[
"unitOfMeasure" => "EA",
"identity" => [
"senderPartnerId" => "PRD-0001",
"receiverPartnerId" => "AB-MM-9988",
"gtin" => "12345678901234",
],
"lineNumber" => 12,
"quantity" => 5,
"action" => "NEW",
"currency" => "EUR",
"isOrderable" => true,
"unitPrice" => 44.23,
"pricingUnitOfMeasure" => "CT",
"pricingUnitQuantity" => 100,
"description" => "Description/Name of the product",
"hsCode" => "222222",
"isDangerous" => false,
"hasExpiryDate" => false,
"hasBatchNumber" => false,
"hasSerialNumber" => false,
"originCountryCode" => "US",
"nutritionalInformation" => [
"energy" => [
"totalInKcal" => 250.5,
"totalInKj" => 1047.2
],
"fats" => [
"totalInGrams" => 15.2,
"saturatedInGrams" => 3.5,
"monounsaturatedInGrams" => 6.8,
"polyunsaturatedInGrams" => 4.9
],
"carbohydrates" => [
"totalInGrams" => 30.5,
"sugarsInGrams" => 8.2
],
"proteins" => [
"totalInGrams" => 12.5
],
"saltInGrams" => 0.8,
"vitamins" => [
"vitaminCInMicrograms" => 80.0
]
],
"additives" => [
[
"identifiers" => [
"gdsn" => "E300",
"senderInternal" => "ADD-001"
],
"name" => "Ascorbic Acid (Vitamin C)"
]
],
"certifications" => [
"eudr" => [
"verificationNumber" => "FAHLHGK7",
"referenceNumber" => "24ITYGBJFOS258"
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Shipping Notices
Source: https://docs.procuros.io/en/api/v2/sending-shipping-notices
This is the right section for you if you are acting as a supplier and looking to send shipping notices to your customers.
Throughout this guide you will learn how to send shipping notices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a shipping notice:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
1. If products being shipped are perishable and thus require shelf-life tracking, batch information needs to be added (see: [Batches & Best Before Dates](/en/api/v2/features-batches-best-before-dates))
2. If you are sending large shipments on Euro Pallets, additional shipment identification needs to be provided. (see: [Package Identification](/en/api/v2/features-package-identification))
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Shipping Notices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including shipping notices.
The following fields are required:
* `type` (Transaction type. In this case `SHIPPING_NOTICE`)
* `content` (The details of the shipping notice items.)
Inside the `content` you will need to build all shipping notice items. All details can be found in the `SHIPPING_NOTICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
Each item in `transportUnits` must have a `unitType`. The following values are supported:
| Value | Description |
| - | - |
| `EURO_PALLET` | Euro Pallet (120 × 80 cm) |
| `EURO_PALLET_HALF` | 1/2 Euro Pallet (80 × 60 cm) |
| `EURO_PALLET_QUARTER` | 1/4 Euro Pallet (60 × 40 cm) |
| `PALLET` | Generic / non-Euro pallet |
| `PACKAGE` | Package |
| `CARTON` | Carton |
| `CONTAINER` | Shipping container |
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'SHIPPING_NOTICE',
'content' => [
'header' => [
'buyer' => [
'name' => 'ACME Co. Ltd.',
'identifiers' => [
[
'identifier' => '3220010000005',
'domain' => 'GS1'
]
]
],
'supplier' => [
'name' => 'Testsupplier',
'identifiers' => [
[
'identifier' => '3220010000010',
'domain' => 'GS1'
]
]
],
'shipTo' => [
'identifiers' => [
[
'identifier' => '3220010000005',
'domain' => 'GS1'
]
]
],
'billTo' => [
'identifiers' => [
[
'identifier' => '3220010000006',
'domain' => 'GS1'
]
]
],
'technicalRecipient' => [
'identifiers' => [
[
'identifier' => '3220010000006',
'domain' => 'GS1'
]
]
],
'technicalSender' => [
'identifiers' => [
[
'identifier' => '3220010000007',
'domain' => 'GS1'
]
]
],
'shippingNoticeIdentifier' => 'SN9383-R45',
'shippingNoticeDate' => '2021-11-24',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2021-11-20',
'despatchDate' => '2021-11-05',
'requestedDeliveryDate' => '2021-11-06',
'expectedDeliveryDate' => '2021-11-06'
],
'transportUnits' => [
[
'unitIdentifier' => '34000000000001',
'unitType' => 'EURO_PALLET',
'containedTradeUnitCount' => 10,
'items' => [
[
'lineNumber' => 1,
'orderLineNumber' => 1,
'orderIdentifier' => 'PO9383-R45',
'identifiers' => [
[
'identifier' => '2330010000061',
'domain' => 'GS1'
],
[
'identifier' => 'filter-coffee',
'domain' => 'BUYER'
],
[
'identifier' => 'supplier-filter-coffee',
'domain' => 'SUPPLIER'
]
],
'isDepositItem' => false,
'orderedQuantity' => 20,
'shippedQuantity' => 20,
'description' => 'First product description.',
'certifications' => [
'eudr' => [
'verificationNumber' => 'FAHLHGK7',
'referenceNumber' => '24ITYGBJFOS258'
]
],
'batches' => [
[
'batchIdentifier' => 'BATCH_ID_1',
'expirationDate' => '2022-12-24',
'quantity' => 15
],
[
'batchIdentifier' => 'BATCH_ID_2',
'expirationDate' => '2022-12-31',
'quantity' => 5
]
]
],
[
'lineNumber' => 2,
'orderLineNumber' => 2,
'orderIdentifier' => 'PO9383-R45',
'identifiers' => [
[
'identifier' => '2330010000019',
'domain' => 'GS1'
],
[
'identifier' => 'bread-crumbs-bulk',
'domain' => 'BUYER'
],
[
'identifier' => 'supplier-bread-crumbs-bulk',
'domain' => 'SUPPLIER'
]
],
'isDepositItem' => false,
'orderedQuantity' => 19,
'shippedQuantity' => 15,
'openQuantityAction' => 'DISCARDED',
'batches' => [
[
'batchIdentifier' => 'BATCH_ID_2',
'expirationDate' => '2022-05-01',
'quantity' => 15
]
],
'description' => 'Sparkling Water - Crate (6x0.75l).'
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
## Advanced Use Cases
When it comes to sending shipping notices, there are a number of advanced cases, such as [Bottle Deposits](/en/api/v2/features-bottle-deposits), [Batches & Best Before Dates](/en/api/v2/features-batches-best-before-dates) and [Package Identification](/en/api/v2/features-package-identification).
Please see the Features section of our API reference for a detailed description of all advanced use cases.
# Download Transport Label
Source: https://docs.procuros.io/en/api/v2/transport-labels/download-transport-label
/en/api/v2/openapi-v2.yaml get /v2/transactions/{transportLabelUrl}/download
Download the file content of a transport label. Use the value of the `zplUrl` or `pdfUrl` field from the `transportLabel` object of a transport unit (available on Shipping Notice and Dispatch Instruction Response transactions) as the `transportLabelUrl` path parameter, depending on whether you want the raw ZPL or the rendered PDF. The response is the streamed file content for download.
# Procuros AS2 Details
Source: https://docs.procuros.io/en/connectors/as2/as2
Technical information for connecting to Procuros via AS2
The AS2 connection from Procuros enables secure and reliable electronic data exchange between you and your trading partners. This technical documentation contains all necessary parameters for configuring your AS2 connection.
## Technical Contact Person
If you have questions about AS2 setup or connection issues, the following contact options are available:
* Email: [help@procuros.io](mailto:help@procuros.io)
## Connection Addresses
Use one of the following endpoint addresses for configuration:
* HTTPS: `https://as2.procuros.io/receive/v1` (Port: 443)
* HTTP: `http://as2.procuros.io/receive/v1` (Port: 80)
AS2 Identifier: `procuros`
## Technical Details
The following settings are required for a successful AS2 connection with Procuros:
* Message Encryption: Yes (Algorithm: 3DES)
* Message Compression: No
* Message Signing: Yes (Algorithm: SHA1)
* MDN: Yes
* Mode: Sync
* Signed: Yes (Algorithm: SHA1)
These configuration details can be used for both production and test environments.
## IP Addresses
### Outgoing IP Addresses
Procuros uses the following outgoing IP addresses when your AS2 server is addressed:
```
51.116.233.35, 51.116.171.49, 51.116.233.33, 51.116.233.22, 51.116.168.104, 51.116.175.17, 51.116.233.87, 51.116.175.51, 20.113.11.136, 20.113.11.85, 20.113.10.168, 20.113.8.64, 3.70.10.129, 3.76.51.85, 52.28.170.162, 52.59.155.142
```
### Incoming IP Addresses
The Procuros AS2 server can be reached at the following incoming IP addresses:
```
20.101.181.60, 35.157.232.59, 35.159.186.102
```
Ensure that these IP addresses are whitelisted in your firewalls and security systems to ensure smooth communication.
## Certificates
For encrypted communication, you need the Procuros certificates. These are available in various formats:
* procuros\_as2\_certificate.cer
* procuros\_as2\_certificate.txt
* procuros\_as2\_certificate.pem
* procuros\_as2\_certificate.p7b
Download the certificate in the required format from the list above.
Import the certificate into your AS2 software according to the instructions from your AS2 provider.
## Frequently Asked Questions
Yes, the AS2 connection can be used for both environments.
# Troubleshooting Common Errors
Source: https://docs.procuros.io/en/connectors/ms-business-central/common-errors
Overview of common errors and how to fix them in MS Business Central
## Troubleshooting Common Errors
Below you will find an overview of the most common errors (import, export, status) and how you can fix them.
### Import Error


### Export Error


### Status Error



# Overview MS Business Central Connector
Source: https://docs.procuros.io/en/connectors/ms-business-central/getting-started/overview
Overview of the capabilities and benefits of the Procuros MS Business Central Connector
## Overview of the MS Business Central Connector
The Procuros MS Business Central Connector enables integration between your Microsoft Dynamics 365 Business Central system and the Procuros platform, allowing automated exchange of business documents between you and your business partners.
## Supported Document Types
The MS Business Central Connector currently supports the following document types:
Receiving:
* Orders
* Confirm/Reject Orders
Sending:
* Delivery Notes
* Invoices
## Benefits of Integration
* **Optimized Workflows**: Streamlines data exchange between you and your business partners.
* **Enhanced Capabilities**: Includes support for discounts, deposit items, product hierarchies, and batches.
* **Automated Document Handling**: Procuros seamlessly processes business documents automatically.
# Technical Setup
Source: https://docs.procuros.io/en/connectors/ms-business-central/getting-started/technical-setup
Learn how to set up Microsoft Business Central integration with Procuros
Learn how to give Procuros access to your Business Central system and set the correct permissions & settings.
## Installing the app
To connect Business Central to Procuros, you need the "simple\_EDI" app.
Depending on whether your Business Central instance is hosted in the cloud or on-premise, you can download the app from [Microsoft App Source](https://appsource.microsoft.com/en-us/product/dynamics-365-business-central/pubid.mp-solutions%7Caid.mp_simpleedi%7Cpappid.46655971-0727-4a01-93c2-35e7facb1ab9?tab=overview) or contact us for the download link for on-premise installation.
In the case of an on-premise installation, please provide us with your partner's PSBC ID so that we can authorize them for the installation and ensure that the required [object ids](https://onedrive.live.com/edit.aspx?resid=A9C0C8416014A546!70356\&ithint=file%2cxlsx\&wdo=2\&authkey=!AAJBs71il7XKwJ8) are approved.
## Basics app
We created a new role center called "simple\_EDI". It contains all the lists, settings and actions you need to implement the module in your BC - and also to work in your day-to-day business:

Installing/publishing the simple|EDI app creates two new permission sets:

The "ALL" permission set contains all permissions for all objects added by the module. The "READ" permission set includes only read permissions on all tables and the permissions to execute pages and code units that are added. Make sure all users processing orders have full permissions to the module.
## Setting up the app
First, you need to set up the API connection and transaction transfer options:

Please follow the steps below to edit fields, options and features:

1. Enter the URL and API token (provided to you by Procuros) and activate the setup with the specified API version (currently v2).
2. Decide at what time/action the incoming and outgoing transactions will be triggered:
* **Import orders:**
* **Manual** to receive orders only when the function is called from this setup page
* **Interval-based** to use a job queue that allows you to control start times and the time between runs. We recommend using this option.
If not already done, initialize the job queue:

Determine the time intervals between runs:

If you want, you can edit the job queue:

If you decide to switch from the interval-based to the manual option, the job queue will be automatically cleared. If the import method is "interval-based", you cannot import manually.
Enable setup to ensure the transfer works.
If you want to import new orders in the background without confirmation messages, it is helpful to activate the "Hide validation dialog" flag.
## Activation of the app
It is necessary to enter the GLN of your own company or the companies in your database if there is more than one company. You may have already done this on the Company Information page. If this has already happened, the Sync GLN Information function populates the simpleEDI Business Relationships table:

If you have not yet entered a GLN code for your company, either enter it in the "Company Information" card, or (recommendation) create a new entry here in the "simpleEDI - Business Relationships" table for each company in your database to be linked to Procuros:

## Setup Checklist
Use this checklist to ensure that key facilities are completed.
### Initial Setup Checklist
* You have successfully downloaded and installed the **simple\_EDI app**
* You have assigned the new **authorizations** to the **users** who will process EDI orders
* You entered a **valid API token** on the setup page (provided by Procuros)
* You have entered the **GLN for your company** and activated the business relationship with Procuros
# How to setup Article Master Data in Business Central
Source: https://docs.procuros.io/en/connectors/ms-business-central/master-data-configuration/article-master-data
Step by step guide to configure your article master data
Items are identified via the EAN/GTIN code, and the corresponding item information such as item name or prices is pulled from your Business Central master data.
## Article GTIN / EAN Setup
After the customers, their addresses and their own company(s) have been activated for transmission via EDI, the GTIN must - if not already done - be entered on the item card.

Please be careful not to include spaces or other special characters - the GTIN / EAN must adhere to the GS1 standards.
## Deposit Items Configuration
There is also the option of automatically adding additional items to the customer order, for example for deposits. A new table is used here to link these items - the ordered item and the deposit item.
Set up the relationship between ordered items and deposit items.

Link the ordered item with the corresponding deposit item.

The transmitted indicator "is deposit" is not necessary for linked items to be included in the customer order. If there is an entry in this table without the "deposit" indicator, the linked item is also included in the document.
## Translations of Units of Measure
Your customers may not use the same codes as you, e.g. B. for pieces, sets or lump sums. To avoid entering every code a customer uses into your database and setting up sales prices for them, you can set associations.
Set up unit of measure translations for your trading partners.

Map your customer's unit codes to your internal unit codes.

## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GTIN/EAN stored for each article relevant for trade
* Article number and description filled out for each article
* Format of GTIN/EAN correct (no spaces, only numeric characters)
* Deposit items configured and linked to ordered items (if applicable)
* Unit of measure translations set up for trading partners
* No duplicate GTIN/EAN codes in the system
The correct setup of your master data forms the foundation for successful integration with Procuros and your trading partners.
# How to setup Customer Master Data in Business Central
Source: https://docs.procuros.io/en/connectors/ms-business-central/master-data-configuration/customer-master-data
Step by step guide to configure your customer master data
In order to work with the "simple-EDI" app in day-to-day business, you must complete the customer master data setup. Customers in your Business Central instance are identified via the GLN and the corresponding master data such as addresses are pulled from your Business Central instance based on the GLN code.
## Customer GLN Setup
On the customer card, you must fill in the GLN field in the "Invoicing" section.

You also need to ensure that all relevant shipping addresses for this customer exist and that the GLN field is populated with the correct identifiers.

## Configure Business Relationships
To set up the basic functionality, you need to identify the customers (and their shipping addresses) whose sales transactions should be processed via EDI.
To do this, open the "simpleEDI - Business relationships" page.

If you have previously entered GLNs into customer cards and/or shipping addresses, you can sync this information into the list used for this module.

Select the "Business relationship with Procuros" checkbox to enable the possibility of exchanging data via Procuros. For each customer, you also have to decide which type of document you want to send via Procuros.

In the context of the customer, you also need to decide whether the submitted prices should be included in the order or (if this is not desired) whether the standard BC rules for prices and discounts of an item should be included in the order.

If you have different shipping addresses for a customer, make sure you have entered a GLN and that you have enabled these addresses for transfer via Procuros. If the case arises that not all delivery addresses (and/or customers) should be sent via Procuros, you can deactivate the checkbox.
After you have installed/published the simple|EDI module and synchronized your existing customers as described, you can also maintain the GLN on the customer card or on the delivery address card if you want. However, we recommend that you do this on our "simpleEDI - Business relationships" page, as you can activate and edit the individual entries more quickly here.
## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GLN stored for each trading partner
* GLN stored for different billing and delivery addresses
* Business relationship with Procuros enabled for relevant customers
* Document types configured for each customer (orders, invoices, etc.)
* Pricing options configured (submitted prices vs. standard BC rules)
* All relevant shipping addresses enabled for Procuros transfer
# Confirm/Reject Orders
Source: https://docs.procuros.io/en/connectors/ms-business-central/receiving-documents/confirm-reject-orders
Learn how to confirm, modify, or reject orders received from your trading partners
## Confirm/Reject Orders
To find orders initialized by Procuros, you can use the following call in your role center:

In this list view you will only find customer orders that were submitted successfully and without errors. This means that the following records were successfully found in your system:
* Customer (sales, invoice recipient) via GLN
* Delivery address via GLN (if different from the selling customer's GLN)
* Position(s) via GTIN
* Unit of measure(s) (in the unit of measure list and in the allocation table)
It depends on your institution (see Business Relationships table) whether the unit price is taken from Procuros or from your data in BC. If address identifiers are transferred from Procuros, they are not transferred to the sales order document. As with "non-Procuros customer orders", the address data is taken from your BC.
## Order Approval Workflow
After importing the orders, you can use a standard approval workflow to request and approve the document. If you have not activated an approval workflow, the document is automatically released after changing the simple|EDI status field:

## Order Status Options
So you have the following options:
If you have no changes, such as adding items, changing the quantity or delivery date, you can mark this order as accepted. Each line (or all lines) of the sales order that you want to ship and invoice as a whole.
If you have changed the order, mark it as "changed". This allows you to partially ship and invoice the order if you wish.
If you do not want to process this order, mark it as such. If you have set an immediate reply to Procuros, selecting this option will delete the document immediately. If you submit the order confirmation manually, the order will be deleted after successful transmission.
Depending on your settings, this status will be sent to Procuros immediately after entering the status or manually in response to the order.
## Error Handling
You may receive an error message if you try to select any of these options. This is because the following mandatory fields are checked when the EDI status is changed:
* The invoice recipient's VAT ID is not empty
* The customer and his delivery address and, if applicable, "invoice recipient" are activated in the simple|EDI business relationship table
* Name, address, city, postal code, contact person name and region code are filled (for sales, delivery and invoice recipients)
According to the standard functionalities, you can delete the sales order until a delivery is booked. The filled "simple|EDI status field" does not prevent deletion.
# Receiving Orders from Trading Partners
Source: https://docs.procuros.io/en/connectors/ms-business-central/receiving-documents/receiving-orders
Learn how to receive and process orders from your trading partners in Business Central
## Receive orders from your trading partners
Once you have prepared your data for incoming and outgoing transactions, you can import the first customer orders into your system.
Depending on your setup, this can be done through the job queue or manually. The manual import can be accessed via the role center:

## Error Handling
If the import of one or more transactions was unsuccessful, you will see an error entry in your role center:

We recommend that you go to the Procuros portal to see what error occurred. There you can resend the transaction to your Business Central and run the import function again.
## Log Archive
If you want to see all the log entries in your system, you can open the log archive:

Here you can also find the reasons for the errors and whether these reports have been sent to Procuros:

The log archive provides detailed information about all transactions processed through the simple\_EDI app, including success and error status for each document.
# Send Delivery Notes
Source: https://docs.procuros.io/en/connectors/ms-business-central/sending-documents/delivery-notes
Learn how to send delivery notes to your trading partners through Business Central
## Send Delivery Notes
You can use almost all functions and options of the standard BC for released documents. The simple|EDI status "accepted" or "changed" is a requirement for posting shipments and/or invoices, regardless of whether the order response must be sent via Procuros or not. This is because some mandatory fields cannot be edited subsequently.
## Order Status Requirements
Please remember the following:
### Accepted Status
If the sales order has the simple EDI status "accepted": Only complete shipments are permitted for an order line. Therefore, the "quantity to ship" in each line must be either zero or equal to the original quantity:

The second line cannot be processed this way.
### Changed Status
The sales order has the simple|EDI status "modified": it is possible to book the shipment in whole or in part:

If you do not plan to send an order confirmation to Procuros, we recommend the "modified" option to be more flexible.
## Important Remarks
For all outgoing documents, please check whether you have set the transmission to "manual" or "interval-based" on the simpleEDI setup page. If they are not set to "interval-based" they will not be sent automatically. Instead, you have to send them manually from the sales order list or from the Role Center page.
## Delivery Note Process
Ensure the sales order has the required simple|EDI status ("accepted" or "changed") before posting shipments.
For "accepted" orders: Only complete shipments are allowed (quantity to ship must be zero or equal to original quantity).
For "changed" orders: Partial shipments are permitted.
Use the standard Business Central shipment posting process. The simple\_EDI app will handle the delivery note transmission.
Verify your transmission settings are configured for automatic or manual sending as required.
The simple|EDI status is a critical requirement for posting shipments. Make sure the order has been properly processed through the confirm/reject workflow before attempting to post delivery notes.
Delivery notes are automatically generated when shipments are posted and will be sent to Procuros based on your transmission configuration and business relationship settings.
# Send Invoices
Source: https://docs.procuros.io/en/connectors/ms-business-central/sending-documents/invoices
Learn how to send invoices to your trading partners through Business Central
## Send Invoices
After the shipment, the "order decision" influences the options for posting an invoice.

We do not currently support the ability to send a single sales invoice to Procuros via the API. So you cannot use the "get shipment Lines..." function to separate an invoice from your order.
## Important Remarks
For all outgoing documents, please check whether you have set the transmission to "manual" or "interval-based" on the simpleEDI setup page. If they are not set to "interval-based" they will not be sent automatically. Instead, you have to send them manually from the sales order list or from the Role Center page.
The invoice sending process is directly linked to the order confirmation workflow. Make sure your order decisions are properly configured before attempting to send invoices.
## Invoice Sending Process
Ensure that the shipment has been completed and the order decision has been made (Accepted, Changed, or Rejected).
Verify that your transmission settings are configured correctly on the simpleEDI setup page.
Use the standard Business Central invoice posting process. The simple\_EDI app will automatically handle the transmission to Procuros based on your settings.
If transmission is set to "manual", you must manually trigger the sending process from the sales order list or Role Center.
The invoice will be automatically sent to Procuros once posted, provided your transmission settings are configured for automatic sending. The system will use the business relationship settings to determine which trading partners should receive the invoice.
# Procuros SFTP Details
Source: https://docs.procuros.io/en/connectors/sftp/sftp
Technical information for connecting to Procuros via SFTP
Procuros SFTP connection enables secure document exchange between you and your trade partners. This connection method supports EDIFACT documents and provides a reliable way to transfer business documents like orders and invoices through our network.
## Technical Details
### Connection Information
Our SFTP server connection requires specific credentials and settings for proper operation.
* **SFTP Server Address (Endpoint)**: sftp.procuros.io
* **Port**: 22 (SSH)
* **Username**: Provided by Procuros
* **Password**: Provided by Procuros
Password authentication is preferred but public key authentication is also available.
### Directory Structure
The SFTP connection uses a specific directory structure to organize document flow.
* **Inbound directory** (You → Procuros): `partner2procuros`
* **Outbound directory** (Procuros → You): `procuros2partner`
You can upload **any** file format (including .csv, .edi, .xml, .desadv, .invoic, .txt)
Custom directory structures as required by your EDI software are possible. Please inform Procuros about your specific requirements.
## Using Your Own SFTP Server
If you prefer to use your own SFTP server for document exchange, we can connect to it.
Please whitelist all of the following **outbound** IP addresses so that Procuros can connect to your server:
* 3.70.10.129
* 3.76.51.85
* 3.76.66.206
* 52.28.170.162
* 52.59.155.142
Please ensure all of the IP addresses above are whitelisted in your firewall or security settings.
Please share the following information with our team:
* Your SFTP Server Address
* Port number
* Username
* Password
* Directory Structure
## Frequently Asked Questions
Currently, we only provide EDIFACT documents via SFTP.
Share the **outbound** IP addresses listed in the table above. These are the IPs Procuros connects from when reaching out to third-party SFTP servers.
For partners sending documents **to** Procuros, they need to whitelist our **inbound** IP addresses. These are tied to the AS2 proxy's Network Load Balancer. Please contact the Procuros Solutions Team for the current inbound IP addresses.
## Technical Support
If you need assistance with SFTP setup or encounter any issues:
* **Contact**: Solutions Team
* **Email**: [help@procuros.io](mailto:onboarding@procuros.io)
# How to set up Article Hierarchies
Source: https://docs.procuros.io/en/connectors/weclapp/features/article-hierarchies
Step by step guide to setting up article hierarchies in Weclapp
## Creation of Article Hierarchy & Bills of Materials in Weclapp
Create a new item in weclapp for a display, a box, a deposit item, etc.
Add a name, item number, and other parameters to the BOM.
In the lower area on the same input mask, please select "Sales bill of material" for "Article type", then please click "Save and details".
Please make sure that all Items in the sub-items contain an EAN.
Important! Please remember to enter the corresponding EAN in the "EAN field". Without an EAN, the Item information will not be sent correctly and the message will not be delivered to your Trade Partner.
You can then add the sub-items under the "Sales parts list sub-items" tab.
The EAN for the main item is absolutely necessary for the article hierarchy to be transmitted correctly.
### Specific Requirements - 3 Layer Article Hierarchies
Some Trade Partners such as Edeka always require that the smallest consumer unit (unit that will be purchased by the end consumer) to be factorized and displayed on the invoice.
Most ERP systems do not support multi (>2) level article hierarchies. For this reason, item master data must be set in a certain way in order for Procuros to pick them up correctly:
1. **Article hierarchies are correctly set up via the bill of material feature in weclapp**
* When creating an article hierarchy, the correct article type is selected. Only then you can add the child items to the parent item
* Make sure all the quantities and prices are correctly set
2. **Make sure all the quantities and prices are correctly set**
* In weclapp you can decide whether you want the parent item or the child items to be the invoiced items (having a price)
* Please select the correct case for your use cases by ticking or not ticking the appropriate fields on the article configuration page
3. **The GTIN of the article hierarchy is either unique or the same as the article that only has another deposit article**
* The GTIN of the article hierarchy should be unique, such that Procuros can find one article if a customer orders one
* In case the article hierarchy is being used for deposit articles, it is fine that the same GTIN is being used for the main article and the article hierarchy
4. **Article Hierarchy SKU Breakdown**
* Make a copy and fill in following [Article Hierarchy SKU Breakdown](https://docs.google.com/spreadsheets/d/1Zil6O7QbsRHl41mjxhK7Arc-0ioM-7uSUvyJXyC-IfA/edit?gid=0#gid=0)
* Procuros will then use this Article Hierarchy to correctly process and send the documents to Trade Partners
# How to set up Batches
Source: https://docs.procuros.io/en/connectors/weclapp/features/charges
Step by step guide to setting up batches in Weclapp
### Batch Setup in Weclapp
Batches are stored using the 'Stock Movement' Feature in Weclapp.
Batches are added to Line Items on shipments.
Expiration dates are added to all batches.
Multiple batches are added by adding a new line item.
The correct management of batches and best-before dates is particularly important for companies subject to legal traceability obligations.
# How to set up Deposits
Source: https://docs.procuros.io/en/connectors/weclapp/features/deposits
Step by step guide to setting up deposits in Weclapp
### Deposit Article Setup in Weclapp
It is necessary that your Deposit Articles are also assigned a GTIN. GTINs for deposit items can be generated on [**GS1's Check Digit Calculator**](https://www.gs1-germany.de/serviceverzeichnis/pruefziffernrechner/#c418).
**Step 1**
The Deposit Article must be set up as a single item.
The "Product group" must be set to a "Deposit".
The "Unit of measure" must also be a "Deposit" (not a "Piece", for example). This can be set universally in the settings for the "Unit of measure".
The Deposit Article requires a GTIN/EAN (set up beforehand).
**Step 2**
Articles with a Bottle Deposit must be created as a "Parts List".
Parts Lists can be created in weclapp. A separate Bill of Materials (BOM) is therefore required for each item subject to a deposit. Each of these BOMs must be created with the following parameters:
* the item for which a deposit is charged
* the Deposit article with the "Unit" set as "deposit"
* Important: the deposit product must correspond to the container size of the product: e.g. 4x water → 4x deposit (= 1 item), and NOT 4 x 1x deposit (= 4 items)
* the EAN/GTIN of the deposit item
The corresponding EAN/GTIN is then deleted from the deposit item itself and added to the BOM, the deposit item must be assigned a newly generated EAN/GTIN.
Using the Unit of Measure (Deposit) it is then possible to differentiate between the deposit product and the deposit item.
# How to set up Discounts
Source: https://docs.procuros.io/en/connectors/weclapp/features/discounts
Step by step guide to setting up discounts in Weclapp
Weclapp allows for two types of discounts: Header level discount & Article level discount.
### Header Level Discount
* The Header level discount will apply to the whole document / all articles
* You can create Header level discounts by going into the specific 'Customer Tab' → 'Sales surcharges and discounts' tab' and then apply them for the respective customer
* IMPORTANT: If your traded items include a deposit article (such as bottle deposit), the discount must be setup at item level so that the discount is not applied to the deposit amounts
### Item Level Discounts
A distinction is made between generally applicable Item Level discounts and trading partner-specific scenarios (option 1 & option 2). You then link the product groups to relevant articles.
**Option 1: General Discount - Applied to all Trade Partners**
The following describes how to create discounts for material groups that apply to **all** business partners.
Navigate to "Merchandise categories" in the "Articles" menu and select an existing product group or create a "+ New merchandise category"
Add the Item Level discount to the product group in the "Surcharge and reduction" tab by clicking on "+ Surcharge and reduction"
In the window that opens, select the appropriate type (Surcharge / Reduction), Sales Channel, Percentage value and Start date. Then please save.
**Option 2: Specific Discount - Applied to individual Trade Partner/s**
The following describes how to create the material group and corresponding discounts for **one or more** specific business partners.
Navigate to the customer for whom the discount should apply and open the tab "Sales surcharges and discounts". There you can either add new entries (via "+ Surcharge and discount sale") or edit existing entries
In the window that opens, select the product group you just created. And please select the distribution channel, discount percentage and start date, then please save.
**Link merchandise category to article**
Link the category to a relevant article. If you only want to configure parts of an item bill of materials (e.g. the individual item without a deposit in a bill of materials), it is important that the product group of this individual item is created and linked accordingly.
The article will be displayed in the corresponding product group.
The stored discounts are taken into account for the configured customers.
# How to set up Fulfillment
Source: https://docs.procuros.io/en/connectors/weclapp/features/fulfilment
Step by step guide to setting up fulfillment in Weclapp
## Setting up the fulfillment integration for 3PL documents
* The shipping instructions are sent to the fulfillment service provider (3PL) as soon as the corresponding delivery note has the status "created" in weclapp
* As soon as the fulfillment service provider (3PL) sends a shipping instruction feedback to weclapp, the status of the corresponding delivery note in weclapp is automatically changed to "sent"
### Setting Up Warehouse
A warehouse must be set up in weclapp for each fulfillment service provider. In this way, Procuros can distinguish between different fulfillment service providers and the associated warehouses.
Go to Settings → Warehouse and create / edit a warehouse entity.
Add all the required details:
* Warehouse name
* The delivery address of the Warehouse
* GLN - without the GLN, Procuros will not be able to send the document to the correct Fulfiller
Please then send the relevant warehouse identifier ("ID") to Procuros. To do this, open the relevant warehouse and copy the ID that you can find in the URL. Procuros needs this information to identify the specific Warehouse.
Without the GLN, Procuros cannot send the document to the correct Fulfiller.
### Sending a Dispatch Instruction
Make sure the *shipment* is in weclapp status "*Delivery note created*".
The shipment you choose for testing must have a "date" AFTER `activeFromDate`.
Make sure the correct *Warehouse / Lager* is selected while creating the *shipment*.
Ensure the following mandatory data fields are filled on the shipment:
* *Customer order number*
* *Shipping date*
# Overview Weclapp Connector
Source: https://docs.procuros.io/en/connectors/weclapp/getting-started/overview
Overview of the capabilities and benefits of the Procuros Weclapp Connector
## Overview of the Weclapp Connector
The Procuros Weclapp Connector enables integration between your Weclapp ERP system and the Procuros platform, allowing automated exchange of business documents between you and your business partners.
## Supported Document Types
The Weclapp Connector currently supports the following document types:
Receiving:
* Orders
* Dispatch Instruction Response
Sending:
* Shipping Notice
* Dispatch Instruction
* Invoice
* Credit Note
## Benefits of Integration
* **Optimized Workflows**: Streamlines data exchange between you and your business partners.
* **Enhanced Capabilities**: Includes support for discounts, deposit items, product hierarchies, bills of materials, and batches.
* **Automated Document Handling**: Procuros seamlessly processes business documents automatically.
# How to connect your Weclapp instance to Procuros
Source: https://docs.procuros.io/en/connectors/weclapp/getting-started/technical-setup
Step by step guide to setup your technical connection between your Weclapp and Procuros
## Setting Up Authentication
The *Procuros Weclapp Connector* must be granted access to your Weclapp system so that Procuros can automatically process your business documents. The following instructions will help you create the correct access data and make the necessary configurations.
Click on your initials in the top right corner to access the Weclapp settings.
Create a new API token for the Procuros integration.
Create a new API name, e.g., "Procuros".
Save the new API token.
Please provide Procuros with the following information (ideally through the portal, alternatively via the onboarding form):
* *Weclapp API-URL* → copy from the browser line
* *Weclapp API name*
* *Weclapp API token*
## Setting Up Procuros Free-field
The default Procuros setup is that all documents correctly created will be sent to a Trade Partner for which you are connected with. If you prefer to filter/send only certain documents for a Business Relationship with a Trade Partner, you will need to configure a Free-field.
Navigate to Settings ("Gear") and click "Additional Fields", then "Manage Additional Fields". This usually requires a user with administration rights.
Click on "+ New additional field".
Please enter the following setup values completely and then save them:
* Captions: PROCUROS
* Linked Entities (via "+ New Link"): Quote, Order, Order Line, Purchase Order, Purchase Invoice, Customer/Prospect, Vendor, Delivery, Invoice, Goods Receipt
* Data type: list (single selection)
* Active: yes
* Show on overview pages: yes
* Show when creating: yes
* Manage values (via "+ Add"): CUSTOMER
* Active: yes
In the same view ("Manage additional fields") from the address line of the browser, please note the "entityID" value. Please pass this value on to Procuros.
For each trading partner/customer, please enter the value "Customer" in the Procuros free field that has just been created.
Only Trade Partners/Documents marked with this Free-field will be pulled by the Procuros Weclapp Connector.
## Testing the Connection
After configuring the API credentials and the Procuros free field, a connection test should be performed:
1. Procuros sets up the connector with your access data
2. A test document is created to verify correct transmission
3. After successful verification, you will be informed about the operational connection
Ensure that all required information has been correctly transmitted to Procuros to ensure a successful connection.
## Troubleshooting
If problems occur during setup:
1. **API Access Rights**: Ensure that the created token has sufficient rights
2. **Free-field Configuration**: Check if the Procuros free field is correctly set up and assigned to trading partners
3. **Weclapp Version**: Confirm that your Weclapp version is compatible with the connector
If problems occur, contact the Procuros support team at [help@procuros.io](mailto:help@procuros.io) with a detailed description of the problem.
# How to setup Article Master Data in Weclapp
Source: https://docs.procuros.io/en/connectors/weclapp/master-data-configuration/article-master-data
Step by step guide to configure your article master data
### Article GTIN / EAN
Create the GTIN/EAN in the article master data of your articles that you use in transactions with your trading partners.
To do this, open the item card of a corresponding item and store the GTIN/EAN in the "EAN" field.
You will also need to provide an article number and the description of the item.
Please be careful not to include spaces or other special characters - the GTIN / EAN must adhere to the GS1 standards.
## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GTIN/EAN stored for each article relevant for trade
* Article number and description filled out for each article
* Format of GTIN/EAN correct (no spaces, only numeric characters)
## Special Adaptations for Special Article Types
For special article types such as bills of materials, deposit items, or hierarchical article structures, additional setups are required. These are explained in more detail in the corresponding sections under "Connector Features":
* Article Hierarchies / Bills of Materials
* Deposit Articles
* Batches & Best Before Dates
The correct setup of your master data forms the foundation for successful integration with Procuros and your trading partners.
# How to setup Customer Master Data in Weclapp
Source: https://docs.procuros.io/en/connectors/weclapp/master-data-configuration/customer-master-data
Step by step guide to configure your customer master data
### Creating Trading Partner GLNs
Open a customer's customer card and add or change addresses by clicking on the "plus" sign.
Check all boxes relevant to this address. Pay attention to different billing or delivery addresses. These must be created separately - details can be found in the official Weclapp documentation.
Paste the GLN into the appropriate field located at the bottom.
Please be careful not to include spaces or other special characters - the GLN must adhere to the GS1 standards.
### Creating Trading Partner Sales Tax IDs
Set up the sales tax ID / VAT ID in your customer's master data.
To do this, open a corresponding customer and in the "Overview" tab scroll down to the "VAT ID number" field and enter the customer's VAT ID there.
The correct setup of the VAT ID is particularly important for the correct tax treatment in cross-border trade.
## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GLN stored for each trading partner
* GLN stored for different billing and delivery addresses
* VAT ID stored for each trading partner
* Procuros free field filled out with "CUSTOMER" value for each relevant trading partner
# Sending Credit Notes
Source: https://docs.procuros.io/en/connectors/weclapp/sending-documents/credit-notes
Step by step guide to sending credit notes from Weclapp to Procuros
## Credit Note Prerequisites
IMPORTANT! An invoice associated with the credit is mandatory for setup.
* Procuros can only send credit notes that are based on an existing invoice. Please ensure this is always the case. You can easily check this:
* If you go to the "Documents" tab on the credit note, you should find the associated invoice.
### Required Fields
* Invoicing-GLN
* ShipTo-GLN
* Article GTINs / EANs
### Credit Note Workflow
Relevant credits are generated via the "Create credit" button.
The "Create credit note" option is only displayed if you have previously selected "Create open items" for the associated invoice.
In order for Procuros to be able to export the credit, it must have the status "Open items created". This status is achieved by simply saving the credit.
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
4. **Missing link for credit notes**: Check if the credit note is linked to an invoice
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Sending Dispatch Instructions
Source: https://docs.procuros.io/en/connectors/weclapp/sending-documents/dispatch-instructions
Step by step guide to sending dispatch instructions from Weclapp to Procuros
### Fulfillment Integration Setup
In order to be able to use the Procuros fulfillment function, your weclapp must be set up correctly so that Procuros can pick up the documents correctly.
* The shipping instructions are sent to the fulfillment service provider (3PL) as soon as the corresponding delivery note has the status "created" in weclapp.
* As soon as the fulfillment service provider (3PL) sends a shipping instruction feedback to weclapp, the status of the corresponding delivery note in weclapp is automatically changed to "sent".
### Warehouse Configuration
A warehouse must be set up in weclapp for each fulfillment service provider. In this way, Procuros can distinguish between different fulfillment service providers and the associated warehouses.
Go to Settings → Warehouse and create / edit a warehouse entity.
Add all the required details:
* Warehouse name
* The delivery address of the Warehouse
* GLN - without the GLN, Procuros will not be able to send the document to the correct Fulfiller
Please then send the relevant warehouse identifier ("ID") to Procuros. To do this, open the relevant warehouse and copy the ID that you can find in the URL. Procuros needs this information to identify the specific Warehouse.
Without the GLN, Procuros cannot send the document to the correct Fulfiller.
### Dispatch Instruction Flow
Make sure the *shipment* is in weclapp status "*Delivery note created*".
The shipment you choose for testing must have a "date" AFTER `activeFromDate`.
Make sure the correct *Warehouse / Lager* is selected while creating the *shipment*.
Ensure the following mandatory data fields are filled on the shipment:
* *Customer order number*
* *Shipping date*
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
4. **Missing link for credit notes**: Check if the credit note is linked to an invoice
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Sending Invoices
Source: https://docs.procuros.io/en/connectors/weclapp/sending-documents/invoices
Step by step guide to sending invoices from Weclapp to Procuros
### Invoice Prerequisites
Create a (test) invoice that can be exported from Procuros and sent to your trading partners for testing purposes to obtain your trading partner's approval for this document type. The procedure for sending this document type is then the same in productive operation.
**The basic requirement** is that you meet the requirements of this [**weclapp checklist**](https://help.procuros.io/en/articles/64).
### Required Fields
* Invoicing-GLN
* ShipTo-GLN
* Article GTINs / EANs
Missing or incorrect information in these mandatory fields can lead to rejection of the invoice by the trading partner.
### Invoice Status Configuration
For Procuros to export the invoice and send it to trading partners, the invoice must have a certain status. In the standard configuration, invoices with the status "Open items created" are picked up by Procuros.
### Process for Sending Invoices
Create an invoice from a corresponding order/shipping notice.
Make sure the invoice has the status "Open items created".
If all prerequisites are met, the invoice will be automatically exported by Procuros.
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
4. **Missing link for credit notes**: Check if the credit note is linked to an invoice
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Sending Shipping Notes
Source: https://docs.procuros.io/en/connectors/weclapp/sending-documents/shipping-notices
Step by step guide to sending shipping notices from Weclapp to Procuros
### Shipping Notice Prerequisites
Create a (test) shipping notice that can be exported from Procuros and sent to your trading partners for testing purposes to obtain your trading partner's approval for this document type. The procedure for sending this document type is then the same in productive operation.
**The basic requirement** is that you meet the requirements of this [**weclapp checklist**](https://help.procuros.io/en/articles/64).
### Shipment Requirements
* A corresponding order must be available
* Mandatory fields that must be filled in on all related documents (order): "Customer Order Number", "Planned Delivery Date", GLNs
* Important: In order for Procuros to export this document, the document must be in the weclapp workflow status "created"
Missing or incorrect information in these mandatory fields can lead to rejection of the shipping notice by the trading partner.
### SSCC / NVE
Some Trade Partners will request you to provide the SSCC / NVE number (18-digit GS1 Identification Key used to identify a logistic unit) on each Shipping Notice for a warehouse delivery.
Weclapp currently does not support a SSCC / NVE function. In order for you to provide this number, there are two options:
* A direct connection with your fulfillment provider (3PL) - please see **Fulfillment integration** tab for more information
* Direct input on our Portal, after the document has been created in weclapp
### Shipping Document Creation Flow
Create a shipping notice from a corresponding order.
Make sure the shipping notice has the status "created".
If all prerequisites are met, the shipping notice will be automatically exported by Procuros.
If SSCC/NVE is required, enter this information via the Procuros portal or use the fulfillment integration.
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
4. **Missing link for credit notes**: Check if the credit note is linked to an invoice
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Procuros x400 Details
Source: https://docs.procuros.io/en/connectors/x400/x400
Technical information for connecting to Procuros via x400
## Technical Contact Person
If you have questions about X.400 setup or technical issues, the following contact options are available:
* Email: [help@procuros.io](mailto:help@procuros.io)
* Phone: +49 40 87709293
## X.400 Address Information
The following address table contains all necessary components of the Procuros X.400 address:
| Address Component | Value |
| - | - |
| C (Country) | DE |
| A (ADMD) | VIAT-AS2 |
| P (PRMD) | |
| S (surname) | Procuros |
| G (Given name) | |
| O (organization) | Procuros-GmbH |
| CN (Common Name) | Procuros |
| n-id | 2063352 |
Ensure that all address components are entered exactly as specified in your X.400 system. Empty fields should not be transmitted.
Enter the X.400 address components specified above into your X.400 system.
After configuration, we recommend performing a test transmission to verify correct setup.
The X.400 connection can be used for both production and test environments.
# How to set up Article Hierarchies
Source: https://docs.procuros.io/en/connectors/xentral/features/article-hierarchies
Step by step guide to setting up article hierarchies in Xentral
## What are Article Hierarchies/Bills of Materials?
Article hierarchies and bills of materials enable the structured representation of composite products.
### Basic Requirements for Article Hierarchies
* Each bill of materials must be linked to individual articles (including GTINs/EANs)
* Bills of materials should contain corresponding sub-positions in appropriate numbers with article prices
* Prices should (if possible) be listed at the level of the individual sub-positions
## Map parts list via Procuros
* **Artikelhierarchie-SKU-Breakdown**
* Create a copy and complete the following item hierarchy SKU breakdown: [**Artikelhierarchie-SKU-Breakdown**](https://docs.google.com/spreadsheets/d/1Zil6O7QbsRHl41mjxhK7Arc-0ioM-7uSUvyJXyC-IfA/edit?gid=0#gid=0)
* Procuros will then use this item hierarchy to process and send the documents to trading partners correctly
The correct representation of article hierarchies is important, as many trading partners expect these to be correctly displayed in invoices.
# How to set up Batches
Source: https://docs.procuros.io/en/connectors/xentral/features/charges
Step by step guide to setting up batches in Xentral
## What are Batches?
Batch management enables product traceability and is particularly important in the food and pharmaceutical industries.
### Setting Up Batches
First, navigate to batch management in the Xentral system settings.
Create a new Report and name it: Procuros: Gelieferte Chargeninformationen
Create a new variable with the following values:
* the variable name must be LIEFERSCHEINID
* the ‘default value’ must be an ID from a delivery note that contains batches:
* to find this ID, go to a delivery note that contains batches that already exist in your system
* open this delivery note
* copy the ID from the URL and enter it in the Default value field
Copy the following SQL-Code-Snippet and paste it into the SQL Field. Click the play-Button afterwards.
```
SELECT *FROM mhd_log WHERE doctype = 'lieferschein' AND doctypeid = '{LIEFERSCHEINID}'
```
Click on "generate columns"
Go over to the "Transfer"-Tab and set the following API Access settings:
Open the report and you will find the ID in the URL (e.g. ...\&id=170). This number must be sent to Procuros. If you are not sure which number to use, simply send us the entire link. Send an e-mail to [edi@procuros.io](mailto:edi@procuros.io) - we will then store this ID in our system.
### Managing Best-Before Dates
Closely connected to batch management is the management of best-before dates:
Activate the management of best-before dates in the article settings
Navigate to Best Before + Batch and enter the number of items, the corresponding best-before date and the desired storage location of the item.
The correct management of batches and best-before dates is particularly important for companies subject to legal traceability obligations.
# How to set up Deposits
Source: https://docs.procuros.io/en/connectors/xentral/features/deposits
Step by step guide to setting up deposits in Xentral
## What are Deposits?
The configuration of deposit items enables correct billing and management of deposit fees.
### Setting Up Deposit Items
Create a separate article in Xentral for each type of deposit (e.g., bottles, crates).
Assign a unique GTIN/EAN to each deposit item.
Mark the article as a deposit item in the system.
### Bills of Materials for Articles with Deposits
Bills of materials must be created for articles with deposits:
Create a bill of materials that contains both the main article and the deposit item(s).
Specify the correct number of deposit items per main article.
Store the prices for both the main article and the deposit items.
# How to set up Discounts
Source: https://docs.procuros.io/en/connectors/xentral/features/discounts
Step by step guide to setting up discounts in Xentral
### Header Discounts (e.g., Invoice Discount)
Header discounts are applied at the document level:
Enter the discount in the discount field of the document.
For multiple discount levels, calculate the total combined discount and enter it. Depending on how the discounts are applied you need to calculate them differently.
You can find a spreadsheet tool to help you calculate the combined discount [here](https://docs.google.com/spreadsheets/d/186BCs-W_IrTwNoSy5CIm7iN-9fu6deYzAzBZmOraw1w/edit?gid=0#gid=0).
### Calculation Examples for Discounts
1. **Combined discount with different discount levels**:
* Example: 4% cash discount and 1.5% invoice discount plus 3% central purchasing discount
* Formula: `(1-((1-0.04)\*(1-(0.0015+0.03))) = 5.09%`
2. **Sum discount at the same level**:
* Example: 2% logistics discount and 1.5% invoice discount, which apply to the same level (initial price)
* Formula: `0.02+0.015 = 3.5%`
The correct calculation and representation of discounts is important for the acceptance of invoices by your trading partners.
# How to set up Fulfillment
Source: https://docs.procuros.io/en/connectors/xentral/features/fulfilment
Step by step guide to setting up fulfillment in Xentral
## What is fulfillment?
The fulfillment integration enables the connection of logistics service providers to your Procuros workflow.
### Warehouse Configuration for Fulfillment
Set up a warehouse for each fulfillment provider in Xentral under "Warehouse Management".
Assign each warehouse its own, exclusive project.
Assign each warehouse an address of the fulfillment service provider that contains the "ship to GLN".
Each project may only be assigned to a single warehouse. If the same project is assigned to multiple warehouses, Procuros cannot pick up the correct documents.
### Project IDs for Fulfillment
The project IDs are crucial for the correct assignment of shipments:
The project IDs can be found in the URL of the project page in Xentral.
Share these IDs with the Procuros team so they can be stored on their side for correct identification.
## Summary of Features
The advanced features of the Procuros Connector offer extensive possibilities to optimize your business processes and improve data exchange with your trading partners. By correctly configuring these functions, you can fully exploit the capabilities of the connector.
* Batch and BBD management activated and configured
* Article hierarchies/bills of materials correctly set up
* Deposit items created and linked to main articles
* Tax rates configured for all scenarios
* Discount structures defined and tested
* Fulfillment integration set up with correct warehouse and project settings
If you have questions about setting up or using these features, please contact the Procuros support team at [help@procuros.io](mailto:help@procuros.io).
# Overview Xentral Connector
Source: https://docs.procuros.io/en/connectors/xentral/getting-started/overview
Overview of the capabilities and benefits of the Procuros Xentral Connector
The connector links your Xentral system with the Procuros platform and enables automated exchange of business documents.
## Supported Document Types
The Xentral Connector currently supports the following document types:
**Receiving:**
* [Orders](/en/connectors/xentral/receiving-documents/orders)
* Dispatch instructions Response
* [Inventory reports](/en/connectors/xentral/receiving-documents/inventory-reports)
**Sending:**
* [Shipping notes](/en/connectors/xentral/sending-documents/shipping-notices)
* [Invoices](/en/connectors/xentral/sending-documents/invoices)
* [Credit notes](/en/connectors/xentral/sending-documents/credit-notes)
* [Dispatch instructions](/en/connectors/xentral/sending-documents/dispatch-instructions)
## Benefits of the Procuros Xentral Connector
* Simplification of data exchange between you and your trading partners
* Automated document processing for more efficient workflows
* Comprehensive data access to articles, customers, orders, and invoices
* Bidirectional data exchange for receiving and sending documents
* Support for discounts, deposit items, article hierarchies, and batches
# How to connect your Xentral instance to Procuros
Source: https://docs.procuros.io/en/connectors/xentral/getting-started/technical-setup
Step by step guide to setup your technical connection between your Xentral and Procuros
The setup of the Xentral Connector is done via a Personal Access Token in Xentral.
Click on your username in the bottom left and select **Account Settings**.
Go to **Developer Settings > Personal Access Token**. Here you will see a list of all active tokens.
Click on **+ Create Token**. If no tokens are active, you will find the button in the center of the screen. Otherwise, it appears at the top right above your token list.
Enter a unique name for your token (maximum 50 characters).
Click on **Create Token**. The new token will appear on the screen.
Click on the copy icon to copy the token to the clipboard.
Keep the token safe, as it will not be displayed again after leaving the page.
## Token Scopes
The token needs the following scopes so that Procuros can create orders and send documents in your Xentral:
| Scope | Used for |
| - | - |
| `salesOrder:create` | Creating incoming orders |
| `salesOrder:release` | Releasing incoming orders |
| `deliveryNote:send` | Sending shipping notices |
| `creditNote:send` | Sending credit notes |
A token without these scopes cannot be used for the actions above. If you created your token before these scopes were required, create a new one that includes them.
## Enable the Delivery Notes Feature in Xentral
Xentral enables the `api-v3-delivery-notes` feature flag per tenant. It must be enabled for your Xentral tenant, so please ask Xentral to activate it before the connection is switched.
## Submit Access Information to Procuros
The following information is required for the setup:
1. **Xentral API URL**: This consists of your browser URL + "/api"
2. **Xentral PAT**: Encrypt this via [https://eu.onetimesecret.com/](https://eu.onetimesecret.com/) and send it by email to [help@procuros.io](mailto:help@procuros.io)
3. **Xentral Project ID**: If relevant for your integration
Never transmit the Personal Access Token unencrypted via email.
## Test Connection
After configuration by the Procuros team, a connection test is performed:
1. Procuros sets up the connector with your access data
2. A test document is created to verify correct transmission
3. After successful verification, you will be informed about the operational connection
## Troubleshooting
If problems occur during setup:
1. **API Access Rights**: Ensure that the created token includes all the [scopes listed above](#token-scopes) and that the `api-v3-delivery-notes` feature flag is enabled for your tenant
2. **Firewall Settings**: Check if your firewall settings allow connections from Procuros
3. **Xentral Version**: Confirm that your Xentral version is compatible with the connector
If problems occur, contact the Procuros support team at [help@procuros.io](mailto:help@procuros.io) with a detailed description of the problem.
# How to setup Article Master Data in Xental
Source: https://docs.procuros.io/en/connectors/xentral/master-data-configuration/article-master-data
Step by step guide to configure your article master data
For successful integration between your Xentral system and the Procuros platform, various master data must be correctly configured. This guide walks you through the necessary steps.
## Article Master Data
Correctly stored article master data is crucial for error-free transmission of business documents.
### GTIN (Global Trade Item Number)/EAN
A GTIN/EAN must be stored for each article that is traded with trading partners.
Enter the GTIN/EAN in the appropriate field on the article card.
Make sure the GTIN/EAN is known to all connected trading partners.
Do not use spaces or non-numeric characters in the GTIN/EAN fields.
### Internal and External Article Identifiers
If additional article identifiers are used:
Determine which internal and external article identifiers are relevant for your trading partners.
Enter these identifiers in the appropriate fields of the article card.
### Unit and Tax Class
When Procuros creates an order in Xentral, the unit and the tax class of each line come from the article master data, not from the order message. Make sure both are correctly maintained on the article card. A line shows the unit of the article itself, typically "Stk".
### Disabled Articles
An order line that points at a disabled article is rejected right away with an error that names the article identifier. To resolve it, re-enable the article in Xentral or correct the article mapping.
## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GTIN/EAN stored for each article relevant for trade
* Format of GTIN/EAN correct (no spaces, only numeric characters)
* Additional article identifiers stored as needed
* Unit and tax class maintained on the article
* Articles that are traded with trading partners are enabled
The correct setup of your master data forms the foundation for successful integration with Procuros and your trading partners.
# How to setup Customer Master Data in Xental
Source: https://docs.procuros.io/en/connectors/xentral/master-data-configuration/customer-master-data
Step by step guide to configure your customer master data
For successful integration between your Xentral system and the Procuros platform, various master data must be correctly configured. This guide walks you through the necessary steps.
## Company Master Data
The correct configuration of your company master data is a basic requirement for smooth communication with trading partners.
## Customer Master Data
Specific data must be stored for each trading partner connected via Procuros.
### GLN (Global Location Number)
Each trading partner needs an assigned GLN in the "GLN" field on the customer card ("Address").
Check the box for "Different billing address" and enter the GLN of the different billing address in the additional fields.
Do not use spaces or non-numeric characters in the GLN fields.
### VAT ID
The VAT ID is a mandatory field for all trading partners connected via Procuros:
Enter the ID in the "Payment Terms / Taxation" tab in the "VAT ID" field.
Do not use spaces in the text field.
Always use the same free field for the value "PROCUROS" for each customer to ensure consistency.
## Master Data Checklist
Use this checklist to ensure that all necessary master data is correctly stored:
* GLN correctly stored
* VAT ID correctly stored
* Additional identifiers stored as needed
* GLN stored for each trading partner
* GLN stored for different billing addresses
* VAT ID stored for each trading partner
* Procuros free field filled out for each trading partner
The correct setup of your master data forms the foundation for successful integration with Procuros and your trading partners.
# Receiving Inventory Reports
Source: https://docs.procuros.io/en/connectors/xentral/receiving-documents/inventory-reports
Step by step guide to receiving inventory reports in Xentral from Procuros.
## Receiving Inventory Reports
Inventory reports are sent by a fulfilment provider to Xentral to update stock levels and manage inventory.
### Prepare your instance for receiving inventory reports
A warehouse needs to be set up in Xentral for the fulfilment provider you're trying to connect with. The warehouse designation must be provided to Procuros.
All the products that are to be received in the inventory report must be properly set up in Xentral, including any wanted batch related option.
Go to Settings > System > Process Starter and make sure that the process named "Übertragenmodul (Fulfillment, Übertragen, EDI, XML)" is activated and set to be running every 10 minutes.
### Create a new transfer for the inventory report
Go to Settings -> Administration -> Data Exchange -> Transfers and click "Create New Transfer"
* API: Select the relevant api account. If you don't have any, go to the APIs menu, in Settings -> Administration -> Data Exchange, and create one.
* Transfer format: XML
* Type: SFTP
* Server: to be provided by Procuros
* Port: to be provided by Procuros
* Username: to be provided by Procuros
* Password: to be provided by Procuros
* Antwort-Speicherort (Eingang): to be provided by Procuros
* Delete files after download: Checked/Active
Anything not mentioned here can be left as default.
* Stock numbers received: Checked/Active
* Storage behaviour: "Override"
* Display error message for unknown items: Checked/Active
Anything not mentioned here can be left as default.
Make sure you save the transfer settings after adjusting them. This will ensure that the transfer is correctly configured for receiving inventory reports.
# Receiving Orders
Source: https://docs.procuros.io/en/connectors/xentral/receiving-documents/orders
Step by step guide to receiving orders in Xentral from Procuros.
## Receiving Orders
Procuros creates the orders of your trading partners directly in Xentral, using the Xentral API.
## Prerequisites
Make sure your API token has the `salesOrder:create` and `salesOrder:release` scopes. See [Technical Connection](/en/connectors/xentral/getting-started/technical-setup#token-scopes).
Procuros creates the order in Xentral and then releases it. Decide whether incoming orders should arrive **released** or as a **draft**, and tell the Procuros team. We then set this status for your connection.
You do not configure this in Xentral yourself.
## Troubleshooting
If problems occur when receiving orders:
The unit and the tax class of an order line are taken from the article master data in Xentral, not from the order message. A line therefore shows the unit of the article itself, typically "Stk".
See [Article Master Data](/en/connectors/xentral/master-data-configuration/article-master-data#unit-and-tax-class).
An order line that points at a disabled article is rejected right away with an error that names the article identifier.
To resolve it, re-enable the article in Xentral or correct the article mapping.
# Sending Credit Notes
Source: https://docs.procuros.io/en/connectors/xentral/sending-documents/credit-notes
Step by step guide to sending credit notes from Xentral to Procuros
## Sending Credit Notes
Credit notes are used to correct invoices that have already been issued.
### Prerequisites for Credit Notes
The following prerequisites must be met for sending credit notes:
* A corresponding invoice must already exist
* The credit note must be marked as a "**Cancellation invoice**"
* Procuros only transmits credit notes of this type
* Your API token has the `creditNote:send` scope (see [Technical Connection](/en/connectors/xentral/getting-started/technical-setup#token-scopes))
Only credit notes marked as "Cancellation invoice" are accepted by trading partners. This checkbox must be set when processing the credit note.
### Required Fields
The following fields must be correctly filled out:
* Customer order number (on order & delivery note)
* Planned delivery date (on order & delivery note)
* GLNs (Global Location Numbers)
* Procuros free field on the customer
* GLN of the delivery address on the customer
### Process for Sending Credit Notes
Create a test cancellation invoice from a relevant existing invoice and mark it as a "Cancellation invoice".
The document must be in the workflow status "approved".
If all prerequisites are met, the cancellation invoice will be automatically exported by Procuros.
Share the document number with Procuros and provide a PDF example. After positive feedback, credit notes can be sent regularly.
# Sending Dispatch Instructions
Source: https://docs.procuros.io/en/connectors/xentral/sending-documents/dispatch-instructions
Step by step guide to sending dispatch instructions from Xentral to Procuros
## Sending Dispatch Instructions
Dispatch instructions are used to inform fulfillment service providers about pending shipping activities.
### Set Up Fulfillment Integration
The connector uses the same shipping function for delivery notifications and dispatch instructions. For integration with fulfillment service providers, there are specific requirements:
1. A separate warehouse is required for each fulfillment service provider
2. Each warehouse must be assigned a unique project
3. Each warehouse must be linked to an address of the fulfillment service provider
### Warehouse Configuration
Set up a warehouse for each fulfillment provider in Xentral under "Warehouse Management".
Assign each warehouse its own, exclusive project. The project name is the only mandatory field.
Assign each warehouse an address of the fulfillment service provider that contains the "ship to GLN".
Make sure that only one combination exists for each project/warehouse combination.
The project IDs can be found in the URL of the project page. Share these IDs with Procuros.
If the same project is assigned to multiple warehouses, Procuros cannot pick up the correct documents!
### Process for Sending Dispatch Instructions
Make sure that the shipment has been assigned the correct project and fill out all mandatory fields (customer number, order number).
The shipment and the associated delivery note must be in the status "approved".
The dispatch instruction will be sent to the fulfillment service provider as soon as all conditions are met.
Share the document number with Procuros and wait for positive feedback from the fulfillment service provider.
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect workflow status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
4. **Incomplete batch information**: Check if all batch information is complete
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Sending Invoices
Source: https://docs.procuros.io/en/connectors/xentral/sending-documents/invoices
Step by step guide to sending invoices from Xentral to Procuros
## Sending Invoices
Invoices are a central component of the business process. The Procuros Connector enables automated and standardized transmission.
### Prerequisites for Invoices
Before an invoice can be sent, the following prerequisites must be met:
* A corresponding order must exist
* All related documents (order and delivery note) must be correctly created
* The basic requirements of the Xentral checklist must be fulfilled
### Required Fields
The following mandatory fields must be filled out on all related documents (order **and** delivery note):
* Customer order number
* Shipping Note number
* GLNs (Global Location Numbers)
Missing or incorrect information in these mandatory fields can lead to rejection of the invoice by the trading partner.
### Configure Invoice Status
The workflow status of the invoice must be set to "sent" so that Procuros can export it automatically and send it to trading partners.
### Process for Sending Invoices
Create an invoice from a relevant productive order/delivery note and process it to the status "sent".
If all prerequisites are met, the invoice will be automatically exported by Procuros.
Please inform Procuros of the document number and provide a PDF example. After positive feedback, invoices can be sent as normal.
# Sending Shipping Notes
Source: https://docs.procuros.io/en/connectors/xentral/sending-documents/shipping-notices
Step by step guide to sending shipping notices from Xentral to Procuros
## Sending Shipping Notes
Delivery notes document the handover of goods to the recipient.
### Token Scope
Sending delivery notes requires the `deliveryNote:send` scope on your API token. See [Technical Connection](/en/connectors/xentral/getting-started/technical-setup#token-scopes).
### Configure Delivery Note Status
The delivery note must be in the Xentral workflow status "approved" or "Sent" for Procuros to export the document. This is a mandatory step in the shipping process.
### Process for Sending Delivery Notes
A corresponding order must exist and mandatory fields (customer order number, planned delivery date, GLNs) must be filled out.
Create a delivery note from a relevant productive order and process it to the agreed status.
If the prerequisites are met, the delivery note will be automatically exported by Procuros.
Share the document number of the delivery note with Procuros and provide a PDF example. After positive feedback, documents can be sent regularly.
## Troubleshooting Document Sending
If problems occur when sending documents:
1. **Missing mandatory fields**: Check if all required fields are filled out
2. **Incorrect workflow status**: Make sure the correct status is set
3. **Missing master data**: Check if all necessary master data (GLN, GTIN, etc.) is stored
For persistent problems, please contact Procuros support at [help@procuros.io](mailto:help@procuros.io) with a detailed description and the affected document numbers.
# Manage Company Data
Source: https://docs.procuros.io/en/general/admin/company-data
Learn how to maintain and update your company details and business identifiers in the Procuros Portal.
## Editing Company Data
Click on "Settings" in the left navigation bar and then select "Company Data."
Fill in the required fields in the upper section:
* Company Name
* Street and House Number
* Postal Code and City
* Country
In the lower "Standard Settings" section, you can enter the following identifiers:
* Default Bill From Address (GLN)
* Default Bill Address from Domain
* Default Tax ID
All changes will only be applied and activated after clicking "Save."
## Standard Company Identifiers
The stored standard identifiers are automatically used in all transactions to ensure the correct assignment of documents. Maintaining these details is particularly important for:
* Automatic document assignment
* Correct invoicing
* Unique identification within the network
The following identifiers can be set as standard:
1. **GLN (Global Location Number)**
* Your unique identification number in the Procuros network
* Used for document addressing
* Format: 13-digit number
2. **Bill From Address Domain**
* Defines the standard domain for electronic invoices
* Important for the correct delivery of documents
3. **VAT ID**
* Your VAT identification number
* Automatically applied to invoices
* Country-specific format (e.g., DE123456789)
# Invite Team Members
Source: https://docs.procuros.io/en/general/admin/invite-new-team-members
Learn how to add and manage team members in Procuros.
## Team Members Overview
Click on "Settings" in the left navigation bar and then select the "Team Members" section. There, you will find a tabular overview of all current team members with the following information:
* Team member's name
* Assigned email address
## Invite a New Team Member
Click the "Add Member" button in the upper right corner of the team members overview.
In the dialog that appears, enter the email address and name of the new team member. Ensure the email address is spelled correctly.
Confirm your entries. The system will automatically send an invitation email to the specified address.
The invited team member will receive a personalized invitation link that is valid for 3 months. After this period, a new invitation must be sent.
# Notifications Management
Source: https://docs.procuros.io/en/general/admin/notifications-management
Learn how to manage document-level and relationship-level responsible users for notifications in the Procuros Portal.
Procuros allows you to control who receives notifications about document exchanges. You can configure notification recipients at two levels: **document-level** and **relationship-level**. Together, these give you flexible control over who gets notified — from broad company-wide defaults down to specific overrides for individual trade partners.
## Understanding Notification Levels
### Document-Level Responsible Users
Document-level responsible users are the **default recipients** for notifications related to a specific document type (e.g., Invoices, Credit Notes, Price Catalogs). These are configured centrally in your company settings and apply across **all** your trade partner connections.
For example, if you add `accounting@yourcompany.com` as a document-level responsible user for Invoices, that address will receive invoice-related notifications from every trade partner — unless a relationship-level override is in place.
### Relationship-Level Responsible Users
Relationship-level responsible users allow you to **override the document-level defaults** for a specific trade partner connection. When set, they completely replace the document-level responsible users for that particular partner and document type — the two lists are not merged.
This is useful when different teams or contacts within your organization are responsible for specific trade partners. For example, you might want `team-a@yourcompany.com` to handle invoice notifications from Partner A, while all other partners continue using the default `accounting@yourcompany.com`.
## Contacts Declared by Your Trade Partner
Besides the responsible users you configure, Procuros can also use contacts that your trade partner declares directly inside the documents they send you. This behavior is controlled by the **Include document specific contacts** toggle, which is available at both the document level and the relationship level.
When **Include document specific contacts** is selected and a document includes contact email addresses, those contacts will also receive notifications in addition to your default recipients.
Enable **Include document specific contacts** when your partner routinely includes the right operational contact in the documents they send, and you want those contacts to be notified automatically without having to maintain them manually.
## Editing Responsible Users
When you click **Edit** (either at the document level or relationship level), a dialog opens where you can manage the list of email addresses.
Enter a valid email address in the input field and click **+ New Email Address** to add it to the list.
Remove existing email addresses by clicking the remove button next to them.
Click **Save** to apply your changes, or **Cancel** to discard them.
## Managing Document-Level Responsible Users
To configure the default notification recipients for each document type, navigate to the Notifications Management settings page.
Navigate to **Settings** in the left sidebar and select **Notifications Management**.
The page lists all available document types (e.g., Invoices, Credit Notes, Price Catalogs, Remittance Advices, Sales Reports) along with the currently configured responsible users for each.
Click the **Edit** button next to a document type to add or remove email addresses. Changes apply to all trade partners that do not have relationship-level overrides.
Each document type also has an **Include document specific contacts** toggle. Enable it to also notify contact email addresses included in a document, in addition to your default recipients. See [Contacts Declared by Your Trade Partner](#contacts-declared-by-your-trade-partner) for details.
If a document type shows "No recipients configured", no one will receive notifications for that document type unless relationship-level responsible users are set for specific partners.
### Viewing Relationship-Level Overrides
When one or more trade partners have custom responsible users configured for a document type, you will see a green indicator below the document type with the text **"Custom recipients set in X trade partner(s)"**.
Click **View Details** to open a side panel that shows which partners have custom responsible users and the email addresses configured for each. You can search by partner name or email address to quickly find specific overrides.
## Managing Relationship-Level Responsible Users
To configure notification recipients for a specific trade partner and document type, navigate to the connection's Notifications Management tab.
Go to **My Connections** in the left sidebar, select a trade partner, and open the relevant document type.
Click the **Notifications Management** tab in the document type detail view.
The page shows both parties in the connection. Click **Edit** next to a party to configure who receives notifications for this specific partner and document type.
The same **Include document specific contacts** toggle is available here for this specific partner and document type, and it overrides the document-level choice for that connection. Enable it to also notify contact email addresses included in a document, in addition to your default recipients. See [Contacts Declared by Your Trade Partner](#contacts-declared-by-your-trade-partner) for details.
**Editing permissions depend on your partner's status.** If your trade partner is not a Procuros customer, you can edit the responsible users for both parties in the connection. If your trade partner is also a Procuros customer, you can only edit your own party's responsible users — the other party's recipients are managed by them and shown as read-only with the label "Recipients are defined by your trade partner".
## Unrecognized Email Domains
To protect against misconfigured notifications, Procuros verifies the email domains used for notification recipients. When you save changes that include email addresses from domains that have not been previously approved for your organization, Procuros will show a review dialog before applying the changes.
The dialog separates the email addresses into two categories:
* **Approved** — Email addresses from domains that are already recognized by your organization. These are added immediately and will start receiving notifications right away.
* **Require domain approval** — Email addresses from domains that are not yet recognized. These will **not** become active until the domain has been approved internally. The email addresses are shown highlighted in yellow to indicate they are pending.
To submit unrecognized domains for review, click **Request Approval**. You can also click **Back** to return to the edit dialog and remove or correct the email addresses before proceeding.
Until a domain is approved, email addresses from that domain will not receive any notifications. Make sure to follow up on approval requests if notifications are time-sensitive.
This page covers managing **who** receives notifications. To configure **which types** of notifications you personally receive (e.g., issue alerts, incoming documents, sent documents), visit [Profile & Preferences](/en/general/admin/profile-preferences).
# Change Password
Source: https://docs.procuros.io/en/general/admin/password
Learn how to securely change your password in the Procuros Portal
Your new password must meet security requirements and should be different from your previous password.
Navigate to "Settings" in the left sidebar. You can find the settings section at the bottom under "Your Account."
In the "Account" section, select the "Password" menu option. The password change form will be displayed.
* Enter your current password in the "Current Password" field
* Enter your desired new password
* Repeat the new password for confirmation
Click "Save" to apply the password change. After a successful update, you can log in with your new password.
Store your new password securely and do not share it with others. If you lose your password, please contact Procuros Support.
* At least 8 characters in length
* A combination of uppercase and lowercase letters
* At least one number
* At least one special character
* No reuse of previous passwords
# Manage Profile & Preferences
Source: https://docs.procuros.io/en/general/admin/profile-preferences
Learn how to customize your personal settings in the Procuros Portal, including language, name, and notification preferences.
In the Profile & Preferences settings, you can manage your personal data and choose which notifications you want to receive from Procuros. These settings are specific to each user and do not affect other team members' preferences.
## Manage Profile Information
In this section, you can update basic information about your user profile.
Navigate to "Settings" in the left sidebar and select "Profile & Preferences" from the menu.
At the top of the page, you will find your email address and the option to update your name.
Choose your preferred language from the dropdown menu. Currently, German and English are available.
## Configure Notifications
Control which notifications you want to receive from Procuros. Notifications help keep you informed about important activities in your network.
* **Issue Notifications**: Receive alerts when there are issues with a transaction
* **New Incoming Documents**: Get notified when new documents arrive from your trading partners
* **Successfully Sent Documents**: Receive confirmation when your documents have been successfully sent to trading partners
**Exception for WebEDI users**
If you send and receive documents via our portal (WebEDI), you will receive all transaction-related notifications (e.g. new documents and reminders), even if you deactivate them in your profile. This is because emails are the only communication channel for WebEDI suppliers as they do not receive documents directly in their system.
Use the toggles next to each notification type to turn them on or off.
Click "Save" to apply your changes. The new settings will take effect immediately.
Even if you disable notifications, you can still view all your documents and transactions within the portal.
# SSCC Settings
Source: https://docs.procuros.io/en/general/admin/sscc-settings
Learn how to configure your GS1 company prefix, serial numbers, and label printer resolution for SSCC labels in the Procuros Portal.
SSCC Settings is only available if the SSCC Labels feature is enabled for your company. If you don't see this page in your Settings, contact Procuros to have it activated.
## What Is an SSCC?
An **SSCC (Serial Shipping Container Code)** is a globally unique 18-digit number used to identify a logistics unit, such as a pallet, carton, or container, as it moves through the supply chain. It is made up of four parts:
1. **Extension digit** — 1 digit, used to extend the capacity of the serial reference.
2. **GS1 company prefix** — 7 to 10 digits, assigned to your company by GS1.
3. **Serial reference** — fills the remaining digits, issued sequentially by Procuros.
4. **Check digit** — 1 digit, calculated automatically to detect scanning errors.
Procuros assembles the full 18-digit SSCC for you from the GS1 company prefix and serial number configured on this page — you never have to type or track a full SSCC yourself.
SSCCs are used to identify transport units on shipping notices. See [Sending Shipping Notices](/en/general/portal/transactions/sending-shipping-notices) for how they fit into a shipment, and [Package Identification](/en/api/v2/features-package-identification) for how they appear in the API.
## SSCC Generation
Click on **Settings** in the left navigation bar and then select **SSCC Settings**.
In **GS1 company prefix**, enter the digits GS1 assigned to your company. Every SSCC you issue is built on this prefix. You can obtain a prefix from your national GS1 member organization if you don't already have one.
**Next serial number** shows the next serial number that will be issued for your prefix. It is managed automatically and stays read-only unless you change the prefix above.
Changing the GS1 company prefix turns the field into **First serial number** — the serial number to start from. Leave it empty to start from 1, or set it if you've already printed SSCCs elsewhere and want numbering to continue instead of starting over.
Changing your GS1 company prefix restarts your serial number sequence, and issuing a serial number that has already been printed produces duplicate SSCCs on the network. Trading partners may reject shipping notices that reference a duplicate SSCC. Only change your prefix when GS1 has actually reassigned it, and double-check the next serial number if you do.
## Labels Printing
In **Printer resolution**, select the dots per millimeter (dpmm) of the label printer you use for SSCC labels:
| Printer resolution | Equivalent |
| - | - |
| 6 dpmm | 152 dpi |
| 8 dpmm | 203 dpi |
| 12 dpmm | 300 dpi |
| 24 dpmm | 600 dpi |
If you're not sure which resolution your printer uses, check its spec sheet or configuration label. Selecting the wrong resolution can cause labels to render at the wrong physical size, which may prevent the SSCC barcode from scanning correctly.
All changes will only be applied and activated after clicking **Save**. Click **Cancel** to discard your changes.
# AI Agents
Source: https://docs.procuros.io/en/general/portal/ai-agents
Here's a look at how Procuros's AI Agents work, what they do, and where they fit into your document flow.
Procuros offers several AI Agents that take manual work off your plate and keep your data clean across document exchange.
Think of them as extra teammates: one reads the PDFs landing in your inbox, another translates documents into the format your ERP expects, and others cross-check incoming documents and enrich them using data from previous transactions. Together, they let documents flow from your trade partners straight into your systems with far less manual effort on your side.
## Document Understanding Agent
When a trade partner emails you a document, an AI Agent can read the PDF and extract the data automatically — no copy-pasting into your ERP. The agent classifies each document, matches it to the right sender, and passes the data on to your system.
Document Understanding is a paid feature. Each document the agent processes uses credits from your account.
## Data Enrichment
Not every incoming document is complete. A supplier might send an invoice without the article numbers your ERP needs, or a purchase order that's missing a reference your system relies on. Instead of bouncing the document back, an AI Agent can look at related documents and past transactions with that trade partner, finds the matching information, and fills in the gaps automatically.
The more you and your partner exchange documents, the smarter this gets — every transaction becomes context the agent can draw on next time.
Data Enrichment is currently in beta — free to use while we refine it.
## Transformation between formats
You and your trade partners probably don't use the same systems or file formats. An AI Agent sits in the middle: it takes whatever the sender sends, fills in any missing details from your master data, and delivers it in the exact format your system expects.
Custom Transformations is currently in beta — free to use while we refine it.
## How to know when an agent was involved?
Whenever an AI Agent has worked on a document, it's clearly marked with an AI tag in the Portal. That way you can tell at a glance which transactions went through an agent and which didn't — useful for spot-checks, audits, or just knowing where the agent stepped in.
# My Connections
Source: https://docs.procuros.io/en/general/portal/connections
An overview of your trading partner connections in Procuros – check status, activate new connections, and manage existing ones.
## Overview of Trading Partner Connections
The main view displays all your trading partners and their connection status. Each partner is shown along with the available document types and their current status.
### Document Type Status
Different document types are indicated by color codes:
* **Green**: Document type is active and live
* **Blue**: Ready for test or live transactions
* **Gray**: Document type is inactive or awaiting partner action
## Navigation and Filtering
Use the search field "Search by partner name" to quickly find specific trading partners.
Filter the view by:
* Message type (e.g., orders, invoices)
* Actions required
* Show deactivated partners
## Managing Trading Partner Connections
### Open Detail View
Click on a trading partner or document type to open the detail view. This displays:
* Current connection status
* Progress of document type activation
* Required actions
Using the three-dot menu next to each partner, you can:
* Request new document types
* View transaction overview
* Access price lists (if available)
### Activating New Document Types
**Testing Phase Requirement**
A testing phase is generally required when a buyer and supplier are connected via an integration.
If a supplier is using the portal to send and receive documents, testing is typically not necessary.
For integrated connections, follow these steps to complete the testing phase:
1. Open the detail view of the desired document type.
2. Follow the displayed test instructions.
3. Send the required test documents.
4. Wait for validation from the trading partner.
The specific steps for sending test documents vary depending on the integration type. Detailed instructions can be found in the integration guide for your chosen integration method.
# Document Understanding Agent
Source: https://docs.procuros.io/en/general/portal/document-understanding-agent
> The Document Understanding Agent is one of the AI Agents in Procuros. Where the [Order Agent](/en/general/portal/order-agent) digitizes the purchase orders coming in, the Document Understanding Agent handles the documents that come back: order confirmations, shipping notices, invoices, and credit notes. It reads the PDFs your trade partners email you, checks them against the original order, flags anything that needs a look, and delivers them into your system.
## What the agent does
When a trade partner emails you a document, the Document Understanding Agent reads the PDF and extracts the data automatically — no copy-pasting into your ERP. The agent:
1. Classifies the document type.
2. Matches the document to the right trade partner.
3. Extracts the data you need from the PDF.
4. Matches the document to the related order and enriches it with data from that order that isn't in the PDF itself.
5. Flags anything it can't resolve cleanly, so it can be reviewed.
6. Delivers the document into your ERP once it's ready — or holds it in the Procuros Portal for review first (depending on your setup).
## Reviewing transactions
During digitization, each document runs through a set of automatic verification checks that confirm the extracted data lines up with the original order. For any check the agent can't resolve on its own, it raises a flag for review in the Portal.
The review is done by whoever is assigned as the [issue resolver](/en/general/troubleshooting/blocked-transactions#the-issue-resolver) — which can vary by document type (order, invoice, etc.) and trade partner. Depending on how your relationship with a given trade partner is set up, that's either you or them.
A flagged document is held in the Portal and is not delivered until the review is complete. The issue resolver receives an email notification whenever a document is waiting for them.
If the review falls to you:
1. **Open the transaction in the Portal.** The email notification links straight to it, or you can find it in your transaction list.
2. **Inspect the warnings.** Each flag is pinned to the field or line it concerns. See [Understanding warnings](#understanding-warnings) for what each one means.
3. **Compare against the original PDF.** Check the flagged data against the source document to decide whether the extraction was correct.
4. **Edit the data if needed.** A warning doesn't always mean the extraction was wrong — sometimes the document genuinely differs from the original order. Correct the data only where the extraction doesn't match the PDF.
5. **Mark the transaction as reviewed.** The document then continues on its way and is delivered as normal.
## Understanding warnings
Each flag appears as a warning pinned to the field or line it concerns.
| Flag | What it means |
| - | - |
| Date looks unusual | A date on the document (for example the delivery or document date) is outside the normally expected range. |
| Higher quantity than ordered | A line shows a quantity greater than what was originally ordered. |
| New line not on the original order | A line appears on the document that wasn't on the original order. |
| Ordered line missing | One or more lines from the original order weren't found on the document. |
| Total quantity is zero | The document's total quantity came through as zero. |
| Total quantity doesn't match | The overall total quantity on the document doesn't match the sum of its individual line items. |
For each flag, check the data against the original attachment to confirm whether it's valid.
# Getting Started
Source: https://docs.procuros.io/en/general/portal/getting-started
Learn about the core functions of Procuros. This guide walks you through the key areas of the platform and explains how to get started.
Procuros is your central platform for digital collaboration with your trading partners. As a network, Procuros connects buyers and suppliers, enabling the automated exchange of business documents such as orders, order confirmations, and invoices.
## Signing in to Procuros
You can access Procuros via portal.procuros.io. No password is required—magic links sent to your email provide seamless login when new orders arrive or when a trading partner invites you to Procuros.
However, passwords are available as an alternative login method. When you first log in via a magic link, a password is automatically assigned, which you can change or reset anytime in the portal. On the login page, you can either enter your password or request a new magic link.
## Navigation and Key Features
The sidebar serves as the central navigation tool for the platform. Here, you will find all essential functions arranged from top to bottom:
### Dashboard
The dashboard is your homepage in Procuros. Depending on whether you're using a direct integration with Procuros or not, you'll see two variations of the dashboard.
1. As a supplier **using an integration**:
* **Overview Section**: Displays key metrics such as your transaction volume and the number of active trading partners.
2. As a supplier **without an integration**:
* **Inbox**: Acts as a central hub for your daily workflow, providing quick access to:
* [Pending order responses](https://docs.procuros.io/en/general/portal/transactions/sending-order-responses)
* [Pending shipping notices](/en/general/portal/transactions/sending-shipping-notices)
* [Invoices](/en/general/portal/transactions/sending-invoices) that need processing
* [**Blocked transactions**](https://docs.procuros.io/en/general/troubleshooting/blocked-transactions)
* **Forwarding email address:** Instead of submitting documents using the portal, you can simply forward your documents as PDF to this email ([learn on how to set that up using Outlook](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding))
### Transactions
Under "Transactions," you will find a complete overview of all your business activities. The view can be filtered by various criteria, such as:
* Document type (orders, invoices, etc.)
* [Status](/en/general/portal/connections#status-der-dokumententypen) (open, in progress, completed)
* Time period
* Trading partner
### Price Catalogs
This section is only visible if at least one of your trading partners uses the price catalog feature. Detailed instructions on how to use it can be found in our dedicated article on price catalogs.
If Price Catalogs are not enabled in your account, you will see Price Lists instead. Price Lists allows users to include their prices, which can then be automatically applied when generating invoices in the portal.
### Connections and Network
Managing your business relationships is done through two closely related sections:
* **My Connections**: Overview and management of your existing trading partners.
* **Procuros Network**: Search for and request new connections with potential trading partners.
### System Integration and Support
At the bottom of the navigation menu, you will find:
* **Integrations**: Management and request of system integrations.
* **Settings**: Configuration of your Procuros account.
* **Help & Customer Support**: Direct access to the Help Center and support.
You can log out of the platform via the user profile in the bottom right. You can always regain access through a valid link in your Procuros emails.
## Next Steps
After setting up your account, we recommend:
Add your [company details in the settings.](/en/general/admin/company-data)
Review your existing trading partners under "[My Connections.](/en/general/portal/connections)"
Learn about the [different document types ](/en/general/portal/transactions/transactions-intro)and how to process them.
Detailed guides on individual features can be found in the corresponding articles in our Help Center.
# Multi-Partner Workspace
Source: https://docs.procuros.io/en/general/portal/multi-partner-workspace
Use one Procuros account to access multiple companies and switch between them from the portal.
A single Procuros account can have access to multiple companies. You can switch between them from inside the portal without signing out.
## Why use a multi-partner workspace?
Multi-partner workspaces are for people whose work spans more than one company on Procuros. Common cases:
* **Agents and sales representatives** working on behalf of several brands. A fashion agent, for example, might receive orders for three different brands they represent — each brand has its own Procuros account, with its own company data, so each one is a separate workspace.
* **Multi-brand groups**, where a single person needs to review and process documents across the different companies in the group.
* **Shared service teams** (operations, finance, customer support) that handle trading documents for several Procuros customers from one place.
In each case, you sign in once with your email and switch between the companies you have access to — without juggling separate accounts.
## When you get multi-partner access
Your account is automatically linked to additional workspaces in either of these cases:
* **A colleague invites you using the email you already use for Procuros.** Anyone in another company on Procuros can [invite you as a team member](/en/general/admin/invite-new-team-members), and your account is linked to that workspace automatically.
* **Procuros support sets it up for you.** If you need access to another company's workspace and an invite isn't an option, contact support and we'll link your account manually.
## Switching between companies
The active workspace is shown by the company logo in the portal. To switch:
Click the company logo in the sidebar to open the list of workspaces you have access to.
Select the company you want to switch to. The portal reloads into that workspace, and the logo updates to reflect your selection.
## What's shared across workspaces
Some settings follow you into every workspace; others belong to the company you're working in.
**Shared across all workspaces:**
* Your name and email
* Language preference
* Password and login method
* Notification preferences
**Specific to each workspace:**
* [Company data](/en/general/admin/company-data) (name, address, identifiers like GLN and VAT ID)
* [Team members](/en/general/admin/invite-new-team-members)
* Trading partner [connections](/en/general/portal/connections) and [network](/en/general/portal/network)
* [Transactions](/en/general/portal/transactions/transactions-intro)
Changing your language or notification preferences in one workspace applies everywhere, but each workspace's company data, team, and transactions stay separate.
## Inviting someone who already uses Procuros
When a team member [invites a colleague](/en/general/admin/invite-new-team-members) using an email that's already attached to another Procuros workspace, that colleague is automatically given access to your workspace too. They don't need to create a new account, and there's no extra setup — the next time they sign in, your workspace appears in their switcher.
# Procuros Network
Source: https://docs.procuros.io/en/general/portal/network
Learn how to expand your trading network and connect business partners through the Procuros Network.
The Procuros Network allows you to digitally connect with your trading partners for the automated exchange of business documents. Through the central network overview, you can find existing partners and establish new connections.
## Find Trading Partners
The network overview offers various ways to find your trading partners:
Use the search bar at the top of the screen to search for your trading partner by name.
Use the filters for status and industry to narrow down the display:
* Status: Available to connect, Connected, Pending
* Industry: e.g., Food, Fashion, Household Goods
## Establish a Connection with a Trading Partner
Click the "Connect" button next to the desired trading partner.
Choose the identification method:
* GLN (Global Location Number)
* Internal Identifier
Specify which document types you want to exchange:
* Receiving: e.g., Orders
* Sending: e.g., Dispatch Notifications, Invoices
## Invite New Trading Partners
If your trading partner is not yet in the Procuros Network, you have two options:
### Invite an Individual Partner
Click on "Invite Trading Partner" in the upper right corner.
Fill in the required fields:
* Trading partner name
* Contact person
* Email address
* Phone (optional)
* Preferred language
Set the GLN or internal identifier and select the desired document types.
### Invite Multiple Partners at Once
Inviting and onboarding new trading partners is free of charge. Your partners can decide which document types they want to support.
Download the CSV template via the corresponding button.
Fill out the CSV template with your trading partners' details.
Upload the completed CSV file and select the desired document types.
After sending the invitation, Procuros will handle the communication with your trading partners and support them in connecting to the network.
# Order Agent
Source: https://docs.procuros.io/en/general/portal/order-agent
> The Order Agent is one of the AI Agents in Procuros. It takes the manual work of order entry off your plate: it reads the purchase orders your customers email you, checks them against your product and customer data, flags anything that needs a look, and delivers them into your system.
## What the Order Agent does
When a customer emails you a purchase order as a PDF, the Order Agent:
1. Reads the PDF and extracts the order — order number, line items, quantities, prices, delivery and invoice details.
2. Matches it to the right customer and the right articles, using the master data you've provided. If a new customer orders, the order agent will ask you whether they should be added to your master data.
3. Flags anything it can't resolve cleanly (an unknown article, an unrecognised sender, a missing field) so you can review it.
4. Delivers the order into your ERP once it's ready — or holds it in the Portal for your review first.
It works in all major business languages, including English, German, French, Spanish, Italian, and Dutch, and recognises customer-specific terminology.
💳 The Order Agent is a paid feature. Each order it processes uses credits from your account.
## What it works with (and what it doesn't)
**B2B Orders that arrive as PDF attachments by email.** This is what the Order Agent is built for.
The Order Agent processes orders sent as PDF email attachments. Orders that arrive as links, embedded images, Excel/CSV files, free-text email bodies, or through a web portal are not processed by the Order Agent today. Orders that already flow via EDI don't need the Order Agent — they route into your system directly, and the two work side by side.
## Getting started
Setting up the Order Agent takes one main step on your side: forwarding your order emails to Procuros.
1. **Receive your Procuros order address.** Procuros gives you a unique inbox address for your account, in the form `orders+yourcompany@procuros.io`. Every order email you forward to this address is picked up automatically.
2. **Set up email forwarding.** Set up an automatic forwarding rule from the mailbox where you receive customer orders to your Procuros address. This is where the time saving happens — once the rule is active, every incoming order is picked up without anyone on your team doing anything. See the "[Setting Up Email Forwarding](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding#setting-up-email-forwarding-in-microsoft-outlook)" guide for step-by-step instructions.
3. **Confirm orders are arriving.** Once forwarding is active, forwarded orders start appearing in your Procuros Portal. You can review them under Transactions.
We recommend automatic forwarding over forwarding each order by hand. The Order Agent only acts on emails that contain an actual order attachment — internal threads, confirmations, and other inbox traffic are skipped automatically, so a blanket forwarding rule won't cause noise.
## Reviewing orders in the first weeks
When you first go live, we recommend a manual review phase of about 1-3 months. During this phase, every order the Order Agent processes waits for you to review it in the Portal before it's sent to your ERP.
1. **Open the processed order.** The order appears in your transaction list. Open it to see the extracted data alongside the original PDF.
2. **Compare against the original.** Check the extracted fields against the source PDF to confirm everything was captured correctly. Any warnings or issues are shown directly on the order.
3. **Submit to your ERP.** Once you're satisfied, submit the order. It's delivered into your system in the format your ERP expects.
After a stable review period, most customers choose to let orders flow straight from inbox to ERP without manual review.
Whenever the Order Agent has worked on a document, it's marked with an AI tag in the Portal, so you can tell at a glance which orders went through the agent.
## Understanding warnings and statuses
The Order Agent tells you clearly when an order needs your attention, both in the Portal and in the summary emails you receive. Here's what the most common messages mean.
The order was imported successfully, but something is worth a look — for example a new article or a new partner was added to your master data. Warnings don't block delivery; you can review and edit before sending if needed.
The order needs you to check it before it's delivered. Open the order, review the content, and edit if necessary before submitting.
The Order Agent extracted an item from the PDF but couldn't match it to a known article. This usually means the article (or its GTIN/EAN) isn't yet in your master data. Add or correct the item, then resubmit.
The sender doesn't match any trade partner registered for your account. If you recognise the partner and their identifiers, you can submit the order. If a customer that isn't in your master data sends an order, the Order Agent won't book it against the wrong account — it flags it and lets you decide whether to process orders from that customer going forward.
The order has one or more blocking issues that must be fixed before delivery. Click "Edit" to resolve them, then resend the document.
A document with the same number already exists in your system, with differences in content. The Order Agent holds it and alerts you rather than silently creating a second entry — so you stay in control of whether to deliver it.
## Troubleshooting
Two causes are common:
* **External forwarding is blocked by your IT settings.** Some organisations (often on Microsoft Outlook / Office 365) disable external email forwarding at the admin level, with no obvious error shown to the user. Ask your IT administrator to allow external forwarding (including attachments!).
* **Forwarding is set up on the wrong mailbox.** Double-check the rule is active on the inbox where you actually receive customer purchase orders — not a general or accounting inbox.
Common causes are an article that isn't yet registered in your ERP catalogue, or a required field that's missing. The order's warnings will point to what's missing — resolve it and resubmit. If the issue isn't clear, contact Procuros support.
This is common very early in the pilot and for low order volumes (less than 10 orders per week). Accuracy improves as the agent is tuned to your specific customers and catalogue, and most repetitive corrections you make by hand can be automated. If specific fields are consistently off, let your Procuros contact know — these patterns can usually be fixed so you stop correcting them.
## FAQ
Within 48 hours of setup. We connect to your existing ERP processes and immediately start delivering documents (such as compliant e-invoices) to all your customers — no waiting, no complex implementations, no IT projects.
No technical expertise is needed to get started with Procuros. Our platform is designed to be plug-and-play, with pre-built ERP connectors and AI that works out of the box. There’s no need to configure OCR tools, create mappings, or run complex IT projects.
PDF orders. Our AI-powered platform automatically reads and processes them - no manual setup or configuration required. This means you can connect with all your customers, regardless of their technical capabilities.
Not at all. Your customers keep ordering exactly as they do today — by email, in whatever format they use. No new portal, no new process, no onboarding on their side. All it takes is a simple email forwarding rule on your end, and the Order Agent takes it from there.
Yes — and this is one of the areas where the Order Agent goes well beyond simple data extraction. Real-world orders are often messy: customers reference outdated article numbers, use incorrect GTINs, or send product identifiers that no longer match your current catalog. Rather than just flagging these as errors, the Order Agent can be configured with custom business rules to handle them automatically. For example, if a customer consistently orders using a child GTIN but your ERP only knows the parent GTIN, the Order Agent can be set up to recognize and correct this automatically — without any manual intervention.These kinds of custom rules are built together with you during onboarding, based on the specific quirks of your customers and catalog.
Accuracy is something we take very seriously. Because we have a dedicated team continuously maintaining and improving the Order Agent across all our customers, we typically observe 99% extraction accuracy. That said, we always recommend a one- to three-month review phase when you first go live. During this period, you review each processed order in the Procuros portal — comparing it against the original PDF to confirm everything has been captured correctly — before clicking to submit it to your ERP. This gives you full confidence in what's going into your system without any risk of incorrect data slipping through. After a month of smooth operation, most customers choose to fully automate this step — orders flow straight from inbox to ERP without any manual review needed.
Mostly yes. The Order Agent can process scanned and non-standard order documents, but documents that are unreadable, incomplete, or ambiguous are flagged for review instead of being pushed blindly into your ERP.
No. The Order Agent detects if an order matches one already in your system, so accidental duplicates don't end up in your ERP.
Yes, they work side by side. Customers connected via EDI continue to flow through that channel directly, while the Order Agent handles everyone who still sends orders as PDFs by email. You don't have to choose one or the other: the Order Agent is built to cover the long tail of customers who aren't on EDI, so you can automate all of your incoming orders regardless of how each customer sends them.
Yes. Customers often order using their own article numbers rather than yours. The Order Agent can be configured to translate a customer's codes into your internal product codes automatically, so the right item is always matched. These mappings are set up as custom rules during onboarding and improve over time as the agent learns from your data.
Yes. If a customer orders in one unit (e.g. individual pieces) but your ERP expects another (e.g. cases, trays or pallets), the Order Agent can apply the conversion automatically before the order is booked. The conversion logic is set up during onboarding based on your product data, so every future order from that customer is handled without any manual recalculation.
Yes. Customer-specific rules can be configured during onboarding, so orders can be checked before booking. If something violates a rule, the order can be held for review.
It does not silently guess. You receive a review notification for orders with unclear customer, product, quantity, or required-field information, so your team stays in control before anything is booked.
OCR extracts text. The Order Agent goes further: it understands the order, matches it to your customers and products, applies business rules, flags exceptions, prepares the order for booking and finally sends it to your ERP.
Yes, if the mapping logic is known. During onboarding, Procuros can configure rules for cases where customers still use old article numbers, outdated GTINs, or customer-specific product references.
The Order Agent flags the order instead of forcing it through. For example, if a delivery date, product identifier, or customer detail is missing and required for your process, the order can be held for review before anything reaches the ERP.
Personal data contained in the order emails and PDFs you forward (such as the professional contact details of your buyers' employees) is covered by the standard Procuros Data Processing Agreement. See the [Data Processing Agreement](https://procuros.io/data-processing) for the full details, including the technical and organisational security measures in place.
# Order Forms
Source: https://docs.procuros.io/en/general/portal/orderform
Learn how to place an order via a Procuros order form to one of your suppliers
## Intro
The **Order Form** allows you to place orders directly with your supplier — quickly, securely, and with your order sent straight to their system.
Each supplier manages their own catalog and pricing, so what you see in your Order Form is tailored specifically to your company.
## Accessing the Order Form
Your supplier will share a link with you by email, for example:
```
https://portal.procuros.io/order-form/[supplier-name]
```
Tip: Bookmark the link for easier access next time.
## Logging In
You must be logged in to view and use the Order Form. This ensures you see the correct prices and terms for your company.
You have **two ways to log in:**
* **Magic link:**
Enter your business email address and click **Send me a log in link via email.** You’ll receive a secure login link by email. Click it to access the order form instantly.
* **Email and password:**
If you’ve already set a password, you can use it instead. You can also reset your password at any time.
Only email addresses that your supplier has set up can access the order form. If you try to log in with a different email, access will be denied.
To invite more users from your company, enter the [Procuros Portal](https://portal.procuros.io/), go to **Settings → Team Members → Add Member.**
## Browsing and Searching Products
Once logged in, you’ll see a list of all available products.
Browse through the list and add items to your order by entering the desired quantities.
Please pay attention to the specified **unit of measure:** some items may only be available in trays or boxes.
You can find products in two ways:
* **Search bar:** Search by product name, GTIN, article number, or keyword.
* **Category list:** Click a category name to jump directly to that section of the form.
## Minimum Order Amount
Some suppliers might require a **minimum order value** for orders.
If this applies to you, a message will appear on the top of the screen indicating how much more you need to reach the minimum.
## Completing your order
When you’re done selecting items, click **Proceed to Shipping** in the top-right corner.
Take a moment to review your order summary and double-check all quantities.
If everything looks correct, fill in your address details:
1. **Delivery Address** – choose where the goods should be delivered.
2. **Billing Address** – choose or enter your invoice details.
If you’ve ordered before, your previously used addresses will appear in the dropdown list.
You can also add a new address, which will be stored for future use.
## Add notes for your supplier
Below the address fields, you’ll find an **open text field** where you can include any additional information for your supplier — for example:
* Delivery instructions
* Internal references
* Any other message you’d like to share about the order
These notes will be sent together with your order and visible to your supplier.
## Placing Your Order
Once you’re ready click **Place order**.
You’ll immediately see a confirmation screen and receive a **confirmation email** with all order details. You can also **download a PDF copy** of your order.
## What Happens Next
Your order is automatically transmitted to your supplier’s system, no need to send a separate email or document.
Your supplier will process the order and follow up as usual.
## Troubleshooting
Make sure you’re using the same email address registered by your supplier. If you’re unsure, contact your supplier’s sales team or support.
Verify you’re using the email registered by your supplier. Then check your spam folder or ask your IT team to whitelist `@procuros.io`.
Prices are set by your supplier and may be tailored to your company. Contact your supplier for clarification.
# Payment Reconciliation
Source: https://docs.procuros.io/en/general/portal/payment-reconciliation
Learn how to identify and resolve payment data by comparing your exchanged documents with remittance advices.
Procuros automatically matches payments to invoices using the details provided in remittance advices and reconciles the payment information against your submitted invoices — ensuring accuracy down to the cent.
## Overview of Payment Reconciliation
The reconciliation dashboard is divided into two tabs: Open Remittance Advices and Completed.
These are remittance advices that still require your attention. This could be because the reconciliation process is not yet fully complete or the data has not yet been manually pushed to your ERP system.
These remittance advices have been fully reconciled. No further action is required, and the payment information has already been updated in your ERP system.
### Payment Reconciliation Detail View
The detail view displays all key information about the documents referenced in the remittance advice. In the list, you’ll be able to review each referenced document along with its current status. The possible statuses are:
The document has been manually reviewed and approved.
The referenced document contains amount differences when compared to the remittance advice.
The document **requires manual approval**. It was referenced in the remittance advice but has not yet been received by Procuros. To proceed with reconciliation, you’ll need to manually approve the missing document. This confirms that the reference is valid even if the original document wasn’t received through Procuros.
The document **requires manual approval**. This status typically applies to Debit Notes and Service Invoices, as these types of documents are not transmitted through Procuros automatically.
The document was automatically matched with the remittance advice by the system.
Reconciliation progress will only reach 100% once all referenced documents are either **Approved** or **Reconciled**. Only then will you be able to submit the remittance advice to your ERP system. Until that point, any unresolved items must be addressed to ensure data consistency. Please note that **discrepancies do not impact the reconciliation process** percentage.
Once the reconciliation is complete and the remittance advice has been submitted to your ERP system, Procuros will automatically mark the corresponding pending invoices as Paid.
### How to use the feature
Open the "Open Remittance Advices" tab to view your open inbox.
Click on a single remittance advice to view its line items. By clicking 'View Pending Items Only' all items that require your action will be auto-filtered. You can click on them one by one to make a decision on them or leave an internal comment.
Discrepancies do not hold back remittance advice submission but it is generally advisable to review any discrepancies with an abnormal discrepancy percentage.
Click 'Submit to ERP' to update all documents as paid in your ERP system that are contained within the remittance advice. If certain documents are not in your ERP system (e.g., because you manage your liabilities in a third party system), nothing will happen to them and only the documents that can be found will be updated.
Keen to see anything that you submitted in the past? All historic submissions are stored under the 'Completed' tab.
### FAQs
Procuros will look up all documents that correspond to the document numbers in the remittance advice and change their status to paid / redeemed.
With submission, any document will be **marked as fully paid**. Procuros does not distinct between partial and full payments, hence discrepancies will be highlighted before submission so that you can take corresponding action if desired.
No, the current version only supports status changes. To see a breakdown of deductions, simply hover your mouse cursor over the discrepancy in Procuros (only shown if the retailer sends that information).
Missing documents are indicated as documents that are unknown to Procuros. This is typically the case for document types that are not yet transmitted via Procuros, but rather outside of it (e.g., debit notes).
Not yet. The current version focusses exclusively on the translation of EDI messages from larger retailers like EDEKA and Markant partners. The support of PDF and CSV files is on the short-term roadmap for the feature.
All documents are globally searchable via Procuros. Simply use the search function under 'Transactions' by using the document number. After clicking into the document, all related transactions (e.g., the remittance advice the invoice was included) are linked in the right side bar.
Unfortunately not yet. This is a heavily requested improvement and it's on our product roadmap. For now, please refer to the discrepancy percentages to see whether a discrepancy is within expectations and if not, hover the discrepancy pill to see a breakdown of the discrepancy.
No. The current version only updates whichever documents you work on in your ERP.
If you have an active EDI connection covering Markant service invoices, those will in the current version of the feature moved directly to the 'Completed' tab (effectively skipping the invoice). This is due to the fact that the current feature integration does not support the updating of service invoices in the ERP.
# Create Price Catalogs
Source: https://docs.procuros.io/en/general/portal/pricat
Learn how to create and manage price catalogs for your trading partners. Price catalogs allow you to maintain and share current product information and pricing with your trading partners.
Price catalogs allow you to share current product information and pricing with your trading partners.
1. **Open the Price Catalogs menu**
* In the side bar, click “Price Catalogs”.
2. **Choose your trading partner**
* Select your trade partner for whom you want to submit a price catalog.
3. **Click on “Create Price Catalog”**
* Start the submission process by clicking on “Create Price Catalog”.
1. **Download your partner’s template**
* Open the file in Microsoft Excel or in the spreadsheets editor of your choice. **Do not use your own Excel or spreadsheets** since it will be blocked by the system.
2. **Add in your data**
* Fill out the template by adding all required product and pricing information. You can just copy / paste whatever is available from other sheets you might already have. For further explanations, go to the Data Fields section below.
3. **Upload completed template**
* Once finalized, save the file to your computer and upload the filled out version to Procuros.
Note: The system will ignore any additional columns not present in the original template.
1. **Review data validation results**
* Make sure that the data was translated as intended.
2. **Address any flagged errors**
* Potential errors will be highlighted in red.
3. **Name your Price Catalog**
* Use a unique identifier that is aligned with your byuer.
4. **Set a Price Catalog date**
* We recommend using the date on which you submit your Price Catalog.
5. **Submit your Price Catalog**
* Your trade partner will receive the data after you click on “Send Price Catalog” in the top right corner.
Your Price Catalog will not be submitted, if you just uploaded it, but did not click on "Send Price Catalog".
### Industry-specific Data Fields
**Rules before filling in Data Fields**
* Only use your partner’s Excel template. Other documents won’t be accepted.
* Mandatory fields in the template are marked with an asterisk \*
* Optional fields in the template are displayed without asterisk
* Conditional fields are displayed with 2 asterisks \*\*
**Meaning of each Data Field**
1. **GTIN/EAN\***: Global Trade Item Number/European Article Number (unique product identifier).
2. **Name\***: Product name. Do not add color, size or any other information to the name. If not sure, please reach out to [help@procuros.io](mailto:help@procuros.io).
3. **Supplier Article Number\***: Supplier's internal product identifier. Do not add color, size or any other information to the Supplier Article Number. If not sure, please reach out to [help@procuros.io](mailto:help@procuros.io).
4. **Buyer Article Number**: Buyer's internal product identifier (if available).
5. **Currency\***: Three-letter currency code (EUR, USD, etc.). Do not use other currency descriptions - they won’t be processed. Only 3 letter codes.
6. **Unit**: The sales unit e.g., piece, box, kg (if available).
7. **Unit Price\***: Price for a single unit, based on the selected unit and currency.
8. **HS Code:** Harmonized System Code is an international standard for classifying goods (if available).
9. **Unit Price Valid From\***: Start date when the unit price becomes valid. Please use only this format DD-MM-YYYY.
10. **Unit Price Valid Until**: Indicate when the current unit price expires. Please use only this format DD-MM-YYYY (if available).
11. **RRP\***: Recommended Retail Price for the product.
12. **Color Code\*\***: Product Internal color code.
13. **Color Name\*\***: Product's color in plain text (e.g., "Red", "Midnight Blue").
14. **Size\*\***: Item's size (e.g., S, M, L). If it has no size variants, use "One-size" or nothing.
15. **Dimension**: Varies by product group. Relevant only for trouser length and bra cup size. Otherwise please keep it empty. All other size related topics should be listed under size.
16. **Origin Country Code**: ISO country code where the product was manufactured (e.g., DE, CN, US). Please only write two-letter country code for product origin (if available).
**Rules before filling in Data Fields**
* Only use your partner’s Excel template. Other documents won’t be accepted.
* Mandatory fields are marked with an asterisk \*
* Optional fields are displayed without asterisk
**Meaning of each Data Field**
1. **GTIN/EAN\***: Global Trade Item Number/European Article Number (unique product identifier).
2. **Name**: Product name. Do not any other information to the Product Name. If not sure, please reach out to [help@procuros.io](mailto:help@procuros.io).
3. **Supplier Article Number**: Supplier's internal product identifier. Do not any other information to the Supplier Article Number. If not sure, please reach out to [help@procuros.io](mailto:help@procuros.io).
4. **Buyer Article Number**: Buyer's internal product identifier (if available).
5. **Unit\***: The sales unit e.g., piece, box, kg (if available).
6. **Quantity per Unit\***: Quantity of consumer units (pieces, bottles) contained in this item.
### How to Set up Article Variations & Multiple Values for a Single Field
If you have articles/products, that have **multiple values (e.g., images, packaging units) for a single field**, you can display this logic in the template in two ways:
1. **Duplicate article row** and change only specifics
2. **Add empty row** and add specifics of variation
Both methods are outlined below.
1. **Make the first entry**: include the main information of the product like GTIN, article name, price, etc.
2. **Duplicate the entire row**, including all main information.
3. **Change the parameter in the datafield that has a variation** (e.g., `Units)` only, leaving all the main information as is.
4. **Check whether the variation has dependent field** (e.g., `Per Unit Quantity`) and adapt accordingly.
1. **Make the first entry**: include the main information of the product like GTIN, article name, price, etc.
2. **Add a blank row below the entry**. If fields are empty, the template is always read as the closest article *above* the empty row.
3. **Add the parameter in the datafield that has a variation** (e.g., `Units)` only, leaving all the rest blank.
4. **Check whether the variation has dependent field** (e.g., `Per Unit Quantity`) and adapt accordingly.
# Setup tasks
Source: https://docs.procuros.io/en/general/portal/tasks
Learn how to complete tasks required by your trading partners to proceed with a connection.
When you establish a connection with a trading partner, they may require specific information before the connection can proceed. In that case, you will see tasks assigned to your connection that need to be completed.
Not all connections require tasks. If you don't see any tasks on your connection, it means your trading partner does not require any additional information and no action is needed on your part.
## Viewing your tasks
To view tasks assigned to a connection, navigate to **Connections**, select a trading partner, and click on a specific connection. Tasks are displayed directly in the connection detail view.
You can also use the **Action** filter on the Connections page to quickly find connections that need your attention.
## Types of tasks
There are two types of tasks you may encounter:
* **Tasks that require your action** — You'll see a form with fields to fill in, files to upload, or questions to answer. These must be completed before the connection can move forward.
* **Tasks handled by Procuros** — Some tasks are handled by the Procuros team. You'll see a description of what's being done — no action is needed from you for these.
## Completing a task
Open the connection detail page and locate the pending task.
Click on the task to expand it and read the description and instructions carefully.
Complete all required fields or upload the requested files.
Review your information to make sure it's correct, then click **Submit**.
Make sure all information is accurate before submitting. If your submission needs corrections, you will be asked to fix and resubmit it, which may delay the process.
### What happens after submission
Depending on the task, one of the following will happen:
* **Completed immediately** — Some tasks are marked as completed right after you submit. No further action is needed and you can move on to other tasks.
* **Goes into review** — Other tasks require the Procuros team to review your submission before it's considered complete. The task status will change to **In review**. If your submission is rejected, you will be notified by email with instructions on what needs to be corrected.
## Task statuses
Each task has a status that indicates where it is in the process:
* **Pending** — The task is assigned to the responsible partner but hasn't been submitted yet.
* **In review** — The task has been submitted and is being reviewed. No action needed at this time.
* **Completed** — The task is done. No further action needed.
* **Rejected** — The submission needs corrections. Check the feedback provided and resubmit.
Not all tasks go through a review step. Some tasks are marked as completed immediately after submission.
## Resubmitting a rejected task
If your submission is rejected, you will receive an email notification explaining what needs to be corrected. The rejection reason is also displayed directly on the task in the portal.
To fix and resubmit:
1. Open the task in the connection detail view
2. Read the feedback provided
3. Make the necessary changes
4. Click **Submit** again
## Reminders
If you have pending or rejected tasks, you will receive automatic email reminders twice a week — on **Mondays and Wednesdays at 08:00 UTC** — starting one week after the trade connection was requested. We recommend completing your tasks as soon as possible to avoid delaying the onboarding process.
# Import a CSV into Excel
Source: https://docs.procuros.io/en/general/portal/transactions/import-csv-into-excel
A quick 4-step guide to importing Procuros CSV exports cleanly into Microsoft Excel using the Text Import Wizard.
Double-clicking a CSV file often goes wrong — columns get misread, numbers turn into dates, IDs lose leading zeros, and everything lands in a single column. The Text Import Wizard handles it cleanly.
## Step 1 – Open the file
Launch Microsoft Excel.
From the top menu, choose **File → Import**.
Select **CSV** as the file type and open your file.
## Step 2 – Choose the import type
Choose **Delimited** — not "Fixed Width".
Leave **Start import at row** set to **1** so the header row is included.
Click **Next** to continue.
## Step 3 – Set the delimiter
Check **Comma** as the delimiter.
Make sure **Tab**, **Semicolon**, and **Space** are unchecked.
Leave **Text qualifier** as `"` (double quote).
Click **Next** to continue.
## Step 4 – Set column formats
Leave all columns set to **General** — this works for most data.
Click **Finish** to complete the import.
For columns with long IDs or numbers with leading zeros (e.g. GTINs, order numbers), click each column **before** hitting Finish and set it to **Text**. Otherwise Excel will truncate the values or convert them to scientific notation.
## Done
Your CSV is now loaded into Excel with columns correctly split and data readable. To save: **File → Save As** and choose **Excel Workbook (.xlsx)**.
# Orders
Source: https://docs.procuros.io/en/general/portal/transactions/receiving-orders
Learn how to efficiently process open orders in the Procuros Portal. This guide shows you how to access orders and process them, including creating subsequent documents.
The Procuros Portal allows you to centrally manage all incoming orders. You can view open orders, process them, and directly create follow-up documents such as order confirmations or shipping notices. This guide explains how to efficiently work with incoming orders.
## Accessing Open Orders
Navigate to the "Transactions" section and filter by the document type "Order." This will display all orders in chronological order.
## Viewing Order Details
After selecting an order, you will enter the detail view. Here, you will find:
* Order number and order date
* Comments from the trading partner or Procuros
* Complete list of ordered items
* Delivery and invoice addresses
* Transmission records and document status
## Processing an Order
Check the order details and any comments from the trading partner. The transmission record in the right sidebar confirms successful delivery.
Depending on your integration, you can create the following documents directly from the order:
* [Order Confirmation](/en/general/portal/transactions/sending-order-responses)
* [Shipping Notice](/en/general/portal/transactions/sending-shipping-notices)
* [Invoice](/en/general/portal/transactions/sending-invoices)
Use the corresponding buttons in the upper right corner.
For documents that support uploading PDF or CSV files, you can choose between "Create Manually" and "Upload Document."
## Additional Options
You can download any order as a PDF or CSV file. Use the "More Options" dropdown menu in the upper right corner of the detail view.
All follow-up documents, such as order confirmations or shipping notices, are automatically assigned to the correct trading partner and linked in the transaction history.
# Reprocessing & Resending
Source: https://docs.procuros.io/en/general/portal/transactions/reprocessing-transactions
Learn how to send a document to your trading partner again in Procuros, how reprocessing behaves depending on your connection, and how to edit a document before sending it again.
Sometimes a document needs to be sent to your trading partner again, for example if a previous delivery did not arrive as expected, or after the document was updated in your system. If you are the **sender** of a document, you can reprocess and send it again from the **More Options** button on the transaction detail view.
## Reprocess and Send
Open the transaction you want to send again and choose the reprocess option under **More Options**. What happens next depends on the connection the document was sent from:
Procuros retrieves the most recent version of the document from your ERP, processes it again, and delivers it to the recipient.
Use this when the document has changed in your ERP and you want the latest version to be sent.
For every other connection (for example API, SFTP, AS2, another ERP, or a document uploaded manually in the portal), Procuros processes the document it already received and delivers it to the recipient again.
No new data is retrieved from your system. The document is reprocessed using the information from when it was originally received.
## When Reprocessing Isn't Available
### The option isn't shown
The reprocess option only appears to the **sender** of a document. If you are not the sender, you won't see it at all, because only the sender can reprocess and send a document again.
### The option is grayed out
When you are the sender, the option may still be grayed out with the message *"Current status doesn't allow this action."* This can happen when:
* A **newer version of the document already exists** because it was replaced or revised.
* The document was **sent together with other documents in a single batch** and can't be reprocessed on its own.
* The **original document data is no longer available** to reprocess.
* The transaction is a **test transaction**.
## Edit Before Sending
If you need to change the document before sending it again, choose **Edit before sending** under **More Options**. Procuros creates an editable copy of the document so you can adjust it before it is sent to the recipient.
Changes you make here are only sent to the **recipient**. They are **not** saved back into your own system.
# Credit Notes
Source: https://docs.procuros.io/en/general/portal/transactions/sending-credit-notes
Learn how to create and manage credit notes for existing invoices in Procuros WebEDI.
A credit note is a document used to correct or partially cancel an already sent invoice. It allows you to refund amounts due to returns, price adjustments, or complaints.
## Three Ways to Provide Credit Notes
As a supplier, you have three options for providing Invoices via in Procuros
Create Credit Notes directly in the Procuros portal using the built-in form interface.
**Steps to follow**
1. Open the [invoice](/en/general/portal/transactions/sending-invoices) for which you want to create a credit note.
2. Click "Create Credit Note" in the top right corner.
3. Select “Create Manually”.
4. The input form opens for manual editing with the transferred data from the invoice.
The credit note document contains similar sections to an invoice:
* Credit Note Number\*
* Credit Note Due Date\*
* Credit Note Date (default is the current date)
* Currency \*
* Order Number\*
* Reason for the Credit Note
\*mandatory fields
All relevant details about the involved trading partners:
* Buyer (the ordering trading partner)
* Supplier (your company)
* Invoice Address
* Delivery Address
A detailed tabular overview of all order or invoice positions, including:
* Item Number and Description
* Quantity and Unit
* Unit price and Total Price
* Tax Rate
* Line Item Discounts
Overview of all price-related additions and deductions:
* Discounts at the Item Level
* Surcharges at the Document Level
* Special Conditions
* Total Discounts
Details of the agreed payment conditions:
* Payment Deadline
* Early Payment Discount Conditions
* Payment Method
* Bank Details
1. Review Line Items
* All positions from the original [invoice](/en/general/portal/transactions/sending-invoices) are listed. You can:
* Adjust quantities
* Correct prices
* Remove positions
2. Set Credit Note Amount
* Click on the position to be corrected.
* Enter the credited quantity.
* Adjust the price if necessary.
* The system automatically calculates the credit amount.
The credited quantity cannot exceed the originally invoiced quantity.
Like an invoice, credit notes allow for global adjustments:
**Available Options**
* Credit discounts: Correct previously granted discounts.
* Credit fees: Refund previously charged fees.
* Multiple calculation levels available.
**Reviewing and Sending the Document**
1. **Checking Mandatory Fields**
* Credit Note Number
* Credit Note Date
* Reference to the original invoice
* Correct amounts and quantities
2. **Resolve Issues**
* Problematic fields are highlighted in red.
* Error messages provide correction hints.
* Use "Next Issue" for systematic correction.
3. **Send Credit Note**
* After a successful review, send the credit note by clicking "Send".
**Advantage to create a Credit Note manually**\
If you can’t provide credit notes differently this is your option to easily create them.
Upload an existing Credit Note as a PDF file.
**Steps to follow**
1. Open the corresponding Invoice.
2. Click on “Create Credit Note” in the top right corner.
3. Select “Upload Document.”
4. Upload an existing Credit Note.
If you submit your credit note via portal upload **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
Manually uploaded documents are directly enriched with the initial order and invoice information - therefore we need less information.
**Steps to follow**
1. Get your personalized “Procuros inbound” email after your first order. Contact [**help@procuros.com**](mailto:help@procuros.com) in case you did not receive it.
2. Send PDF of your credit notes to your personalized “Procuros inbound” email (no subject or text needed). We recommend saving this email in your system for automatic sending or setup automatic forwarding within your ERP or email client. Learn more about it [**here**](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding).
3. Verify delivery status by checking the portal, where all transaction records are visible (if needed).
If you submit your credit note via “ Procuros inbound” email **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
**Key Rules for Email PDF Forwarding**
1. Only send one credit note per PDF file. Do not send multiple credit notes within one PDF file.
* Our system will only process the first one and disregard all others
* Maximum capacity = 10 PDF files or 30 MB
2. Provide all necessary information on the credit notes.
3. Only credit notes for orders received via Procuros will be processed - others will be rejected.
4. If your credit note wasn’t processed, you will receive an email with the explanation. If this email directs you to the portal, please follow the instructions there.
# Invoices
Source: https://docs.procuros.io/en/general/portal/transactions/sending-invoices
Learn how to create, edit, and send invoices to your trading partners in Procuros WebEDI.
An invoice is a document used to request payment for delivered goods or services. It contains essential details such as items, prices, discounts, payment terms, and tax-related information.
## **Three Ways to Provide Invoices**
As a supplier, you have three options for providing Invoices via in Procuros
Create Invoices directly in the Procuros portal using the built-in form interface.
**Steps to follow**
1. Open Order.
2. Click on "Create Invoice" in the top right corner.
3. Select “Create Manually”.
4. The input form opens for manual editing with the transferred data from the previous document, most probably shipping notice.
The invoice document consists of five main sections
Key information for identifying and processing the invoice:
* Invoice Number
* Invoice Date (default is the current date)
* Order Number (to reference your invoice to the correct order)
* Currency
* Shipping Notice Number (if applicable)
All relevant details about the involved trading partners:
* Buyer (the ordering trading partner)
* Supplier (your company)
* Invoice address
* Delivery address
A detailed tabular overview of all order or invoice positions, including:
* Item number and description
* Quantity and unit
* Unit price and total price
* Tax rate
* Line item discounts
Overview of all price-related additions and deductions:
* Discounts at the item level
* Surcharges at the document level
* Special conditions
* Total discounts
Details of the agreed payment conditions:
* Payment deadline
* Early payment discount conditions
* Payment method
* Bank details
1. Change Values
* Click on the cell you want to edit.
* Enter the new value.
* Note: locked fields (indicated by a lock symbol).
2. Remove Items
* Click "X" next to the row.
* The quantity will be set to 0.
* The item remains visible for documentation purposes.
3. Add New Items
* Click "Add."
* Select "New Item."
* Enter the item details.
Locked fields cannot be edited as they are either automatically calculated or derived from previous documents.
**Using Price Lists**
1. Click "Apply Price List."
2. Select the desired price list.
3. Prices will be automatically populated.
**Global Discounts and Fees**
* Add Discount: Percentage or absolute deduction.
* Add Fee: Additional costs such as shipping.
* Calculation Levels: Grouping multiple discounts/fees.
Fees are always calculated before discounts. You can add multiple discounts and fees.
Offer payment discounts for early payments
**Add Payment Condition**
1. Click "Add Payment Condition."
2. Enter the payment term in days.
3. Set the discount percentage.
You can define multiple payment terms with different discount rates.
**Reviewing and Sending the Document**
Before sending, the system automatically checks the invoice:
1. **Identify Issues**
* Incorrect fields are highlighted in red.
* An exclamation mark indicates mandatory fields.
2. **Fix Issues**
* Click on the marked fields.
* Read the error message.
* Make the necessary corrections.
* Use "Next Issue" for systematic correction.
3. **Send Invoice**
* After resolving all issues, send the invoice by clicking "Send."
**Advantage to create an Invoice manually**\
If you can’t provide invoices differently this is your option to easily create them.
Upload an existing Invoice as a PDF file.
**Steps to follow**
1. Open the corresponding shipping notice.
2. Click on “Create Invoice” in the top right corner.
3. Select “Upload Document.”
4. Upload an existing invoice.
If you submit your invoice via portal upload **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
Manually uploaded documents are directly enriched with the initial order and shipping notice information - therefore we need less information.
**Steps to follow**
1. Get your personalized “Procuros inbound” email after your first order. Contact [**help@procuros.com**](mailto:help@procuros.com) in case you did not receive it.
2. Send PDF of your invoices to your personalized “Procuros inbound” email (no subject or text needed). We recommend saving this email in your system for automatic sending or setup automatic forwarding within your ERP or email client. Learn more about it [**here**](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding).
3. Verify delivery status by checking the portal, where all transaction records are visible (if needed).
If you submit your invoice via “ Procuros inbound” email **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
**Key Rules for Email PDF Forwarding**
1. Only send one invoice per PDF file. Do not send multiple invoices within one PDF file.
* Our system will only process the first one and disregard all others
* Maximum capacity = 10 PDF files or 30 MB
2. Provide all necessary information on the invoice.
3. Only invoices for orders received via Procuros will be processed - others will be rejected.
4. If your invoice wasn’t processed, you will receive an email with the explanation. If this email directs you to the portal, please follow the instructions there.
# Order Responses
Source: https://docs.procuros.io/en/general/portal/transactions/sending-order-responses
Learn how to confirm, reject, or partially confirm incoming orders from your trading partners in Procuros.
When you receive an order via Procuros, you can respond in three ways:
* **Confirm the order** if everything looks good
* **Reject the order** entirely if you cannot fulfill it
* **Partially confirm the order** if some items, quantities or dates needs to be adjusted
Each of these actions creates an **Order Response** tailored to the specific action you've taken.
## Three Ways to Send Order Responses
As a supplier, you have three options for providing Order Responses via in Procuros
Create Order Responses directly in the Procuros portal using the built-in form interface.
**Accessing Order Responses**
There are two ways to create a new order response:
1. Open the dashboard.
2. Navigate to the "Inbox" section.
3. Click on "Order Responses Pending."
4. The overview displays the open orders, where a Order Response is outstanding.
1. Open the "Transactions" section.
2. Use the "Document Type" filter.
3. Select "Orders".
4. If you click on the individual orders, you can create a response in the top right-hand corner for those where a response is pending.
**Confirming the Entire Order**
If you can fulfill everything as requested:
1. Click **"Confirm Order"** in the top-right corner of the order page.
2. Select **"Confirm Entire Order"**.
3. Review the order summary to ensure everything is accurate.
4. Click **"Send Order Confirmation"** to complete the process.
The confirmation will be sent to your trading partner, and the order will be marked as confirmed in the system.
**Rejecting the Order**
If you cannot fulfill the order at all:
1. Click **"Reject"** in the top-right corner of the order page.
2. Select a reason from the list. If your reason isn't listed, choose **"Other"** and provide a brief explanation.
3. Confirm by clicking **"Reject"** again to send the rejection to your trading partner.
Once rejected, the order will be marked accordingly and no further action will be required.
**Partially Confirming an Order**
If you need to make changes to an Order, like changing items quantities or delivery date:
1. Click **"Confirm Order"** in the top-right corner of the order page.
2. Select **"Partially Confirm Order"**.
3. Apply the changes needed, check "Editing a Partial Order Confirmation" section for further details.
4. Click **"Send"**.
5. Review the order summary to ensure everything is accurate.
6. Click **"Send Order Confirmation"** to complete the process.
The partial confirmation will be sent to your trading partner, and the order will be marked as partially confirmed in the system.
**Fill in Header Data**
The upper section of the document contains essential order details:
* **Mandatory Fields** are marked with an asterisk (\*).
* **Locked Fields** are indicated by a lock icon and cannot be edited.
- Order Confirmation ID\*: Your unique number for this response.
- Order Confirmation Date\*: Default is the current date.
- Order Number\*: Taken from the original order.
- Order Date\*: Date of the original order.
- Requested Delivery Date: Taken from the order.
- Confirmed Delivery Date\*: Your confirmed delivery date.
**Edit Line Items**
To edit multiple or all line items at once, use the "Bulk Edit" function. In the table format, you can select multiple line items and then overwrite individual fields for all selected items.
The line item overview lists all ordered products:
Enter the actual deliverable quantity for each item in the "Confirmed Quantity" field. You can remove individual items from the order by clicking the "X" on the left of each row. Clicking again restores the item.
Specify the confirmed delivery date for each item.
Check the prices and adjust them if needed.
**Send Document**
Before sending, the system automatically checks all required fields:
1. Click "Send."
2. If any mandatory fields are missing, they will be highlighted.
3. Follow the issue resolution assistant.
4. Once all issues are corrected, you can resend the document.
The issue resolution assistant guides you step by step through all pending issues until they are resolved.
**Advantage to create an Order Response manually**\
If you can't provide order responses differently this is your option to easily create them.
Upload an existing Order Response as a PDF file.
**Steps to follow**
1. Open the corresponding order.
2. Click on "Confirm Order" in the top right corner.
3. Select "Upload Document."
4. Upload an existing order response.
If you submit your order response via portal upload **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
Manually uploaded documents are directly enriched with the initial order information - therefore we need less information.
**Steps to follow**
1. Get your personalized "Procuros inbound" email after your first order. Contact [**help@procuros.com**](mailto:help@procuros.com) in case you did not receive it.
2. Send PDF of your order responses to your personalized "Procuros inbound" email (no subject or text needed). We recommend saving this email in your system for automatic sending or setup automatic forwarding within your ERP or email client. Learn more about it [**here**](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding).
3. Verify delivery status by checking the portal, where all transaction records are visible (if needed).
If you submit your order response via "Procuros inbound" email **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
**Key Rules for Email PDF Forwarding**
1. Only send one order response per PDF file. Do not send multiple order responses within one PDF file.
* Our system will only process the first one and disregard all others
* Maximum capacity = 10 PDF files or 30 MB
2. Provide all necessary information on the order response.
3. Only order responses for orders received via Procuros will be processed - others will be rejected.
4. If your order response wasn't processed, you will receive an email with the explanation. If this email directs you to the portal, please follow the instructions there.
# Shipping Notices
Source: https://docs.procuros.io/en/general/portal/transactions/sending-shipping-notices
Learn how to easily create, edit, and send Shipping Notices to your trading partners via Procuros.
A Shipping Notices is a document that informs the buyer about the shipment of an order. It contains important details such as the shipping date, involved parties tracking number, carrier information, and a lists all of delivered items products.
## Three Ways to Provide Shipping Notices
As a supplier, you have three options for providing Shipping Notices via in Procuros
Create Shipping Notices directly in the Procuros portal using the built-in form interface.
**Steps to follow**
1. Open the corresponding order
2. Click on “Create Shipping Notices” in the top right corner
3. Select “Create Manually"
4. The input form opens for manual editing with the transferred data from the order
* Change values: Click on a cell and enter the new value.
* Remove items: Click “X” next to the row (quantity will be set to 0).
* Add new items: Use “Add” and “New Item.”
* Search: Use the search bar for name, GTIN, quantity, etc.
Locked fields (indicated by a lock symbol) cannot be edited as they are automatically calculated or taken from previous documents.
Before sending, the system automatically checks the document.
**Identify Issues**
1. Problematic fields are highlighted in red.
2. An exclamation mark indicates errors.
**Fix Issues**
1. Click on the marked field.
2. Read the error message.
3. Make the necessary corrections.
**Send Again**
1. Ensure all issues are resolved.
2. Click “Send.”
After successful transmission, you can create follow-up documents such as invoices if needed.
**Advantage to create a Shipping Notice manually**
If you can’t provide shipping notices differently this is your option to easily create them.
Upload an existing Shipping Notice as a PDF file.
**Steps to follow**
1. Open the corresponding order.
2. Click on “Create Shipping Notices” in the top right corner.
3. Select “Upload Document.”
4. Upload an existing shipping notices.
If you submit your shipping notice via portal upload **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
**Advantage to upload PDF Document in the portal**
Manually uploaded documents are directly enriched with the initial order - therefore we need less information.
**Steps to follow**
1. Get your personalized “Procuros inbound” email after your first order. Contact [help@procuros.com](mailto:help@procuros.com) in case you did not receive it.
2. Send PDF of your shipping notice to your personalized “Procuros inbound” email (no subject or text needed). We recommend saving this email in your system for automatic sending or setup automatic forwarding within your ERP or email client. Learn more about it [here](https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding).
3. Verify delivery status by checking the portal, where all transaction records are visible (if needed).
If you submit your shipping notice via “ Procuros inbound” email **for the first time**, processing may take up to 24 hours while the Procuros team configures the scanning system. Please always use a single PDF document format.
**Key Rules for Email PDF Forwarding**
1. Only send one shipping notice per PDF file. Do not send multiple shipping notices within one PDF file.
* Our system will only process the first one and disregard all others
* Maximum capacity = 10 PDF files or 30 MB
2. Provide all necessary information on the shipping notice
3. Only shipping notices for orders received via Procuros will be processed - others will be rejected.
4. If your shipping notice wasn't processed, you will receive an email with the explanation. If this email directs you to the portal, please follow the instructions there.
**What information should your shipping notice include?**
Each Shipping Notices consists of 3 main sections:
This section provides all mandatory information to identify the corresponding order and parties and when to expect the shipment.
* Shipping Notices number
* Shipping Notices date (default is the current date)
* Order number
* Expected Delivery Date
* Actual Shipment Date (default is the requested delivery date)
**Party Information**
This section provides all mandatory information to identify the sending and receiving parties.
* Buyer
* Supplier
* Delivery address
This section is not mandatory. But if you decide to fill in information, you should do it fully, otherwise the system will block your shipping notice. Therefore, we advise you to fill it in only if you have information for all the bullet points mentioned below.
**Add a Shipping Unit**
* Index
* NVE/SSCC (18-digit identification number)
* Unit Type (pallet, container, carton, etc.)
* Carrier
* Tracking Number
* Tracking Link
This section is mandatory. It provides all necessary information for each line item.
* Order-line Number \*
* GTIN / EAN \*\*
* Article Name (same as on the order) \*
* Supplier Article Number \*
* Shipped Quantity \*
\* *mandatory fields that have to be provided, otherwise the system will block your shipping notice.*
*\*\* ****GTINs/EANs are mandatory to provide****. If you send a PDF of your shipping notice ****without GTINs/EANs****, our system will intelligently try to match the products to your orders using available data (for example: ****supplier article number + unit of measurement****). However, this automatic matching may not always succeed - if the system cannot confidently match items, you must provide the GTINs/EANs yourself.*
* Order-line Number \*
* GTIN / EAN \*\*
* Article Name (same as on the order) \*
* Supplier Article Number \*
* Shipped Quantity \*
\* *mandatory fields that have to be provided, otherwise the system will block your shipping notice.*
*\*\* ****GTINs/EANs are mandatory to provide****. If you send a PDF of your shipping notice ****without GTINs/EANs****, our system will intelligently try to match the products to your orders using available data (for example: ****supplier article number + size + color****). However, this automatic matching may not always succeed - if the system cannot confidently match items, you must provide the GTINs/EANs yourself.*
* Order-line Number \*
* GTIN / EAN \*\*
* Article Name (same as on the order) \*
* Supplier Article Number \*
* Shipped Quantity \*
* Batch Information (if has expiration date)
* Batch-ID
* Expiration Date
* Quantity
* Net Weight
\* *mandatory fields that have to be provided, otherwise the system will block your shipping notice.*
*\*\* ****GTINs/EANs are mandatory to provide****. If you send a PDF of your shipping notice ****without GTINs/EANs****, our system will intelligently try to match the products to your orders using available data (for example: ****supplier article number + unit****). However, this automatic matching may not always succeed - if the system cannot confidently match items, you must provide the GTINs/EANs yourself.*
# Setting Up Email Forwarding in Microsoft Outlook
Source: https://docs.procuros.io/en/general/portal/transactions/setting-up-email-forwarding
Learn how to automatically forward emails in Microsoft Outlook to Procuros to seamlessly process supplier documents and save time.
Also see: How to setup auto-forwarding for [Gmail](https://support.google.com/mail/answer/10957?hl=en)
Automatically forwarding emails to Procuros enables processing of supplier documents such as orders, invoices, or shipping notices without manual entry. Procuros automatically extracts data from the forwarded documents, saving suppliers time and reducing errors.
This guide shows you how to set up automatic email forwarding in Microsoft Outlook for Windows.
If a fulfiller regularly sends shipping notices to your purchasing department, you can use automatic forwarding to ensure these documents are sent directly to Procuros and thus recorded completely and on time.
## Setting Up Email Forwarding in Outlook for Windows
Select the "Home" tab in the main menu and then click on the "Rules" button in the "Move" section.
Select "Manage Rules & Alerts" from the dropdown menu.
In the "Rules and Alerts" dialog, select the "Email Rules" tab and click on the "New Rule" button.
The Rules Wizard will open. Under "Start from a blank rule," select "Apply rule on messages I receive" and click "Next."
Select the conditions by which emails should be filtered. If all incoming emails from a specific sender should be forwarded, check the appropriate box and specify the sender.
If you don't select any condition and click "Next," all incoming emails will be forwarded. Confirm this in the confirmation dialog.
Select "forward it to people or public group" as the action and click on the blue highlighted text to specify the target address.
Enter the Procuros email address or select it from your address book. Click "OK" to confirm your selection.
If desired, you can set exceptions for the rule. For example, if certain emails should not be forwarded. Then click "Next."
Enter a name for the rule (e.g., "Forward shipping notices to Procuros") and ensure that the "Turn on this rule" option is selected. Then click "Finish."
## Difference Between Forwarding and Redirecting
Microsoft Outlook distinguishes between email forwarding and email redirection:
* **Forwarding**: The recipient of the forwarded message can see who originally sent the email. When you reply to a forwarded email, Outlook automatically selects the address that forwarded the email, not the original sender's address.
* **Redirecting**: The recipient of a redirected message does not see that the email was redirected. It appears as if the email was sent directly from the original sender. Replies to redirected emails go directly to the original sender, not to the account that redirected the email.
To ensure that Procuros receives all relevant information, we recommend using forwarding instead of redirecting, as this preserves the complete header information of the email.
## Verifying the Forwarding Setup
After setting up the rule, you should test the forwarding:
1. Send a test email to the account for which you have set up forwarding
2. Check if the email is correctly forwarded to the Procuros address
3. Verify in the Procuros portal that the document has been processed correctly
Make sure that the forwarding rule you've set up doesn't conflict with other rules. If emails are not being forwarded, check the order of your rules in the "Rules and Alerts" dialog.
## Benefits of Automatic Forwarding to Procuros
Automatic forwarding offers the following benefits:
* Time savings by eliminating manual data entry
* Reduction of errors in document processing
* Increased transparency in the supply chain
* Ensuring all important documents are captured in the Procuros system
* Improved response time to changes or issues
# Transaction Overview
Source: https://docs.procuros.io/en/general/portal/transactions/transactions-intro
Learn how to efficiently manage and monitor your business transactions in Procuros. This guide explains the different views and features of the transaction overview.
The transaction overview in Procuros gives you full control and monitoring of all business documents such as orders, invoices, and shipping notices. You can track the status of each transaction, view details, and resolve issues if needed. Each transaction goes through various status types that indicate its current processing stage.
## Accessing the Transaction Overview
Click on "Transactions" in the sidebar to open the transaction overview.
Choose between "All Transactions," "Blocked Transactions," or "Expired Transactions."
## All Transactions
In the "All Transactions" view, you have access to all historical and current transactions.
### Filtering transactions
The overview offers extensive filtering options:
* **Message Type**: Filter by Order, Order Confirmation, Shipping Notices, Invoice, or Price Catalog. For each selected type you can also set a direction (Both, Incoming, or Outgoing) to narrow it to documents you received or sent.
* **Trading Partner**: Narrow down by specific business partners
* **Status**: View by Delivered, In Progress, or Discarded
* **Transaction Type**: Distinguish between Live and Test transactions
* **Date**: Time-based filtering of transactions
* **Document Number**: Search for specific documents
Searching by document number allows you to quickly find specific transactions without scrolling through the entire list.
### Saving a default view
If you regularly apply the same filters, you can save them as your personal default. Open the **Filters** menu and select **Save as Default**. Those filters are then applied automatically every time you open the Transactions list, on any device you sign in from. To update your default, set the filters you want and select **Save as Default** again. To clear it, remove all filters first, then save.
## Transaction Detail View
The detail view provides all key information about a specific transaction. It is divided into different sections:
### Main Sections
1. **Transaction Information**
* Document type
* [Transaction Status](#transaction-status)
* Key transaction data
2. **Party Identifications**
* Details about the sender and recipient
* System identifiers
* Addresses and contact information
3. **Items**
* Product details
* Total amounts
* Taxes
* Discounts and surcharges
### Transaction Sidebar
The sidebar provides additional context information and can be hidden if needed:
1. **Trading Partner Information**
* Name and details of the connected trading partner
* Direct link to the partner profile
2. **Linked Transactions**
* Overview of all related documents
* From order to invoice
* Current transaction highlighted in green
3. **Document Summary**
* Key figures at a glance
* Total amounts and status
Depending on the type of transaction, additional sections are displayed:
* Shipping Notices: "Transport Units" section
* Invoices: "Global Discounts and Fees" section
For information on handling blocked or expired transactions, please refer to [this guide](/en/general/troubleshooting/blocked-transactions).
## Transaction Status
Each transaction in Procuros can be in one of the following statuses:
### In Progress
A transaction is in this status when:
* It is being processed by Procuros (this usually takes only a few seconds)
* The recipient has not yet retrieved the message (typical for API usage with scheduled retrieval intervals)
### Delivered
A transaction receives this status once:
* The message has been successfully delivered to the recipient
### Blocked
A transaction is blocked if, for example:
* Master data errors prevent processing
* Required parameters are missing
* Incorrect calculations exist
* There is a temporary connection issue
### Discarded
A transaction receives this status when:
* It has been manually discarded by the user in the portal (e.g. after manual processing)
* No further processing in Procuros is possible
For discarded transactions, the reason specified by the user for discarding will be displayed.
## Can't find your transaction in Procuros?
If a transaction does not appear in the Portal search, first check the documentation for the connector you use to exchange messages. Connector pages include connection requirements, sync behavior, and troubleshooting steps for missing transactions.
* Connector documentation and troubleshooting: [AS2](/en/connectors/as2/as2), [SFTP](/en/connectors/sftp/sftp), [X.400](/en/connectors/x400/x400), [Bridge](/en/connectors/bridge/overview), [weclapp](/en/connectors/weclapp/getting-started/overview), [Xentral](/en/connectors/xentral/getting-started/overview), [Microsoft Business Central](/en/connectors/ms-business-central/getting-started/overview)
# Uploading PDF Documents
Source: https://docs.procuros.io/en/general/portal/transactions/upload-existing
Guide for automated uploading and processing of PDF documents such as delivery notes and invoices in the Procuros WebEDI portal.
The PDF upload function enables the automated reading of existing documents. The system extracts relevant data and automatically populates the corresponding fields, significantly reducing manual data entry efforts.
## Upload Process
The upload process consists of the following steps:
Navigate to the desired document type (e.g., dispatch notification or invoice) and click "Create."
In the dropdown menu, choose between:
* "Create Manually" for an empty input form
* "Upload Document" for the PDF upload
In the upload section, you have two options:
* Drag & Drop the file into the designated area
* Click "Upload File" to select a file from your computer
## Processing Additional Positions
The system automatically detects positions that are not part of the original order. These are displayed in a separate dialog, "Additional Items Detected."
The following options are available:
* "Keep All Items": Retains all additional positions
* "Discard All Items": Removes all additional positions
* Individual Selection: Use the dropdown menu in the "Action" column to selectively keep or discard specific positions
## Reviewing Extraction Results
After document extraction, the system displays an overview with color-coded markings:
* Green: Successfully matched positions (corresponding between order and document)
* Blue: Additional positions (e.g., free samples, unordered items)
* Yellow: Missing positions (ordered items not found in the document)
## Processing Consolidated Shipments
For consolidated shipments (multiple orders in one document), the document must be uploaded separately for each included order.
Please follow these steps:
1. Re-upload the document for each included order
2. Select "Discard all items" for positions from other orders
3. Keep only the positions belonging to the current order
## Data Verification and Finalization
After applying the extraction:
1. Carefully review all pre-filled data
2. Pay special attention to:
* Shipped quantities
* Delivery date (if not specified on documents)
3. Complete missing mandatory fields (marked with \*)
4. Confirm by clicking "Send" after full verification
Use the automatic extraction as an aid, but always verify the data for accuracy before sending it to your trading partners.
## Next Steps
After a successful upload, you can:
* Send the document to your trading partner
* Generate follow-up documents such as invoices if needed
* Track the document status in the overview
# Blocked Transactions
Source: https://docs.procuros.io/en/general/troubleshooting/blocked-transactions
Learn how to identify and effectively resolve blocked transactions in the Procuros network. This guide explains the most common causes and outlines the necessary steps for resolution.
A blocked transaction occurs when an error or issue prevents a document from being successfully transmitted to the receiving trading partner. Common causes include missing information, invalid data, or misconfigurations in one of the involved systems. These situations require targeted solutions before the transaction can proceed. The Procuros system clearly indicates the necessary actions and who is responsible for resolving them.
## Accessing Blocked Transactions
Click on "Transactions" in the left sidebar.
Choose the "Blocked Transactions" tab in the top navigation bar.
If there are active blocked transactions, a red banner will appear on the dashboard. Click the "View" button to go directly to the overview.
## Error notifications
If a transaction is blocked, all responsible users will receive an error notification via email. You can add additional users in the [Portal settings](https://portal.procuros.io/settings/team-members) anytime.
### **Notification batching**
By default, transactions that are blocked within a window of 15 minutes are batched into a single notification. This is meant to keep a notification overflow in check and not crowd your email inbox. If you require any changes to this batching (e.g., because your internal workflows depend on individual notifications), please reach out to our support team ([help@procuros.io](mailto:help@procuros.io)).
## The Issue Resolver
The issue resolver is the person or organization responsible for fixing a specific problem. There are three types of issue resolvers:
* **You**: Issues requiring your direct action, such as data corrections or system errors on your side.
* **Your Trading Partner**: Issues that your partner must resolve, such as missing information or system problems on their side.
* **Procuros**: Technical issues that require system updates or manual intervention from our support team.
## Expired Transactions
Transactions that remain blocked for more than 60 days are automatically moved to the "Expired Transactions" tab. This ensures a clear view of current issues and prevents the main overview from becoming cluttered. Expired transactions remain fully editable and are handled in the same way as blocked transactions.
Click on "Transactions" in the sidebar.
Choose "Expired Transactions."
## Common Causes of Blockages
### Data-Related Issues
These issues pertain to the content of the transaction and include:
* **Missing or Incomplete Information**:
* Missing order numbers
* Missing product codes
* Missing quantities or delivery dates
* Incomplete mandatory fields
* **Invalid Data**:
* Data that does not meet format requirements
* Violation of specific field rules
* Invoice numbers outside the allowed pattern
* Delivery quantities exceeding ordered amounts
Click on fields with exclamation marks to view detailed error descriptions. Most of these issues can be resolved directly in the Procuros portal using the "Fix Issues" button in the red banner.
### System-Related Issues
These issues arise due to misconfigurations:
* Incorrect or missing master data
* Incorrect partner identifications
* Faulty system settings
For system-related issues, please follow the displayed instructions carefully. Some issues can be resolved directly in Procuros, while others require adjustments in your system.
### Procuros-Related Issues
In some cases, technical issues may arise that require support from the Procuros team. No action is needed on your part—our team will resolve the issue as quickly as possible.
## Problem Resolution
Identify the issue resolver (You, Trading Partner, or Procuros).
Check whether the issue needs to be resolved directly in Procuros or in your system.
For issues within Procuros:
* Click "Fix Issues."
* Make the necessary changes.
* Resend the document.
For system-related issues:
* Apply the required changes in your system.
* Click "Retrigger Document."
Track the status of the transaction after making corrections.
If you have already manually imported a transaction into your system, you should remove it from Procuros by selecting "Discard Transaction" and providing a reason. This prevents it from continuing to appear as blocked.
# Platform Concepts
Source: https://docs.procuros.io/en/general/welcome/concepts
Fundamental concepts and functionality of the Procuros B2B platform for digital document exchange between trading partners
## Trading Partners
Trading partners are companies that exchange business documents through the Procuros network. Each trading partner can take on different roles:
### Buyer
Buyers are companies that:
* Send orders to suppliers
* Receive order confirmations and delivery notifications
* Receive and process invoices from suppliers
### Supplier
Suppliers are companies that:
* Receive orders from buyers
* Send order confirmations and delivery notifications
* Issue invoices for delivered goods
A company can act as both a buyer and a supplier simultaneously. The role is defined per business relationship.
## Integration
Integration with Procuros enables the automated exchange of business documents. Two main methods are available:
### Document Transmission to Procuros
The transmission of documents to Procuros is carried out via:
1. **API Integration**
Direct system access through our REST API with authenticated endpoints
2. **EDI Integration**
Standardized document exchange using EDI protocols such as AS2 or SFTP
3. **Web Portal**
Manual upload and management of documents through the user interface
### Document Reception from Procuros
For receiving documents, the following options are available:
1. **EDI Reception**
Automatic receipt via established EDI connections
2. **Email Notification**
Delivery of new documents via email in the desired format
## Connections
Connections in Procuros enable document exchange between trading partners. A connection is always set up for specific document types.
### Establishing Connections
Send a request to a trading partner specifying the desired document types
The trading partner reviews the request and the technical requirements
Once confirmed, the connection is activated for the agreed document types
## Error Management
The error management system in Procuros captures and logs failed transactions:
### Error Types
* Validation errors: Documents do not comply with the agreed format
* Transmission errors: Issues with technical delivery
* Business errors: Content discrepancies in documents
In case of critical errors, email notifications are automatically sent to the configured contacts.
### Error Resolution
View detailed error information in the Procuros portal
Fix the root cause (e.g., adjust data format, check connection)
Resend the corrected document
You can find more information about troubleshooting [here](/en/general/troubleshooting/blocked-transactions).
# Welcome to Procuros
Source: https://docs.procuros.io/en/general/welcome/introduction
Getting Started and Overview of the Procuros Platform for Digital Commerce
Procuros is a B2B platform that enables digital exchange between trading partners. With Procuros, you can automate the processing and sharing of business documents such as orders, invoices, and master data with your trading partners.
Procuros is designed to simplify and automate data exchange between trading partners. The platform helps you reduce manual processes and enable efficient digital collaboration.
## Core Features of the Platform
### Digital Document Exchange
Procuros facilitates the seamless exchange of various business documents between you and your trading partners. The most common document types include:
* [**Price Catalogs**](/en/general/portal/pricat) **and Master Data**: Manage and share current price lists and master data with your trading partners
* [**Orders**](/en/general/portal/transactions/receiving-orders): Receive and process incoming orders directly on the platform
* [**Order Responses**](/en/general/portal/transactions/sending-order-responses): Send automated responses to received orders
* [**Invoices**](/en/general/portal/transactions/sending-invoices): Create and send invoices digitally to your trading partners
* [**Shipping Notices:**](/en/general/portal/transactions/sending-shipping-notices) Send automated shipping notifications to inform retail partners.
This list is not exhaustive — Procuros supports a wide range of additional document types and can be flexibly adapted to your specific requirements.
### Automated Processes
The platform offers various automation options to optimize your daily workflows:
* Automatic validation of incoming documents
* Predefined workflows for recurring processes
* Integration with existing ERP and inventory management systems
* Automatic error detection and correction
To use Procuros optimally, you need:
* A modern web browser (Chrome, Firefox, Safari, or Edge)
* A stable internet connection
## Help & Support
Procuros offers various ways to get assistance:
### Help Center
In the Help Center, you will find:
* Comprehensive documentation on all features
* Step-by-step guides for essential processes
* Answers to frequently asked questions
### AI-Powered Search
The integrated search function in the Help Center allows you to:
* Ask targeted questions in natural language
* Quickly find answers from the documentation
* Discover relevant articles and guides
### Personal Support
If you need further assistance:
* Contact our Customer Support directly through the platform
* Receive personalized advice tailored to your specific needs
* Report technical issues or suggest improvements
k
# Procuros Supplier Onboarding
Source: https://docs.procuros.io/en/general/welcome/procuros-supplier-onboarding
> Learn how you are onboarded to Procuros as a supplier, how to upload your product catalogue, and what to expect from your first order onward.
Your customer has chosen Procuros to exchange order-related documents with you digitally. As a supplier, you use the Procuros Portal to receive orders and send back the documents your customer needs — no EDI project or IT setup required to get started.
This page explains the typical WebEDI onboarding journey. Your exact setup may vary depending on the customer you trade with and the document types they require.
WebEDI means you process documents manually in the Procuros Portal, or by emailing PDF documents to Procuros. If you would prefer a direct technical connection later on, speak to our team ([help@procuros.io](mailto:help@procuros.io)) about upgrading to a direct connection.
## Who this guide is for
Use this guide if one of your customers invited you to Procuros and you want to understand what happens during onboarding, what Procuros needs from you, and what to expect once orders start flowing.
## Onboarding at a glance
Your customer announces the switch to Procuros. You then receive a Welcome Email from Procuros and get access to the Procuros Portal.
If your customer requires it, you upload your product catalogue through the Portal so they have your up-to-date item data (GTIN, unit of measurement, price, and so on) to order against.
Orders start flowing exclusively through Procuros. You receive your first order, and then your individual Procuros inbound email address for sending documents back.
## Documents you may exchange
The exact set depends on your customer's process. The most common WebEDI document types are:
| Document | Direction | What it is used for | Channel | Format |
| - | - | - | - | - |
| Order | Customer → supplier | Your customer sends a purchase order to you through Procuros. | Email | CSV, PDF |
| Order Response | Supplier → customer | You confirm whether you can fulfil the order. | Email, Portal | PDF |
| Delivery Note | Supplier → customer | You inform your customer which goods are being shipped. | Email, Portal | PDF |
| Invoice | Supplier → customer | You submit invoice information for delivered goods. | Email, Portal | PDF |
| Product Catalogue (PRICAT) | Supplier → customer | You provide the product data your customer orders against. | Portal | XSL |
***
## Phase A — Invitation
### 1. Your customer announces Procuros
About two weeks before go-live, your customer lets you know they are switching to Procuros for order processing. This is advance notice so the later emails from Procuros are expected — you do not need to do anything yet.
### 2. You receive your Welcome Email
Procuros sends you a **Welcome Email** with a link to activate your account in the [Procuros Portal](https://portal.procuros.io). Activating your account is free and takes a few minutes.
You can invite colleagues to your account at any time under [Team Members](https://portal.procuros.io/settings/team-members). Make sure the right operational contacts have access before go-live.
***
## Phase B — Product catalogue (PRICAT)
### 3. Upload your product catalogue (if requested)
If your customer requires a PRICAT, Procuros sends a **PRICAT request** shortly after your Welcome Email. A PRICAT is your product catalogue — the articles, prices, and identifiers your customer orders against. Uploading it lets Procuros match incoming orders to the right products.
You upload it directly in the Portal. See the [PRICAT documentation](https://docs.procuros.io/en/general/portal/pricat) for the step-by-step upload guide.
**Reminders.** If your catalogue has not been uploaded, you will receive an automatic reminder after 7 days, and a second reminder 7 days after that. Uploading early keeps your go-live on schedule.
***
## Phase C — Go-live & your first order
### Go-live
From go-live onward, **all orders from your customer flow exclusively through Procuros.** Your customer switches off any parallel order channels, so Procuros becomes the single place you receive orders.
### 4. You receive your first order
You receive an **email notification** for each new order. The order is attached in two formats — a **CSV** file and a **PDF** file. The notification also lists which documents your customer expects back from you, such as an order confirmation or a delivery note.
You can create those follow-up documents directly from the order in the Portal, which keeps them linked to the correct order.
### 5. Where to send your documents back
Procuros provides you with a dedicated **inbound email address** for returning your documents. From your second order onward, this address is included directly in the order notification.
→ see as well 🔗 [Order Response](https://docs.procuros.io/en/general/portal/transactions/sending-order-responses#three-ways-to-send-order-responses) and 🔗 [Shipping Notice](https://docs.procuros.io/en/general/portal/transactions/sending-shipping-notices#three-ways-to-provide-shipping-notices)
Send your return documents **only** to the Procuros inbound address. Sending the same document through another channel as well can cause double bookings and extra work for your customer.
If you work with a **factoring provider**, this is handled separately — contact us before changing your invoice routing.
***
## Upgrading to a direct connection
WebEDI is the fastest way to start exchanging documents digitally, with no IT setup. Once you are processing orders regularly, you can upgrade to a [**seamless (direct)** **connection**](/en/general/welcome/upgrading-to-a-direct-connection) that integrates with your own system, removing the manual portal steps.
You become eligible to request a direct connection once:
* at least **1 order** has been transmitted to you via WebEDI, and
* at least **2 return-channel documents** have been submitted via WebEDI.
If a direct connection is right for you, Procuros scopes the document types and transport with you, sets up the integration, tests each document type, and then activates the direct flow. Reach out to your Procuros contact to start that conversation.
***
## Before go-live checklist
Before you start using Procuros operationally, confirm that:
* you can log in to the Procuros Portal
* the correct users have access
* your company details are correct
* your team knows which customer invited you
* your product catalogue has been uploaded, if your customer requires one
* you can receive and open the first order
* follow-up documents can be created or uploaded
* order notifications reach the right people
## Questions or need help?
Reach us any time at [help@procuros.io](mailto:help@procuros.io).
# Basics
Source: https://docs.procuros.io/en/api/v2/api-concepts
## API Versioning
We are constantly improving and expanding our API. In order to give you the choice of when (or if) you want to benefit from these changes, we are versioning our API. Our API follows standard [semantic versioning](https://semver.org/), which means we will introduce a new major version number in case new, backwards-incompatible changes are introduced to the Procuros API.
The API version is included in the path of every endpoint. Example: `https://api.procuros.io/v2/transactions` (`v2` shows this endpoint uses version 2)
Keep in mind, that purely additive changes are not considered backwards-incompatible, which means your system needs to
be able to handle new properties added to the JSON data returned by our API.
Use the version selector in the top lefthand corner of this page to adjust the API documentation to an older version.
## Date and Time
For datetime attributes, we are using the ISO8601 format. However, we recommend sending datetime attributes using the `Europe/Berlin` timezone. Furthermore, **all** datetime attributes returned by our API will be in `Europe/Berlin` timezone, regardless of what timezone was used when storing the record.
## Testing
You can use our **Staging environment** to test your interaction with the Procuros API, which protects you from accidentally sending transactions to your Trade Partners.
Our Staging and Production environments can easily be distinguished by the domain.
* Staging: `https://api.procuros-staging.io/v2`
* Production: `https://api.procuros.io/v2`
# Changelog
Source: https://docs.procuros.io/en/api/v2/changelog
Recent changes to the Procuros API v2
## Confirmed Delivery Date Is Optional on Order Responses
`POST /v2/transactions` no longer rejects an order response of type `CHANGE` without a `confirmedDeliveryDate`. Before, a `CHANGE` response needed the date in the header or on every item. You can now send an order response with only a `confirmedShipmentDate`, or with no confirmed date at all.
`confirmedDeliveryDate` is still prohibited on `REJECT` responses, and a supplied date must still be a valid date. Whether a confirmed delivery date is required depends on your trade partner.
## Item Identifiers Without a GS1 or BUYER Domain
`POST /v2/transactions` no longer rejects a line item, or a sales report location, because none of its identifiers has the domain `GS1` or `BUYER`. An item identified only by a `SUPPLIER` identifier is now accepted on every document type. Which identifiers are required depends on your trade partner.
On invoices, credit notes, shipping notices and sales reports, each item, and each sales report location, still needs at least one identifier. On orders, order responses, dispatch instructions, dispatch instruction responses and receival notices, `identifiers` may now be empty.
## Free Quantity on Order Line Items
New field `freeQuantity` added to order line items (`OrderItem`), matching the field already available on invoice and credit note line items. It represents quantity provided free of charge in addition to (not part of) `quantity` — for example, a line with `quantity` 10 and `freeQuantity` 2 means 12 units are delivered in total, 2 of which are free of charge.
## Transport Label (SSCC Labels)
New read-only field `transportLabel` on transport units for Shipping Notice and Dispatch Instruction Response, returned by `GET /v2/transactions`. It contains `zplUrl` and `pdfUrl` — links to the generated SSCC transport label in ZPL and PDF format. The field is populated by Procuros and is not accepted on input.
## Automatic Cleanup of Outdated Document Versions
When a new version of a document is detected, any older version that is still waiting to be collected is now automatically removed from the pending queue. This means `GET /v2/transactions` will only ever return the latest version of a document — you no longer need to check `isLatestVersion` when processing pending transactions, though it remains available for completeness.
See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Document Versioning
New fields on `Transaction` and `ReceivedTransaction` schemas: `replacesProcurosTransactionId`, `replacedByProcurosTransactionId`, and `isLatestVersion` — allowing you to detect superseded documents and trace version chains.
New guide: [Document Versioning](/en/api/v2/features-document-versioning) — explains how Procuros links old and new versions of the same document. All receiving guides have been updated with versioning information.
## Order Identifier on Shipping Notice Line Items
New field `orderIdentifier` added to shipping notice line items, allowing you to trace each line back to its originating order.
## Technical Sender Party
New party `technicalSender` added to all document types. This identifies the system or party that technically transmitted the document, which may differ from the commercial sender.
## Relaxed Ship-To Identifier Requirements
Identifier fields on the `shipTo` party are no longer required, giving more flexibility when the shipping destination does not carry a formal identifier.
## Receival Notice
Added receival notice documentation. See [Sending Receival Notices](/en/api/v2/sending-receival-notices).
## Pricing Unit Fields on Orders
New fields `pricingUnitQuantity` and `pricingUnitOfMeasure` added to order line items, supporting scenarios where the pricing unit differs from the ordering unit.
## Order Response Documentation
Added order response pages for both [Sending](/en/api/v2/sending-order-responses) and [Receiving](/en/api/v2/receiving-order-responses).
# Authentication
Source: https://docs.procuros.io/en/api/v2/concept-authentication
The Procuros API uses API tokens to authenticate requests. Please contact `[email protected]` to request an API token.
In order to perform an authenticated request, use the `Authorization` header to provide your API token as a "bearer token" like this: `Authorization: Bearer `.
All requests to all endpoints of our API have to be made using the above authentication method. Unauthenticated calls will fail with a `401` status code.
## Testing your Connection
Below are examples of how to ping the API to ensure your credentials are correct.
If you get a successful response from the enpoint, your authorization is confirmed. If you receive a `401 Unauthorized` error then your API key is not correct for this environment.
```bash bash theme={null}
curl --request GET \
--url 'https://api.procuros.io/v2/ping' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '
```
```php php theme={null}
$client = new \GuzzleHttp\Client();
$client->request('POST', 'https://api.procuros.io/v2/ping', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '
]
]);
$response->getStatusCode(); // => 200
```
## SSL Encryption
Requests to the Procuros API can only be made over HTTPS. Unsecured requests using HTTP will fail.
# Error Handling
Source: https://docs.procuros.io/en/api/v2/concept-error-handling
Standard HTTP response status codes are used to indicate the success or failure of a request made to the Procuros API. Status codes in the `2XX` range indicate success, codes in the `4XX` and `5XX` range indicate failure.
HTTP status codes that can be returned by the Procuros API:
| HTTP Status Code | Meaning |
| - | - |
| **400** - Bad Request | There was an issue with the request sent, such as a duplicate payload was sent. |
| **401** - Unauthorized | The API token is missing or invalid. |
| **403** - Forbidden | The API token doesn't have permission to perform this action. |
| **404** - Not Found | The requested entity (e.g. Transaction) could not be found. |
| **422** - Validation Failed | The request data is invalid. Responses contain `errors` that show what field failed validation and why. |
| **429** - Too Many Requests | You are calling the API too much. Check if you can use our bulk endpoints, otherwise contact support to get your rate limit increased. (won't happen to >99% of customers) |
| **500**, **502**, **503**, **504** - Server Error | An error occurred on Procuros side (rare cases) |
## Error Responses
To help you troubleshoot your interactions with the Procuros API, we've included further information within the responses returned from failed requests to the API.
| Property | Type | Description |
| - | - | - |
| `message` | string | Short error descriptions |
| `errors` | object | (Only on 422 "Validation Failed" Errors) Map of fields that failed validation including the corresponding validation error |
### Message
`4xx` range responses will always include the `message` property. For example in the case of a `400`, the `message` property will give you the reason why in English.
```json json theme={null}
{
"message": "Payload already received"
}
```
### Errors
For "Validation Failed" Client Errors (HTTP status code `422`), responses include an additional property `errors`, which list all request fields that failed validation and why.
Example:
```json json theme={null}
{
"message": "Invalid data provided.",
"errors": {
"type": [
"The selected type is invalid."
]
}
}
```
### Handling an Error
```php php theme={null}
$client = new \GuzzleHttp\Client();
$response = $client->request(...);
$statusCode = $response->getStatusCode();
if ($statusCode < 200 || $statusCode > 299) {
// handle error
// you likely want to check for the exact error codes
}
```
### Example
```php php theme={null}
$headers = [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
];
$transaction = [...]; // A transaction payload
$client = new \GuzzleHttp\Client();
$client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
'json' => $transaction,
]);
$statusCode = $response->getStatusCode();
if ($statusCode < 200 || $statusCode > 299) {
if ($statusCode === 400) {
\Sentry\captureMessage('BadPayloadSent', $transaction);
}
if ($statusCode === 422) {
\Sentry\captureMessage('ValidationError', $transaction);
}
if ($statusCode === 500) {
markDocumentForLaterRetry($transaction);
}
\Sentry\captureMessage('UnknownApiError', $transaction);
}
markDocumentAsProcessed($statusCode, $transaction);
```
### Error Handling Best Practises
The most common errors are related to missing or misconfigured data. Here is an example on how to handle these with the [Report Outgoing Error Request](/en/api/v2/outgoing-transactions/report-outgoing-error) endpoint.
```php php theme={null}
$client = new \GuzzleHttp\Client(); $client->request('POST', 'https://api.procuros.io/v2/errors', [
'headers' => $headers, 'json' => [ 'errorReason' => 'Data XYZ could not be found.', 'errorType' => 'INTERNAL',
'errorContext' => [ 'meta' => 'value' ], 'transactionIdentifier' => 'bestellung-20231203-001', 'transactionType' =>
'ORDER', ], ]);
```
#### Best Practise: Missing GTIN
* Set `errorType` to: `DATA`.
* Set the `errorReason` to: `The GTIN/EAN :gtin couldn't be found` and set up the gtin variable accordingly
# Pagination
Source: https://docs.procuros.io/en/api/v2/concept-pagination
For some of our resources (eg. transactions), a "list" endpoint exists to fetch resources in bulk.
These endpoints use a "cursor-based pagination", which means you can use the `per_page` and `cursor` query parameters to step through large collections page by page.
### Requests
Requests to paginated "list" endpoints accept the following query parameters:
| Parameter | Type | Description |
| - | - | - |
| `cursor` | String (optional) | Cursor pointing to the beginning of a page |
| `per_page` | Integer (optional) | Amount of resources that should be returned. (1-100. Default: 25) |
### Responses
All requests to those paginated "list" endpoints have the following response properties:
| Property | Type | Description |
| - | - | - |
| `items` | Array | Array containing the listed resources (eg. transactions) |
| `hasMore` | Boolean | Whether or not there are more resources to be fetched after this page |
| `perPage` | Integer | Amount of resources returned per page |
| `count` | Integer | Amount of resources on the current page |
| `nextCursor` | String \| Null | Cursor pointing to the beginning of the next page (Use the `cursor` query parameter value to get the next page of resources) |
| `nextPageUrl` | String \| Null | URL pointing to the next page of resources (prebuilt for your convenience) |
**Example Response:**
```json json theme={null}
{
"items": [
{...},
{...}
],
"hasMore": true,
"perPage": 50,
"count": 50,
"nextCursor": "kdfhh87sdkfjslasdf7hsbadf",
"nextPageUrl": "https://api.procuros.io/v2/transactions?cursor=kdfhh87sdkfjslasdf7hsbadf"
}
```
### Workflow
1. Make a request to the "list" endpoint without the `cursor` query parameter to fetch the first page of resources. Optionally use the `per_page` query parameter to limit the number of resources to fetch. Example: `GET https://api.procuros.io/v2/transactions`
2. From the response, read the `hasMore` property to determine if there are more resources to fetch on subsequent pages.
3. If more resources are available, use the `nextCursor` property on the response to build the URL of your next request. Alternatively, use the `nextPageUrl` that we've prebuilt for you. Example: `GET https://api.procuros.io/v2/transactions?cursor=kdfhh87sdkfjslasdf7hsbadf`
4. Continue with step 2.
# Batches & Best Before Dates
Source: https://docs.procuros.io/en/api/v2/features-batches-best-before-dates
Most food products have a limited shelf life which needs to be tracked by both supplier and buyer. Therefore, the connector needs to be able to report batch identification and best-before dates on every outbound shipping notice.
## Rules
1. Per line item, one or more batches including best-before date can be returned
## Example
```json json theme={null}
"items": [
{
"lineNumber": 1,
"orderLineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"orderedQuantity": 20,
"shippedQuantity": 20,
"description": "First product description.",
"batches":
[
{
"batchIdentifier": "BATCH_ID_1",
"expirationDate": "2022-12-24",
"quantity": 15.0
},
{
"batchIdentifier": "BATCH_ID_2",
"expirationDate": "2022-12-31",
"quantity": 5.0
}
]
}
]
```
# Bottle Deposits
Source: https://docs.procuros.io/en/api/v2/features-bottle-deposits
Bottle deposit (German: Pfand) applies to products sold in certain single-use or multi-use containers. Buyers will not specifically order bottle deposit items but require bottle deposits as separate line items on invoices. Connectors will therefore be able to handle bottle deposits according to the following rules:
## Rules
1. Per order line item of a product that is subject to bottle deposit, the connector ensures that a second “deposit order line” containing the bottle deposit is added immediately following the original order line.
2. The deposit product used for the “deposit order line” must:
1. Have its own valid EAN/GTIN code
2. Correspond directly to 1 unit of the product ordered. That means, if single PET bottles are ordered, the deposit product (at the time of writing) would be 0.25€ but if full crates of mineral water are ordered, the deposit product (at the time of writing) would be 3.30€ (1.50€ for the crate + 12\*0.15€ for the bottles)
3. The “deposit order line” has to have the exact same quantity as the original order line.
## Examples
Below, you can see how to use bottle deposits when sending orders or invoices.
### Sending Orders
```json json theme={null}
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l"
},
{
"lineNumber": 2,
"identifiers": [...],
"isDepositItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Bottle Deposit PET",
"unitPrice": 0.12
}
]
```
### Sending Invoices
For invoices, bottle deposits can also be added as sub items for grouping purposes.
```json json theme={null}
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": false,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l",
"unitPrice": 0,
"subItems": [
{
"lineNumber": 2,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l",
"unitPrice": 0.84,
"tax": {
"amount": 0.16,
"percentage": 19
}
},
{
"lineNumber": 3,
"identifiers": [...],
"isDepositItem": true,
"isInvoicedItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Bottle Deposit PET",
"unitPrice": 0.12,
"tax": {
"amount": 0.03,
"percentage": 19
}
}
]
}
]
```
# Document Versioning
Source: https://docs.procuros.io/en/api/v2/features-document-versioning
Trade partners sometimes send updated versions of a document they already sent — for example, a revised order with a changed quantity or an amended invoice. Procuros detects these and links the old and new versions together automatically.
Every transaction returned by the API includes three fields that tell you where it sits in that version chain:
| Field | Type | Description |
| - | - | - |
| `isLatestVersion` | `boolean` | `true` if no newer version exists. `false` if this document has been superseded. |
| `replacesProcurosTransactionId` | `uuid \| null` | The ID of the older transaction this one replaces. `null` if this is the original document. |
| `replacedByProcurosTransactionId` | `uuid \| null` | The ID of the newer transaction that replaced this one. `null` if this is still the current version. |
## Recommended Handling
**Always check `isLatestVersion` before importing a document into your system.** If the value is `false`, a newer version of the document is already available and the one you are looking at should be skipped or voided.
```php php theme={null}
foreach ($body->items as $transaction) {
if (!$transaction->isLatestVersion) {
// A newer version exists — skip or void this document
continue;
}
// Safe to import
importTransaction($transaction);
}
```
If `isLatestVersion` is `false` and the document was already imported, you can use `replacedByProcurosTransactionId` to identify the newer version. The newer version will also appear as a separate pending transaction on `GET /v2/transactions`, so no additional API call is needed — simply skip the outdated document and process the newer one when it comes up.
```php php theme={null}
if (!$transaction->isLatestVersion) {
// A newer version will arrive (or has already arrived) as its own pending transaction.
// Skip this outdated document, or void it if it was already imported.
continue;
}
```
### Marking outdated versions as processed
When you mark a transaction as processed, Procuros records that you have acknowledged it. If a transaction in your queue turns out to have `isLatestVersion: false`, you do not need to take any special action — Procuros automatically removes outdated versions from the pending queue before they are returned to you. You will only ever need to mark the latest version as processed.
## Version Chain Example
Given three versions of the same order:
| `procurosTransactionId` | `replacesProcurosTransactionId` | `replacedByProcurosTransactionId` | `isLatestVersion` |
| - | - | - | - |
| `aaa-111` | `null` | `bbb-222` | `false` |
| `bbb-222` | `aaa-111` | `ccc-333` | `false` |
| `ccc-333` | `bbb-222` | `null` | `true` |
Only `ccc-333` should be imported. The earlier versions can be safely skipped or voided.
When polling via `GET /v2/transactions` (pending transactions), outdated versions are removed from the queue automatically as soon as a newer version is detected. `isLatestVersion` will always be `true` for transactions returned by this endpoint.
# Enabled Trade Partners
Source: https://docs.procuros.io/en/api/v2/features-enabled-trade-partners
In order to know which outgoing documents to send via Procuros, a list of **enabled** Trade Partners needs to be maintained. Usually, this is done by either creating a “customer/supplier group” named “via Procuros” or by using custom fields on customers/suppliers marking them as “via Procuros”.
**ALL** outgoing document for an **enabled** Trade Partner should be sent via Procuros once it reaches the status that permits transmission. Procuros will determine whether the receiving enabled Trade Partner can and should receive the document. You will not need to handle this complexity on your end.
# Invoice Modifications
Source: https://docs.procuros.io/en/api/v2/features-invoice-modifications
Invoice modifications can be used to add additional charges or allowances (discounts) to line items or entire documents. For example, you might want to add a handling fee for large items or provide a volume discount for large orders. Modifications can be either absolute (e.g. 5€ handling fee) or relative (e.g. 10% volume discount).
Individual modifications are organised in modification groups. Each modification group **must** have a `level` which determines which modification group is applied first. Furthermore, modification groups contain a `basis` attribute. The basis is used to calculate absolute values for relative modifications, e.g. a relative modification of 10% on a basis of 500€ would result in a 50€ modification.
Modifications on item-level are applied to the subtotal (`quantity` \* `unitPrice`) of the item. Document-level modifications are on the other hand applied to the `subtotalAmount` of the invoice.
## Rules
1. Per line item, one or more modifications can be added
2. Per invoice, one or more modifications can be added
3. No modification group should have the same `level` attribute, unless they are on different items or on the document
4. It is only necessary to send taxes on modifications for absolute charges
**Generally for all modifications (discounts or surcharges):**
Relative (%) does not need tax info (will be distributed equally to all line-items). Example: cash discount, EZHG, partner portal, logistics discount, etc.
**Absolute (€) needs for:**
* **Discounts:** no tax info (will be distributed evenly on all line-items). Example: Credit, Coupon, etc.
* **Surcharge:** needs tax info (because comparable to an independent line-item). Example: shipping costs, minimum quantity surcharge, packaging surcharge, etc.
## Examples
### Single charge on document-level
An invoice with an additional 5€ (net) shipping charge on document-level.
```json json theme={null}
{
"header": {...},
"items": [...],
"summary": {
"subtotalAmount": 100,
"totalCharges": 5,
"totalAllowances": 0,
"netAmount": 105,
"grossAmount": 124.95,
"dueAmount": 124.95,
"tax": {...},
"modificationGroups": [
{
"level": 1,
"basis": 100,
"modifications": [
{
"type": "CHARGE",
"reasonCode": "SHIPPING",
"amount": 5,
"tax": {
"amount": 0.95,
"percentage": 19,
"description": "Umsatzsteuer"
}
}
]
}
]
}
}
```
### Multiple modifications on item- and document-level
A more complex scenario with one modification on item-level and two modifications on document-level.
```json json theme={null}
{
"header": {...},
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": false,
"quantity": 5,
"unitOfMeasure": "EA",
"description": "Large Item",
"unitPrice": 1000,
"tax": {
"amount": 190,
"percentage": 19,
"description": "Umsatzsteuer"
},
"modificationGroups": [
{
"level": 1,
"basis": 5000,
"modifications": [
{
"type": "ALLOWANCE",
"reasonCode": "DISCOUNT",
"amount": 500
}
]
}
]
}
],
"summary": {
"subtotalAmount": 4500,
"totalCharges": 50,
"totalAllowances": 455,
"netAmount": 4095,
"grossAmount": 4873.05,
"dueAmount": 4873.05,
"tax": {...},
"modificationGroups": [
{
"level": 1,
"basis": 4500,
"modifications": [
{
"type": "CHARGE",
"reasonCode": "SHIPPING",
"amount": 50,
"tax": {
"amount": 9.5,
"percentage": 19,
"description": "Umsatzsteuer"
}
}
]
},
{
"level": 2,
"basis": 4550,
"modifications": [
{
"type": "ALLOWANCE",
"reasonCode": "DISCOUNT",
"percentage": 10,
"description": "Loyal Customer Discount"
}
]
}
]
}
}
```
**Explanation:** First, the modifications on item-level are applied. Since item-level modifications are applied to the subtotal (`quantity` \* `unitPrice`) of the item, the `subtotalAmount` of the invoice is 4.500€. Next, the document-level modifications are applied. For the modification with `level = 1`, we apply the charge to the `subtotalAmount` of the invoice. Thus, the subtotal (without taxes) is 4.500€+50€ after applying the first modification. Finally, we apply the second modification (`level = 2`) to the new subtotal and end up with an invoice `netAmount` of 4.095€.
# Package Identification
Source: https://docs.procuros.io/en/api/v2/features-package-identification
More and more trade partners require shipments to be marked externally with barcodes digitally linking them to shipping notices and thus enabling a far easier and faster goods receival processes.
In this case, shipping notices must include a “shipment hierarchy” that identifies every transport unit (pallet, carton, etc.) using a unique transport unit identifier. The identification system used is usually SSCC (Serial Shipment Container Code)
## Examples
Below, you can see how to build the “shipment hierarchy” for different shipment scenarios.
### Single package
A single package will have a transport label printed on the physical package and list a single transport unit in digital form.
**Physical**
Single SSCC on package
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
}
]
}
```
### Multiple packages
A shipment with multiple package will have a transport label printed on every package and one transport unit listed per package in digital form.
**Physical**
One SSCC on every package
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
},
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
}
]
}
```
### Single pallet (homogeneous or mixed content)
A shipment that consists of a single pallet will have a single transport label printed on the pallet shrink wrap. In digital form, a single transport unit is listed and the amount of cartons on the pallet is communicated via the `containedTradeUnitCount` parameter.
**Physical**
Single SSCC on pallet
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 12, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
```
### Sandwich pallet (homogenous pallets stacked)
A pallet that is made up of multiple homogeneous “layers” (sandwich pallet) receives N+1 transport labels. One label on the shirk wrap of the whole stacked pallet and one label per layer. The same is true for the digital form: Transport units describing the different “layers” are contained within a wrapping transport unit describing the whole stacked pallet.
**Physical**
One SSCC on the shrink wrap of the stacked pallet
One SSCC on each sandwich layer
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"transportUnits": [ // further transport units contained within
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 12, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 6, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365379",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 24, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
]
}
```
### Multiple pallets (homogeneous or mixed content)
Shipments that consist of multiple pallets of either homogeneous or mixed content are handled similar to multiple packages. One transport label is attached to every physical pallet and in digital form one transport unit is used for every pallet.
**Physical**
One SSCC on every pallet
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
```
### Other scenarios
Please contact us if you are unsure or require different scenarios (containers, etc.).
# Product Identification
Source: https://docs.procuros.io/en/api/v2/features-product-identification
Based on various identification data, a product can reliably be identified within the ERP system.
## Identification Data
* EAN/GTIN: Barcode data. (optional but present in 99% of retail use cases)
* Buyer part number: A product ID assigned by the buyer. (optional, used only if EAN/GTIN are not provided)
* Supplier part number: A product ID assigned by the supplier. (optional, used only if EAN/GTIN are not provided)
## Rules
1. Products must be uniquely identified. If multiple products within the ERP system match the provided identification data, an error must be reported to Procuros.
# Taxes (VAT)
Source: https://docs.procuros.io/en/api/v2/features-taxes-vat
## Receiving Taxes
Taxes (mainly VAT) should be handled properly. As pricing and tax data is almost never supplied by the buyer on incoming orders, you need to resolve the correct tax rate that applies to the specific document from the ERP system.
### Rules
1. If the ERP system does not automatically apply correct tax rates when you import a transaction pulled from Procuros, you will need to determine the correct rate yourself the same way the ERP system does when users manually add orders into the system.
***
## Sending Taxes
Each line item of an invoice contains the following information, detailing tax percentage, amount, the VAT category, and a description of why the tax was applied.
```json json theme={null}
"tax": {
"percentage": 19,
"amount": 7.50,
"category": "VAT",
"description": "Total Tax"
}
```
This is how an item that is tax free is represented:
```json json theme={null}
"tax": {
"percentage": 0,
"amount": 0,
"category": "ZERO_RATED",
"description": "Tax free"
}
```
### VAT categories
`category` states how the amount is treated for VAT. Use one of the following:
| Category | Use it for |
| - | - |
| `VAT` | A normal taxed amount, at either the standard or a reduced rate. |
| `ZERO_RATED` | Goods taxed at zero percent. |
| `EXEMPT` | Amounts exempt from VAT. |
| `VAT_REVERSE_CHARGE` | The buyer accounts for the VAT instead of the supplier. |
| `VAT_INTRA_COMMUNITY` | A supply to another EU member state. |
| `VAT_EXPORT` | A supply to a country outside the EU. |
| `VAT_OUT_OF_SCOPE` | Amounts not subject to VAT at all. |
Several countries require the category, and an exemption reason alongside it, on an electronic invoice.
The same `category` is available on each entry of the document-level `summary.tax.items` array.
### Rules
1. Each line item in an invoice must have a `tax` attribute provided in the payload. You will need to determine this tax rate, amount, category, and description from the ERP system.
2. When the category is one of the exempt or zero-rated values, put the reason the exemption applies in the `description` of the matching `summary.tax.items` entry. Several countries require that reason to appear on the invoice.
# Tracking Document Status
Source: https://docs.procuros.io/en/api/v2/features-tracking-document-status
Once an outgoing document is being sent to the Trade Partner through the Procuros API, it should be marked for two reasons:
1. To make sure it is not sent again
2. To give users transparency regarding the status of their documents
Most ERP systems have some way to attach information to documents. If the ERP system you are building a connector for does not support this, please get in touch with us to find an alternative solution.
These data fields should be made available on all outgoing documents:
## Rules
* If Procuros accepted the transaction and intends to forward it to the receiving Trade Partner, it will respond with a `201: Created` status code. In this case, the document **Status** field should be set to `TRANSMITTED`.
* If Procuros accepted the transaction but does not intend to forward it to the receiving Trade Partner, it will respond with a `202: Accepted` status code. In this case, the document **Status** field should be set to `NO_ACTION`. The response will also include a `procurosTransactionId` that can be used as a reference for support or tracking purposes. Possible reasons for Procuros not to forward documents:
1. The trade relationship between the sender (you) and the receiving trade partner is not (yet) active.
2. The receiving trade partner is (currently) not accepting documents of this type
* If Procuros did NOT accept the transaction, it will respond with either a `422: Validation Error` or a `400: Bad Request` status code.
In this case, the document **Status** field should **NOT** be set to make sure the document will be retried the next time you are processing outgoing transactions. The response from Procuros will contain a link to view the error on the Procuros Portal. You can optionally add this link to a "**Error URL**" field attached to the document you were trying to send, giving users easy access to view and resolve errors.
* Only documents that have an empty **Status** field should be retrieved from the ERP for sending via Procuros.
## Retrying Documents
If a document has failed to send to Procuros, as per the rules above it should not be marked with one of these statuses: `TRANSMITTED` or `NO_ACTION`.
You should instead retry the document until it is able to be handled by Procuros. This should occur by the ERP administrators making changes to the document to resolve why it was not valid.
This is why you must [report any errors](/en/api/v2/concept-error-handling) documents have via the API, in order for Procuros to notify the customer.
### Caveats
* Depending on your use case, if you are polling for data very often, you may not want to send a document error every time you poll for data. Instead, you may want to send an error only after a certain number of retries. This is up to you to decide.
# Trade Partner + Party Identification
Source: https://docs.procuros.io/en/api/v2/features-trade-partner-party-identification
## Definition of Terms
**Trade Partner** A terms referring to either a customer or a supplier.
**Party** An entity attached to a trade partner. Example: Ship-To parties are entities receiving deliveries for a trade partner. Bill-To parties are entities receiving invoices.
## Description
Based on the GLN data contained within incoming transactions, a trade partner (customer/supplier) as well as Ship-To (delivery) and Bill-To (billing) parties on that trade partner should reliably be identified within the ERP system.
## Identifiers
* Buyer GLN
* Ship-To GLN (optional, fallback to Buyer GLN if not provided)
* Bill-To GLN (optional, fallback to Buyer GLN if not provided)
## Rules
1. All provided GLN information **MUST** be used and match parties on the same trade partner, meaning no fallbacks to standard settings such as a “standard delivery party” as known to the ERP system are allowed!
**Example 1**: A trade partner can be identified based on the provided Buyer and Bill-To GLN but a delivery party cannot be found using the provided Ship-To GLN on this trade partner. In this case, the corresponding transaction should not be processed and instead an error needs to be reported.
**Example 2**: Buyer GLN and Bill-To GLN on the order are different. A trade partner was uniquely identified using the Bill-To GLN but the Buyer GLN does not appear on the trade partner or one of it’s billing parties. In this case, the corresponding transaction should not be processed and instead an error needs to be reported.
2. If no Ship-To or Bill-To GLN are provided, they are to be considered equal to the mandatory Buyer GLN and transactions should be processed accordingly.
## Implementation Checklist
* ✅ Trade partner can be identified using only the Buyer GLN
* ✅ Trade partner can be identified using Buyer, Ship-To and Bill-To GLN
* ✅ Trade partner identification fails, if ANY of the provided GLNs don't match a party on the same trade partner
# Overview
Source: https://docs.procuros.io/en/api/v2/overview
Welcome to the Procuros API. You are currently reading the documentation for API V2.
The Procuros API is the recommended way of integrating with the Procuros Network in order to exchange business transactions with your Trade Partners.
Our API follows RESTful patterns, accepts and returns JSON-encoded data and uses standard HTTP verbs and response codes.
## OpenAPI Specification
The complete OpenAPI specification for the Procuros API v2 is available in raw format for easy integration with your development tools:
Access the complete OpenAPI specification file to use with tools like Postman, Insomnia, or other API development tools.
## Incoming Transactions
### Retrieving and Processing Transactions
To retrieve unprocessed incoming transactions from Procuros, we recommend using a cron job/interval for simplicity.
Looping through the list of retrieved transactions, you will try to process/import them. See our [Quick Start Guide](/en/api/v2/quick-start) for an example how this can be done.
### Reporting Processing Status
Once you have looped through the unprocessed transactions and attempted to process them you will report back whether processing was successful or not.
If a transaction could not be processed, you will send across an error reason and level. This will trigger the exception handling flow:
* An e-mail notification will be sent to the responsible party for resolution
* The error will show up in the Procuros Portal together with the error reason for self-service resolution by the responsible party.
## Outgoing Transactions
### Retrieving and Preparing Documents
To retrieve new unprocessed documents from the ERP system that should be sent via Procuros we recommend using a cron job/interval that runs every 10-30 minutes for simplicity reasons, but you are free to make this event-based as well.
To know which documents should be sent via Procuros, a list of “enabled” customers and suppliers needs to be maintained. This is explained in detail on [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners). Generally, all outgoing documents for an “enabled” Trade Partner (shipping notices, invoices, etc. for customers and orders for suppliers) should be sent via Procuros. We will handle routing and inactive trade relationships. More on that later.
For every document that fulfils the above criteria, you will build the “transaction payload” according to the [API specification](/en/api/v2/incoming-transactions/list-incoming-transactions)) corresponding to the document type (order, shipping notice, etc.).
### Sending Transactions
If you are able to successfully build and send a transaction payload to Procuros, we will respond in one of three ways:
1. For documents Procuros intends to forward to the receiving trade partner, the Procuros API responds with an `201: Created` status code and you should mark the document as `TRANSMITTED`.
2. If we determine the transaction should **not** be forwarded to the trade partner (eg. because the trade relationship is not yet active or documents of that type are not currently accepted by the receiving trade partner), the Procuros API will respond with an `202: Accepted` status code and you will mark the document as `NO_ACTION` to indicate to users that the document was accepted by Procuros but will not be forwarded. More on this in [Tracking Document Status](/en/api/v2/features-tracking-document-status).
3. If the transaction payload sent by you contains errors, the Procuros API will respond with a `422: Validation Error`. More on this below.
4. If a different error occurs, such as `PayloadAlreadyReceived` then this will be reported back via the status code `400: Bad Request`.
### Handling Errors
If you were not able to successfully build the transaction payload to be sent via Procuros you will send an error payload instead to trigger the Exception Handling flow and allow the responsible parties to fix the underlying issue (i.e. change or add information in the unprocessed document). Error reasons could be e.g. missing GLNs or GTIN/EAN codes.
When you send an error payload to the Procuros API, we will respond with an **Error Url** that points to the error within the Procuros Portal. You can attach the Link to the document for which you were unable to build the transaction payload giving your user an easy way to resolve the error fast.
You will also receive an Error Url in case the transaction payload you sent is invalid and the Procuros API responds with `422: Validation Error`.
In any case, you will re-try sending the document until it succeeds.
## Transport Labels
Transport units on Shipping Notice and Dispatch Instruction Response transactions can carry a Procuros-generated SSCC transport label. It is returned as a `transportLabel` object with a `zplUrl` and a `pdfUrl`, giving you the raw ZPL and the rendered PDF version of the same label.
To download the file content, call the [Download Transport Label](/en/api/v2/all-transactions/download-transport-label) endpoint using the value of either URL as the `transportLabelUrl` path parameter. The endpoint requires the same API token as the other endpoints and streams the file content back for download.
# Quick Start
Source: https://docs.procuros.io/en/api/v2/quick-start
In this guide, we will go through the process of setting up an API connection, and a few basic endpoints that you can use for EDI document management.
We will use PHP as the example language but you can translate the examples to any programming language you desire.
## Connecting to the API
We assume for this PHP example that `Guzzle` is installed and available to the script.
```php php theme={null}
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', '', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
## Listing Documents
Following on from this, you can use the connection to list orders from your trade partners.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
All types of documents are returned from this API call. In order to filter for a specific type, you may pass the `filter` URL parameter. For example:
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER', [
'headers' => $headers,
]);
```
For a list of all available parameters, please see the [List Incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) API reference.
## Sending Documents
Similar to listing documents, you can use the connection to send documents to your trade partners.
```php php theme={null}
$transaction = [
"type": "ORDER",
"content": [
"header": [
"orderIdentifier": "bestellung-20231203-001",
"orderDate": "2023-12-03",
"currency": "EUR",
"requestedDeliveryDate": "2023-12-06",
"buyer": ["identifiers": [["domain": "GS1", "identifier": "3220010000001" ]]],
"supplier": ["identifiers": [["domain": "GS1", "identifier": "3220010000013" ]]],
"billTo": ["identifiers": [["domain": "GS1", "identifier": "3220010000001" ]]],
"shipTo": ["identifiers": [["domain": "GS1", "identifier": "3220010000003" ]]],
],
"items": [
[
"identifiers": [["domain": "GS1", "identifier": "2330000000007" ]],
"lineNumber": 1,
"quantity": 10,
"isDepositItem": false,
"unitOfMeasure": "EA",
"description": "A description of the item",
"requestedDeliveryDate": null,
"unitPrice": 1.23
]
]
]
];
$client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => $headers,
'json' => $transaction,
]);
```
For a list of all available document types that can be created, as well as the JSON body format for each, please see the [Send Transaction](/en/api/v2/outgoing-transactions/send-transaction) API reference.
# Order Responses
Source: https://docs.procuros.io/en/api/v2/receiving-order-responses
This is the right section for you if you are acting as a customer and looking to receive Order Responses from your suppliers.
In this guide you will learn how to receive new Order Responses from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the Order Responses.
It is important to mark the Order Responses as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Order Response Types
Order Responses can have one of three types:
* **ACCEPT**: The order was accepted exactly as ordered
* **REJECT**: The order was fully rejected
* **CHANGE**: Part of the order was accepted but either line item quantities or delivery date are changed
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Order Responses
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `ORDER_RESPONSE`.
In this case, the easiest way to achieve the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER_RESPONSE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `ORDER_RESPONSE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'ORDER_RESPONSE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Order Response as Processed
To mark an Order Response as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Order Responses as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Order Response
In the event an Order Response was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these Order Responses as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the Order Response not being processed, which will be used for solving the issue.
### Single Order Response
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Unknown order identifier referenced'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Unknown order identifier referenced'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Orders
Source: https://docs.procuros.io/en/api/v2/receiving-orders
This is the right section for you if you are acting as a supplier and looking to receive orders from your customers.
Throughout this guide you will learn how to pull new orders from the Procuros API, as well as how to paginate over them, mark them as processed, or report errors with the orders.
It is important to mark the orders as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as "processing failed".\*\*\*\*
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/incoming-transactions/list-incoming-transactions).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Process
Incoming orders retrieved from the Procuros API can be imported into the ERP System.
These are usually the steps taken:
1. Uniquely identify customer (see [Trade Partner + Party Identification](/en/api/v2/features-trade-partner-party-identification))
2. Uniquely identify every product ordered (see [Product Identification](/en/api/v2/features-product-identification))
3. Handle Bottle Deposits (see [Bottle Deposits](/en/api/v2/features-bottle-deposits))
4. Resolve customer-specific prices for products (if not done automatically by ERP-System)
### Rules
As a general rule of thumb: An order retrieved from Procuros and one manually entered by a user should be exactly the same. One exception could be some way to indicate the “source” of the order being “Procuros” instead of “Manual”, “Shopify”, or something else.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a 2xx status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Orders
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
The Order response includes all header and item level fields, including:
* **Header level**: `attachments`, `finalRecipient` party, `technicalRecipient` party, `technicalSender` party, and other party information
* **Item level**: `attachments`, product specifications, dimensions, certifications, and other item details
Refer to the OpenAPI schema documentation for the complete list of available fields.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=ORDER', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark Orders as Processed
To mark an order as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Orders as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check the request was successful
```
## Report an Error Processing Orders
In the event an order was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these orders as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the order not being processed, which will be used for solving the issue.
### Single Order
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Missing shipping details in order'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Missing shipping details in order'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Product Catalogs
Source: https://docs.procuros.io/en/api/v2/receiving-product-catalogs
This is the right section for you if you are acting as a customer and looking to receive Product Catalogs from your suppliers.
In this guide you will learn how to receive new Product Catalogs from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the Product Catalogs.
It is important to mark the Product Catalogs as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Product Catalog
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `PRODUCT_CATALOG`.
In this case, the easiest way to achieve the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=PRODUCT_CATALOG', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `PRODUCT_CATALOG` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'PRODUCT_CATALOG';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Product Catalog as Processed
To mark an Product Catalog as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Product Catalogs as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing a Product Catalog
In the event an Product Catalog was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these Product Catalogs as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the Product Catalog not being processed, which will be used for solving the issue.
### Single Product Catalog
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Price missing on line item 10'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Price missing on line item 10'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Shipping Notices
Source: https://docs.procuros.io/en/api/v2/receiving-shipping-notices
This is the right section for you if you are acting as a customer and looking to receive shipping notices from your suppliers.
In this guide you will learn how to receive new shipping notices from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the shipping notices.
It is important to mark the shipping notices as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Shipping Notices
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `SHIPPING_NOTICE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=SHIPPING_NOTICE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `SHIPPING_NOTICE` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'INVOICE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Shipping Notice as Processed
To mark a shipping notice as processed, and take it out of the incoming transactions queue, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Shipping Notices as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Shipping Notice
In the event a shipping notice was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these shipping notices as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the shipping notice not being processed, which will be used for solving the issue.
### Single Shipping Notice
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Credit Notes
Source: https://docs.procuros.io/en/api/v2/sending-credit-notes
This is the right section for you if you are acting as a supplier and looking to send credit notes to your customers.
Throughout this guide you will learn how to send new credit notes to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a credit note to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Credit Notes
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including credit notes.
The following fields are required:
* `type` (Transaction type. In this case `CREDIT_NOTE`)
* `content` (The details of the credit note.)
Inside the `content` you will need to build all credit note items. All details can be found in the `CREDIT_NOTE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'CREDIT_NOTE',
'content' => [
'header' => [
'buyer' => [
'identifiers' => [
[
'identifier' => '3220010000001',
'domain' => 'GS1',
],
],
],
'supplier' => [
'identifiers' => [
[
'identifier' => '3220010000004',
'domain' => 'GS1',
],
],
],
'type' => 'CORRECTION',
'creditNoteIdentifier' => 'valid-credit-note-identifier-1',
'creditNoteDate' => '2022-05-09',
'creditNoteValueDate' => '2022-05-10',
'reason' => 'valid-credit-note-reason-1',
'invoiceIdentifier' => 'valid-invoice-identifier-1',
'invoiceDate' => '2022-05-09',
'shippingNoticeIdentifier' => 'valid-credit-note-shipment-identifier-1',
'shippingNoticeDate' => '2022-05-07',
'orderIdentifier' => 'valid-credit-note-order-identifier-1',
'orderDate' => '2022-05-01',
'paymentTerms' => [],
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
[
'identifier' => 'valid-invoice-item-identifier-1',
'domain' => 'GS1',
],
],
'isDepositItem' => false,
'quantity' => 10,
'unitPrice' => 4.5,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'amount' => 8.55,
'percentage' => 19,
],
],
[
'lineNumber' => 2,
'identifiers' => [
[
'identifier' => 'valid-invoice-item-identifier-2',
'domain' => 'GS1',
],
],
'isDepositItem' => true,
'quantity' => 10,
'unitPrice' => 4.5,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'amount' => 0,
'percentage' => 0,
],
],
],
'summary' => [
'subtotalAmount' => 90,
'grossAmount' => 98.55,
'netAmount' => 98.55,
'dueAmount' => 98.55,
'totalAmountWithoutTax' => 90,
'totalCharges' => 8.55,
'totalAllowances' => 0,
'tax' => [
'total' => 1,
'items' => [
[
'percentage' => 19,
'taxableAmount' => 44.5,
'taxAmount' => 8.5,
'category' => 'Mwst.',
'description' => 'Mehrwertsteuer',
]
],
'description' => 'Tax Summary',
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Dispatch Instruction Responses
Source: https://docs.procuros.io/en/api/v2/sending-dispatch-instruction-responses
This is the right section for you if you are acting as a fulfillment provider and looking to send dispatch instruction responses to a supplier.
Throughout this guide you will learn how to send new dispatch instruction responses to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a dispatch instruction response to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Dispatch Instruction Responses
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including dispatch instruction responses.
The following fields are required:
* `type` (Transaction type. In this case `DISPATCH_INSTRUCTION_RESPONSE`)
* `content` (The details of the dispatch instruction response.)
Inside the `content` you will need to build all dispatch instruction response items. All details can be found in the `DISPATCH_INSTRUCTION_RESPONSE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"DISPATCH_INSTRUCTION_RESPONSE",
"content" => [
"header" => [
"orderId" => null,
"orderDate" => null,
"shipmentId" => "48148",
"shippingNoticeIdentifier" => "SHIPMENT-123",
"shippingNoticeDate" => "2022-10-12T12:53:51.000000Z",
"dispatchInstructionResponseDate" => "2022-10-12T12:53:51.000000Z",
"responseDate" => "2022-10-12T12:53:51.000000Z",
"shipmentDate" => "2022-10-12T12:53:51.000000Z",
"requestedDeliveryDate" => "2022-10-11T22:00:00.000000Z",
"expectedDeliveryDate" => "2022-10-11T22:00:00.000000Z",
"shipFrom" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"shipTo" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"billTo" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"buyer" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"supplier" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"technicalRecipient" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "3220010000006",
],
],
],
"technicalSender" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "3220010000007",
],
],
],
"comments" => null,
],
"transportUnits" => [
[
"unitIdentifier" => "342601560208144493",
"unitType" => null,
"containedTradeUnitCount" => null,
"carrier" => [
"name" => "DHL Express",
"trackingNumber" => "00340434611510850247",
"trackingUrl" => "https://www.dhl.com/track?AWB=00340434611510850247",
],
"items" => [
[
"lineNumber" => 4,
"shippingNoticeLineNumber" => 1,
"shippedQuantity" => 1,
"orderedQuantity" => 1,
"isDepositItem" => false,
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "abc",
],
],
"unitOfMeasure" => "EA",
"unitPrice" => null,
"currency" => null,
"description" => "",
"batches" => [
[
"batchIdentifier" => "abc",
"expirationDate" => "2022-12-31",
"quantity" => 30,
],
],
"parentLineNumber" => null,
"openQuantityAction" => null,
],
],
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Dispatch Instructions
Source: https://docs.procuros.io/en/api/v2/sending-dispatch-instructions
This is the right section for you if you are acting as a supplier and looking to send dispatch instructions to your fulfillment provider.
Throughout this guide you will learn how to send new dispatch instructions to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a dispatch instruction to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Dispatch Instructions
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including dispatch instructions.
The following fields are required:
* `type` (Transaction type. In this case `DISPATCH_INSTRUCTION`)
* `content` (The details of the dispatch instruction.)
Inside the `content` you will need to build all dispatch instruction items. All details can be found in the `DISPATCH_INSTRUCTION` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"DISPATCH_INSTRUCTION",
"content" => [
"header" => [
"orderIdentifier" => "valid-order-id",
"orderDate" => "2023-06-01",
"shipmentIdentifier" => "valid-dispatch-instruction-shipment-id-1",
"noticeDate" => "2023-06-01",
"requestedDeliveryDate" => "2023-06-05",
"customer" => [
"addressId" => "valid-dispatch-instruction-customer-1",
"identifiers" => [
[
"identifier" => "3220010000001",
"domain" => "GS1",
],
],
],
"supplier" => [
"addressId" => "valid-dispatch-instruction-supplier-1",
"identifiers" => [
[
"identifier" => "3220010000002",
"domain" => "GS1",
],
],
],
"shipFrom" => [
"addressId" => "valid-dispatch-instruction-shipFrom-1",
"identifiers" => [
[
"identifier" => "3220010000003",
"domain" => "GS1",
],
],
],
],
"items" => [
[
"orderLineNumber" => 1,
"shippingNoticeLineNumber" => 1,
"shippedQuantity" => 1,
"orderedQuantity" => 1,
"openQuantityAction" => "DISCARDED",
"unitOfMeasure" => "EA",
"identifiers" => [
[
"identifier" => "valid-dispatch-instruction-identifier-1",
"domain" => "GS1",
],
],
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Inventory Reports
Source: https://docs.procuros.io/en/api/v2/sending-inventory-reports
This is the right section for you if you are acting as a fulfilment provider and looking to send inventory reports to your customers.
Throughout this guide you will learn how to send inventory reports to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an inventory report to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send inventory reports
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including inventory reports.
The following fields are required:
* `type` (Transaction type. In this case `INVENTORY_REPORT`)
* `content` (The details of the inventory report items.)
Inside the `content` you will need to build all inventory report items. All details can be found in the `INVENTORY_REPORT` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"INVENTORY_REPORT",
"content" => [
"header" => [
"warehouse" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Test Sender GmbH",
"street" => "Musterstraße 1",
"addressExtra" => "c/o Max Mustermann",
"city" => "Entenhausen",
"postalCode" => "123456",
"countryCode" => "DE"
],
"name" => "Test Sender GmbH"
],
"goodsOwner" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Test Receiver GmbH",
"street" => "Lilienstraße 36",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
],
"name" => "Test Receiver GmbH"
],
"inventoryReportIdentifier" => "Summer 2025",
"inventoryReportDate" => "2024-06-01"
],
"items" => [
[
"unitOfMeasure" => "EA",
"identity" => [
"senderPartnerId" => "PRD-0001",
"receiverPartnerId" => "AB-MM-9988",
"gtin" => "12345678901234",
],
"lineNumber" => 12,
"availableQuantity" => 5,
"unitPrice" => 44.23,
"pricingUnitOfMeasure" => "CT",
"pricingUnitQuantity" => 100,
"name" => "Name of the product",
"hsCode" => "222222",
"originCountryCode" => "US"
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Invoices
Source: https://docs.procuros.io/en/api/v2/sending-invoices
This is the right section for you if you are acting as a supplier and looking to send invoices to your customers.
Throughout this guide you will learn how to send invoices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an invoice to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
1. If products being invoiced are subject to bottle deposit, add additional line items for bottle deposit (see: [Bottle Deposits](/en/api/v2/features-bottle-deposits))
2. Make sure taxes (mainly VAT) are correctly added to line items (see: [Taxes (VAT)](/en/api/v2/features-taxes-vat))
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Invoices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including invoices.
The following fields are required:
* `type` (Transaction type. In this case `INVOICE`)
* `content` (The details of the invoice items.)
Inside the `content` you will need to build all invoice items. All details can be found in the `INVOICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
The example below covers a single shipping notice, so its `shippingNoticeIdentifier` and `shippingNoticeDate` are shared in the header. For an invoice covering multiple shipping notices, omit both header fields and provide them on each item instead; optionally add `shippingNoticeLineNumber` to each item.
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'INVOICE',
'content' => [
'header' => [
'invoiceIdentifier' => 'API-INV-2022-08-31-001',
'invoiceDate' => '2022-08-31',
'invoiceValueDate' => '2022-09-01',
'shippingNoticeIdentifier' => 'SFTP-SHIP-2022-08-31-001',
'shippingNoticeDate' => '2022-08-31',
'orderIdentifier' => 'SFTP-2022-08-31-001',
'orderDate' => '2022-08-31',
'requestedDeliveryDate' => '2022-08-31',
'expectedDeliveryDate' => '2022-08-31',
'paymentTerms' => [
[
'payInNumberOfDays' => 30,
'percentage' => 0
]
],
'supplier' => [
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => 'C10000'
]
]
],
'buyer' => [
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => 'C20000'
]
]
]
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => '2330010000019'
]
],
'isDepositItem' => false,
'quantity' => 10,
'unitPrice' => 10,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'percentage' => 19,
'amount' => 1.9,
'category' => 'VAT',
'description' => 'MwSt. 19%'
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
## Advanced Use Cases
When it comes to sending invoices, there are a number of advanced cases, such as [Invoice Modifications](/en/api/v2/features-invoice-modifications).
Please see the Features section of our API reference for a detailed description of all advanced use cases.
# Receival Notices
Source: https://docs.procuros.io/en/api/v2/sending-receival-notices
This is the right section for you if you are acting as a customer and looking to send receival notices to your suppliers.
Throughout this guide you will learn how to send receival notices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a receival notice to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send receival notices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including receival notices.
The following fields are required:
* `type` (Transaction type. In this case `RECEIVAL_NOTICE`)
* `content` (The details of the receival notice.)
Inside the `content` you will need to build the header and transport units with items. All details can be found in the `RECEIVAL_NOTICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"RECEIVAL_NOTICE",
"content" => [
"header" => [
"receivalAdviceNumber" => "RCV-2024-001",
"receivalDate" => "2024-06-15T10:30:00.000000Z",
"deliveryNoteNumber" => "DN-2024-456",
"customerOrderNumber" => "PO-2024-123",
"deliveryNoteDate" => "2024-06-14T14:00:00.000000Z",
"orderDate" => "2024-06-01T09:00:00.000000Z",
"comments" => "All items received in good condition",
"carrierId" => "DHL",
"carrierDomain" => "SCAC",
"trackingNumber" => "1234567890",
"trackingUrl" => "https://tracking.example.com/1234567890",
"shipFrom" => [
"name" => "Supplier Warehouse GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Supplier Warehouse GmbH",
"street" => "Industriestraße 10",
"addressExtra" => "Building A",
"city" => "Munich",
"postalCode" => "80331",
"countryCode" => "DE"
]
],
"shipTo" => [
"name" => "Customer Warehouse GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Customer Warehouse GmbH",
"street" => "Lagerstraße 25",
"addressExtra" => "Receiving Dock 3",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
]
],
"customer" => [
"name" => "Customer Company GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Customer Company GmbH",
"street" => "Hauptstraße 50",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
]
],
"supplier" => [
"name" => "Supplier Company GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Supplier Company GmbH",
"street" => "Lieferantenweg 15",
"city" => "Munich",
"postalCode" => "80331",
"countryCode" => "DE"
]
]
],
"transportUnits" => [
[
"unitIdentifier" => "342601560208144493",
"unitType" => "EURO_PALLET",
"containedTradeUnitCount" => 4,
"items" => [
[
"lineNumber" => 1,
"receivedQuantity" => 10,
"shippedQuantity" => 10,
"orderedQuantity" => 10,
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "12345678901234"
],
[
"domain" => "BUYER",
"identifier" => "CUST-PROD-001"
]
],
"orderLineNumber" => 1,
"unitOfMeasure" => "EA",
"description" => "Premium Product A",
"unitPrice" => 24.50,
"currency" => "EUR",
"batches" => [
[
"batchIdentifier" => "BATCH-2024-06-001",
"expirationDate" => "2025-12-31",
"quantity" => 10
]
]
],
[
"lineNumber" => 2,
"receivedQuantity" => 18,
"shippedQuantity" => 20,
"orderedQuantity" => 20,
"rejectedQuantity" => 2,
"rejectReason" => "Damaged packaging",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "98765432109876"
]
],
"orderLineNumber" => 2,
"unitOfMeasure" => "EA",
"description" => "Standard Product B",
"unitPrice" => 12.75,
"currency" => "EUR"
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Sales Reports
Source: https://docs.procuros.io/en/api/v2/sending-sales-report
This is the right section for you if you are acting as a buyer and looking to send sales reports to your suppliers.
Throughout this guide you will learn how to send new sales reports to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Sales Reports
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including sales reports.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'SALES_REPORT',
'content' => [
'header' => [
'salesReportIdentifier' => 'SR-20231206-001',
'salesReportDate' => '2023-12-06',
'salesPeriodStartDate' => '2023-12-01',
'salesPeriodEndDate' => '2023-12-06',
'currency' => 'EUR',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000003']
]
]
],
'locations' => [
[
'location' => [
'identifiers' => [
['domain' => 'BUYER', 'identifier' => 'STORE-001']
],
'name' => 'Main Store'
],
'items' => [
[
'salesReportLineIdentifier' => 'ITEM-001',
'identifiers' => [
['domain' => 'GS1', 'identifier' => '2330000000083']
],
'description' => 'Organic Milk 1L',
'unitOfMeasure' => 'EA',
'salesQuantity' => 120,
'returnedQuantity' => 3,
'inventoryQuantity' => 15,
'category' => '1008',
'subCategory' => 'Beverages'
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
# Test Data: Address Identifiers
Source: https://docs.procuros.io/en/api/v2/test-cases-address-identifiers
The following is a list of static test data that exists on our staging system, and which items + identifiers you can expect to find in the data set.
### Legend
* `Partner` - The name of the partner in the test data set
* `Sends` - The types of document this parter can send you on the network
* `Receives` - The types of document this partner can receive from you on the network
* `Domain` - The address identifier domain. `GS1` is used for a `GLN`.
* `Identifier` - The address identifier (GLN, EAN, etc.)
| Partner | Sends | Receives | Domain | Identifier |
| - | - | - | - | - |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000001` |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000002` |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000003` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000004` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000005` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000006` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000007` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000008` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000009` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000010` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000011` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000012` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000013` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000014` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000015` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000022` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000023` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000024` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000016` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000017` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000018` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000019` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000020` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000021` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000025` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000026` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000027` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000028` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000029` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000030` |
# Test Data: Items
Source: https://docs.procuros.io/en/api/v2/test-cases-items
The following is a list of static test data that exists on our staging system, and which items + identifiers you can expect to find in the data set.
### Legend
* `Index` - The index of the item
* `Description` - The description of the item
* `Domain` - The domain of the item. Either `GS1` (a GLN), `BUYER`, or `SUPPLIER`
* `Identifier` - The identifier of the item for that domain
* `Qty` - The quantity of the item
* `Price` - The item price in the test data set
* `UoM` - The Unit of Measure of the item
| Index | Description | Domain | Identifier | Qty | Price | UoM |
| - | - | - | - | - | - | - |
| 1 | Milk, Callets | `BUYER` | `chocolate-milk-callets` | 16 | 70 | `EA` |
| 1 | Milk, Callets | `GS1` | `2330010000001` | 16 | 70 | `EA` |
| 2 | Orecchiette | `BUYER` | `pasta-orecchiette` | 18 | 3.42 | `EA` |
| 2 | Orecchiette | `GS1` | `2330000000002` | 18 | 3.42 | `EA` |
| 3 | | `BUYER` | `bacardiraspberry` | 17 | 20.43 | `EA` |
| 3 | | `GS1` | `2330010000003` | 17 | 20.43 | `EA` |
| 4 | Meat Combo | `BUYER` | `crab-meatcombo` | 19 | 18.94 | `EA` |
| 4 | Meat Combo | `GS1` | `2330000000004` | 19 | 18.94 | `EA` |
| 5 | | `BUYER` | `pralinepaste` | 4 | 57.28 | `EA` |
| 5 | | `GS1` | `2330010000005` | 4 | 57.28 | `EA` |
| 6 | 74 Brights | `BUYER` | `2330000000007` | 18 | 0.69 | `EA` |
| 6 | 74 Brights | `SUPPLIER` | `supplier-port-brights` | 18 | 0.69 | `EA` |
| 6 | 74 Brights | `GS1` | `2330000000007` | 18 | 0.69 | `EA` |
| 7 | Greek Salad | `BUYER` | `2330000000012` | 16 | 11.03 | `EA` |
| 7 | Greek Salad | `SUPPLIER` | `supplier-longos-greeksalad` | 16 | 11.03 | `EA` |
| 7 | Greek Salad | `GS1` | `2330000000012` | 16 | 11.03 | `EA` |
| 8 | Mascarpone | `BUYER` | `2330010000013` | 8 | 31.34 | `EA` |
| 8 | Mascarpone | `SUPPLIER` | `supplier-cheese-mascarpone` | 8 | 31.34 | `EA` |
| 8 | Mascarpone | `GS1` | `2330010000013` | 8 | 31.34 | `EA` |
| 9 | French Vanilla | `BUYER` | `2330010000019` | 2 | 15.33 | `EA` |
| 9 | French Vanilla | `SUPPLIER` | `supplier-yogurt-frenchvanilla` | 2 | 15.33 | `EA` |
| 9 | French Vanilla | `GS1` | `2330010000019` | 2 | 15.33 | `EA` |
| 10 | Crumbs, Bulk | `BUYER` | `bread-crumbs-bulk` | 19 | 15.32 | `EA` |
| 10 | Crumbs, Bulk | `SUPPLIER` | `supplier-bread-crumbs-bulk` | 19 | 15.32 | `EA` |
| 10 | Crumbs, Bulk | `GS1` | `2330010000020` | 19 | 15.32 | `EA` |
| 11 | Cherry | `BUYER` | `piefilling-cherry` | 6 | 1.06 | `EA` |
| 11 | Cherry | `SUPPLIER` | `supplier-piefilling-cherry` | 6 | 1.06 | `EA` |
| 11 | Cherry | `GS1` | `2330000000021` | 6 | 1.06 | `EA` |
| 12 | Italian Corn Meal Poly | `BUYER` | `bread-italiancornmealpoly` | 10 | 54.91 | `EA` |
| 12 | Italian Corn Meal Poly | `SUPPLIER` | `supplier-bread-italiancornmealpoly` | 10 | 54.91 | `EA` |
| 12 | Italian Corn Meal Poly | `GS1` | `2330010000022` | 10 | 54.91 | `EA` |
| 13 | Bones | `BUYER` | `fish-bones` | 12 | 16.09 | `KGM` |
| 13 | Bones | `SUPPLIER` | `supplier-fish-bones` | 12 | 16.09 | `KGM` |
| 13 | Bones | `GS1` | `2330000000023` | 12 | 16.09 | `KGM` |
| 14 | Brisket, Provimi, Bone In | `BUYER` | `veal-brisket-provimi-bone-in` | 19 | 10.52 | `EA` |
| 14 | Brisket, Provimi, Bone In | `SUPPLIER` | `supplier-veal-brisket-provimi-bone-in` | 19 | 10.52 | `EA` |
| 14 | Brisket, Provimi, Bone In | `GS1` | `2330010000025` | 19 | 10.52 | `EA` |
| 15 | | `BUYER` | `bolsmelonliqueur` | 18 | 27.04 | `EA` |
| 15 | | `SUPPLIER` | `supplier-bolsmelonliqueur` | 18 | 27.04 | `EA` |
| 15 | | `GS1` | `2330000000026` | 18 | 27.04 | `EA` |
| 16 | Tongue, Cooked | `BUYER` | `beef-tongue-cooked` | 15 | 17.41 | `EA` |
| 16 | Tongue, Cooked | `SUPPLIER` | `supplier-beef-tongue-cooked` | 15 | 17.41 | `EA` |
| 16 | Tongue, Cooked | `GS1` | `2330000000029` | 15 | 17.41 | `EA` |
| 17 | Radicchio | `BUYER` | `lettuce-radicchio` | 4 | 71.19 | `KGM` |
| 17 | Radicchio | `SUPPLIER` | `supplier-lettuce-radicchio` | 4 | 71.19 | `KGM` |
| 17 | Radicchio | `GS1` | `2330000000031` | 4 | 71.19 | `KGM` |
| 18 | Water | `BUYER` | `crackers-water` | 17 | 70.71 | `EA` |
| 18 | Water | `SUPPLIER` | `supplier-crackers-water` | 17 | 70.71 | `EA` |
| 18 | Water | `GS1` | `2330000000032` | 17 | 70.71 | `EA` |
| 19 | Prime Rib Aaa | `BUYER` | `beef-primeribaaa` | 5 | 43.48 | `EA` |
| 19 | Prime Rib Aaa | `SUPPLIER` | `supplier-beef-primeribaaa` | 5 | 43.48 | `EA` |
| 19 | Prime Rib Aaa | `GS1` | `2330010000036` | 5 | 43.48 | `EA` |
| 20 | | `BUYER` | `chickengiblets` | 19 | 47.27 | `EA` |
| 20 | | `SUPPLIER` | `supplier-chickengiblets` | 19 | 47.27 | `EA` |
| 20 | | `GS1` | `2330000000037` | 19 | 47.27 | `EA` |
| 21 | Cooked Italian | `BUYER` | `ham-cookeditalian` | 6 | 22.64 | `EA` |
| 21 | Cooked Italian | `SUPPLIER` | `supplier-ham-cookeditalian` | 6 | 22.64 | `EA` |
| 21 | Cooked Italian | `GS1` | `2330000000038` | 6 | 22.64 | `EA` |
| 22 | Chardonnay Mondavi | `BUYER` | `wine-chardonnaymondavi` | 3 | 39.11 | `EA` |
| 22 | Chardonnay Mondavi | `SUPPLIER` | `supplier-wine-chardonnaymondavi` | 3 | 39.11 | `EA` |
| 22 | Chardonnay Mondavi | `GS1` | `2330000000039` | 3 | 39.11 | `EA` |
| 23 | Calabrese Baguette | `BUYER` | `bread-calabresebaguette` | 4 | 25.36 | `EA` |
| 23 | Calabrese Baguette | `SUPPLIER` | `supplier-bread-calabresebaguette` | 4 | 25.36 | `EA` |
| 23 | Calabrese Baguette | `GS1` | `2330010000040` | 4 | 25.36 | `EA` |
| 24 | Smoked, Sliced | `BUYER` | `salmon-smoked-sliced` | 2 | 5.18 | `MTR` |
| 24 | Smoked, Sliced | `SUPPLIER` | `supplier-salmon-smoked-sliced` | 2 | 5.18 | `MTR` |
| 24 | Smoked, Sliced | `GS1` | `2330010000050` | 2 | 5.18 | `MTR` |
| 25 | Fettuccine, Egg, Fresh | `BUYER` | `pasta-fettuccine-egg-fresh` | 2 | 8.37 | `KGM` |
| 25 | Fettuccine, Egg, Fresh | `SUPPLIER` | `supplier-pasta-fettuccine-egg-fresh` | 2 | 8.37 | `KGM` |
| 25 | Fettuccine, Egg, Fresh | `GS1` | `2330000000051` | 2 | 8.37 | `KGM` |
| 26 | Butt, Boneless | `BUYER` | `pork-butt-boneless` | 8 | 62.13 | `EA` |
| 26 | Butt, Boneless | `SUPPLIER` | `supplier-pork-butt-boneless` | 8 | 62.13 | `EA` |
| 26 | Butt, Boneless | `GS1` | `2330000000052` | 8 | 62.13 | `EA` |
| 27 | | `BUYER` | `pantscustomdryclean` | 11 | 57.42 | `EA` |
| 27 | | `SUPPLIER` | `supplier-pantscustomdryclean` | 11 | 57.42 | `EA` |
| 27 | | `GS1` | `2330000000053` | 11 | 57.42 | `EA` |
| 28 | Red, Dry | `BUYER` | `lentils-red-dry` | 13 | 36.42 | `EA` |
| 28 | Red, Dry | `SUPPLIER` | `supplier-lentils-red-dry` | 13 | 36.42 | `EA` |
| 28 | Red, Dry | `GS1` | `2330000000059` | 13 | 36.42 | `EA` |
| 29 | Cream Fudge | `BUYER` | `fudge-creamfudge` | 17 | 74.76 | `EA` |
| 29 | Cream Fudge | `SUPPLIER` | `supplier-fudge-creamfudge` | 17 | 74.76 | `EA` |
| 29 | Cream Fudge | `GS1` | `2330010000061` | 17 | 74.76 | `EA` |
| 30 | Coffee | `BUYER` | `filter-coffee` | 20 | 18.46 | `KGM` |
| 30 | Coffee | `SUPPLIER` | `supplier-filter-coffee` | 20 | 18.46 | `KGM` |
| 30 | Coffee | `GS1` | `2330000000063` | 20 | 18.46 | `KGM` |
| 31 | Pina Colada, 355 Ml | `BUYER` | `barmix-pinacolada-355ml-002-001` | 7 | 14.93 | `EA` |
| 31 | Pina Colada, 355 Ml | `SUPPLIER` | `supplier-barmix-pinacolada-355ml-002-001` | 7 | 14.93 | `EA` |
| 31 | Pina Colada, 355 Ml | `GS1` | `2330000000073` | 7 | 14.93 | `EA` |
| 32 | Red | `BUYER` | `cabbage-red` | 16 | 50.68 | `KGM` |
| 32 | Red | `SUPPLIER` | `supplier-cabbage-red` | 16 | 50.68 | `KGM` |
| 32 | Red | `GS1` | `2330010000077` | 16 | 50.68 | `KGM` |
| 33 | Leaves | `BUYER` | `banana-leaves` | 14 | 41.11 | `GRM` |
| 33 | Leaves | `SUPPLIER` | `supplier-banana-leaves` | 14 | 41.11 | `GRM` |
| 33 | Leaves | `GS1` | `2330000000082` | 14 | 41.11 | `GRM` |
| 34 | Vidal Icewine Magnotta | `BUYER` | `wine-vidalicewinemagnotta` | 20 | 32.85 | `EA` |
| 34 | Vidal Icewine Magnotta | `SUPPLIER` | `supplier-wine-vidalicewinemagnotta` | 20 | 32.85 | `EA` |
| 34 | Vidal Icewine Magnotta | `GS1` | `2330000000083` | 20 | 32.85 | `EA` |
| 35 | Sticks, Thin, Plain | `BUYER` | `bread-sticks-thin-plain` | 12 | 77.66 | `EA` |
| 35 | Sticks, Thin, Plain | `SUPPLIER` | `supplier-bread-sticks-thin-plain` | 12 | 77.66 | `EA` |
| 35 | Sticks, Thin, Plain | `GS1` | `2330010000084` | 12 | 77.66 | `EA` |
| 36 | Fresh | `BUYER` | `parsley-fresh` | 100 | 96.37 | `GRM` |
| 36 | Fresh | `SUPPLIER` | `supplier-parsley-fresh` | 100 | 96.37 | `GRM` |
| 36 | Fresh | `GS1` | `2330000000085` | 100 | 96.37 | `GRM` |
| 37 | Original Organic Lager | `BUYER` | `beer-originalorganiclager` | 1 | 31.55 | `EA` |
| 37 | Original Organic Lager | `SUPPLIER` | `supplier-beer-originalorganiclager` | 1 | 31.55 | `EA` |
| 37 | Original Organic Lager | `GS1` | `2330000000087` | 1 | 31.55 | `EA` |
| 38 | Orange, 355ml | `BUYER` | `crush-orange-355ml-001` | 8 | 92.03 | `EA` |
| 38 | Orange, 355ml | `SUPPLIER` | `supplier-crush-orange-355ml-001` | 8 | 92.03 | `EA` |
| 38 | Orange, 355ml | `GS1` | `2330000000092` | 8 | 92.03 | `EA` |
| 39 | Tomato Mush. Florentine | `BUYER` | `soup-tomatomush.florentine` | 17 | 27.22 | `EA` |
| 39 | Tomato Mush. Florentine | `SUPPLIER` | `supplier-soup-tomatomush.florentine` | 17 | 27.22 | `EA` |
| 39 | Tomato Mush. Florentine | `GS1` | `2330000000097` | 17 | 27.22 | `EA` |
| 40 | Linguini, Dry | `BUYER` | `2330010000104` | 19 | 84.12 | `EA` |
| 40 | Linguini, Dry | `SUPPLIER` | `supplier-pasta-linguini-dry` | 19 | 84.12 | `EA` |
| 40 | Linguini, Dry | `GS1` | `2330010000104` | 19 | 84.12 | `EA` |
| 41 | | `BUYER` | `2330000200110` | 20 | 21.66 | `EA` |
| 41 | | `SUPPLIER` | `supplier-bundle-tea` | 20 | 21.66 | `EA` |
| 41 | | `GS1` | `2330000200110` | 20 | 21.66 | `EA` |
| 42 | | `BUYER` | `2330000200111` | 11 | 20.11 | `EA` |
| 42 | | `SUPPLIER` | `supplier-bundle-dinner-for-two` | 11 | 20.11 | `EA` |
| 42 | | `GS1` | `2330000200111` | 11 | 20.11 | `EA` |
| 43 | | `BUYER` | `2330000200112` | 6 | 79.95 | `EA` |
| 43 | | `SUPPLIER` | `supplier-bundle-fruit` | 6 | 79.95 | `EA` |
| 43 | | `GS1` | `2330000200112` | 6 | 79.95 | `EA` |
# Best Practices
Source: https://docs.procuros.io/en/api/v2/test-cases-overview
## Test Data
When testing against staging, we are able to generate static test data for your account. This data is not connected to any real data in your ERP system. It is only used for testing purposes.
We have prepared this data so that you can test different scenarios while building your integration. There are partners that accept different kinds of documents, as well as a list of retail items for your testing needs.
To find a full list of this infromation, please see:
* [Test Data: Address Identifiers](/en/api/v2/test-cases-address-identifiers)
* [Test Data: Items](/en/api/v2/test-cases-items)
## Scenarios you Should Test
When it comes to data integration, it's important to test your integration thoroughly. You should consider the data you will receive or provide to the API. Some scenarios that you should test to ensure that your integration is working correctly are:
* `null` values (Missing dates, missing quantities, etc.)
* Decimal values (quantities, prices, etc.)
* Zeros
Additionally you should consider how your integration handles the following scenarios:
* Validation errors returned from the API
* Can you report an error back to the API, if there is an issue with a document?
* What do you do when there is a duplicate GLN? (Multiple customers were found for the given GLN in the ERP)
* What do you do when there is a duplicate GTIN? (Multiple products were found for the given GTIN in the ERP)
* How to handle missing data in the ERP system?
* Can this data be skipped?
* Should you report an error to the Procuros API?
* How do you handle data received from the API you can't work with?
# List All Transactions
Source: https://docs.procuros.io/en/api/v2/all-transactions/list-all-transactions
/en/api/v2/openapi-v2.yaml get /v2/all-transactions
List all existing transactions to and from your trade partners.
# Show Transaction
Source: https://docs.procuros.io/en/api/v2/all-transactions/show-transaction
/en/api/v2/openapi-v2.yaml get /v2/all-transactions/{procurosTransactionId}
Show a single transaction.
# Changelog
Source: https://docs.procuros.io/en/api/v2/changelog
Recent changes to the Procuros API v2
## Confirmed Delivery Date Is Optional on Order Responses
`POST /v2/transactions` no longer rejects an order response of type `CHANGE` without a `confirmedDeliveryDate`. Before, a `CHANGE` response needed the date in the header or on every item. You can now send an order response with only a `confirmedShipmentDate`, or with no confirmed date at all.
`confirmedDeliveryDate` is still prohibited on `REJECT` responses, and a supplied date must still be a valid date. Whether a confirmed delivery date is required depends on your trade partner.
## Item Identifiers Without a GS1 or BUYER Domain
`POST /v2/transactions` no longer rejects a line item, or a sales report location, because none of its identifiers has the domain `GS1` or `BUYER`. An item identified only by a `SUPPLIER` identifier is now accepted on every document type. Which identifiers are required depends on your trade partner.
On invoices, credit notes, shipping notices and sales reports, each item, and each sales report location, still needs at least one identifier. On orders, order responses, dispatch instructions, dispatch instruction responses and receival notices, `identifiers` may now be empty.
## Free Quantity on Order Line Items
New field `freeQuantity` added to order line items (`OrderItem`), matching the field already available on invoice and credit note line items. It represents quantity provided free of charge in addition to (not part of) `quantity` — for example, a line with `quantity` 10 and `freeQuantity` 2 means 12 units are delivered in total, 2 of which are free of charge.
## Transport Label (SSCC Labels)
New read-only field `transportLabel` on transport units for Shipping Notice and Dispatch Instruction Response, returned by `GET /v2/transactions`. It contains `zplUrl` and `pdfUrl` — links to the generated SSCC transport label in ZPL and PDF format. The field is populated by Procuros and is not accepted on input.
## Automatic Cleanup of Outdated Document Versions
When a new version of a document is detected, any older version that is still waiting to be collected is now automatically removed from the pending queue. This means `GET /v2/transactions` will only ever return the latest version of a document — you no longer need to check `isLatestVersion` when processing pending transactions, though it remains available for completeness.
See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Document Versioning
New fields on `Transaction` and `ReceivedTransaction` schemas: `replacesProcurosTransactionId`, `replacedByProcurosTransactionId`, and `isLatestVersion` — allowing you to detect superseded documents and trace version chains.
New guide: [Document Versioning](/en/api/v2/features-document-versioning) — explains how Procuros links old and new versions of the same document. All receiving guides have been updated with versioning information.
## Order Identifier on Shipping Notice Line Items
New field `orderIdentifier` added to shipping notice line items, allowing you to trace each line back to its originating order.
## Technical Sender Party
New party `technicalSender` added to all document types. This identifies the system or party that technically transmitted the document, which may differ from the commercial sender.
## Relaxed Ship-To Identifier Requirements
Identifier fields on the `shipTo` party are no longer required, giving more flexibility when the shipping destination does not carry a formal identifier.
## Receival Notice
Added receival notice documentation. See [Sending Receival Notices](/en/api/v2/sending-receival-notices).
## Pricing Unit Fields on Orders
New fields `pricingUnitQuantity` and `pricingUnitOfMeasure` added to order line items, supporting scenarios where the pricing unit differs from the ordering unit.
## Order Response Documentation
Added order response pages for both [Sending](/en/api/v2/sending-order-responses) and [Receiving](/en/api/v2/receiving-order-responses).
# Batches & Best Before Dates
Source: https://docs.procuros.io/en/api/v2/features-batches-best-before-dates
Most food products have a limited shelf life which needs to be tracked by both supplier and buyer. Therefore, the connector needs to be able to report batch identification and best-before dates on every outbound shipping notice.
## Rules
1. Per line item, one or more batches including best-before date can be returned
## Example
```json json theme={null}
"items": [
{
"lineNumber": 1,
"orderLineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"orderedQuantity": 20,
"shippedQuantity": 20,
"description": "First product description.",
"batches":
[
{
"batchIdentifier": "BATCH_ID_1",
"expirationDate": "2022-12-24",
"quantity": 15.0
},
{
"batchIdentifier": "BATCH_ID_2",
"expirationDate": "2022-12-31",
"quantity": 5.0
}
]
}
]
```
# Bottle Deposits
Source: https://docs.procuros.io/en/api/v2/features-bottle-deposits
Bottle deposit (German: Pfand) applies to products sold in certain single-use or multi-use containers. Buyers will not specifically order bottle deposit items but require bottle deposits as separate line items on invoices. Connectors will therefore be able to handle bottle deposits according to the following rules:
## Rules
1. Per order line item of a product that is subject to bottle deposit, the connector ensures that a second “deposit order line” containing the bottle deposit is added immediately following the original order line.
2. The deposit product used for the “deposit order line” must:
1. Have its own valid EAN/GTIN code
2. Correspond directly to 1 unit of the product ordered. That means, if single PET bottles are ordered, the deposit product (at the time of writing) would be 0.25€ but if full crates of mineral water are ordered, the deposit product (at the time of writing) would be 3.30€ (1.50€ for the crate + 12\*0.15€ for the bottles)
3. The “deposit order line” has to have the exact same quantity as the original order line.
## Examples
Below, you can see how to use bottle deposits when sending orders or invoices.
### Sending Orders
```json json theme={null}
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l"
},
{
"lineNumber": 2,
"identifiers": [...],
"isDepositItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Bottle Deposit PET",
"unitPrice": 0.12
}
]
```
### Sending Invoices
For invoices, bottle deposits can also be added as sub items for grouping purposes.
```json json theme={null}
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": false,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l",
"unitPrice": 0,
"subItems": [
{
"lineNumber": 2,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Water PET-Bottle 1l",
"unitPrice": 0.84,
"tax": {
"amount": 0.16,
"percentage": 19
}
},
{
"lineNumber": 3,
"identifiers": [...],
"isDepositItem": true,
"isInvoicedItem": true,
"quantity": 20,
"unitOfMeasure": "EA",
"description": "Bottle Deposit PET",
"unitPrice": 0.12,
"tax": {
"amount": 0.03,
"percentage": 19
}
}
]
}
]
```
# Document Versioning
Source: https://docs.procuros.io/en/api/v2/features-document-versioning
Trade partners sometimes send updated versions of a document they already sent — for example, a revised order with a changed quantity or an amended invoice. Procuros detects these and links the old and new versions together automatically.
Every transaction returned by the API includes three fields that tell you where it sits in that version chain:
| Field | Type | Description |
| - | - | - |
| `isLatestVersion` | `boolean` | `true` if no newer version exists. `false` if this document has been superseded. |
| `replacesProcurosTransactionId` | `uuid \| null` | The ID of the older transaction this one replaces. `null` if this is the original document. |
| `replacedByProcurosTransactionId` | `uuid \| null` | The ID of the newer transaction that replaced this one. `null` if this is still the current version. |
## Recommended Handling
**Always check `isLatestVersion` before importing a document into your system.** If the value is `false`, a newer version of the document is already available and the one you are looking at should be skipped or voided.
```php php theme={null}
foreach ($body->items as $transaction) {
if (!$transaction->isLatestVersion) {
// A newer version exists — skip or void this document
continue;
}
// Safe to import
importTransaction($transaction);
}
```
If `isLatestVersion` is `false` and the document was already imported, you can use `replacedByProcurosTransactionId` to identify the newer version. The newer version will also appear as a separate pending transaction on `GET /v2/transactions`, so no additional API call is needed — simply skip the outdated document and process the newer one when it comes up.
```php php theme={null}
if (!$transaction->isLatestVersion) {
// A newer version will arrive (or has already arrived) as its own pending transaction.
// Skip this outdated document, or void it if it was already imported.
continue;
}
```
### Marking outdated versions as processed
When you mark a transaction as processed, Procuros records that you have acknowledged it. If a transaction in your queue turns out to have `isLatestVersion: false`, you do not need to take any special action — Procuros automatically removes outdated versions from the pending queue before they are returned to you. You will only ever need to mark the latest version as processed.
## Version Chain Example
Given three versions of the same order:
| `procurosTransactionId` | `replacesProcurosTransactionId` | `replacedByProcurosTransactionId` | `isLatestVersion` |
| - | - | - | - |
| `aaa-111` | `null` | `bbb-222` | `false` |
| `bbb-222` | `aaa-111` | `ccc-333` | `false` |
| `ccc-333` | `bbb-222` | `null` | `true` |
Only `ccc-333` should be imported. The earlier versions can be safely skipped or voided.
When polling via `GET /v2/transactions` (pending transactions), outdated versions are removed from the queue automatically as soon as a newer version is detected. `isLatestVersion` will always be `true` for transactions returned by this endpoint.
# Enabled Trade Partners
Source: https://docs.procuros.io/en/api/v2/features-enabled-trade-partners
In order to know which outgoing documents to send via Procuros, a list of **enabled** Trade Partners needs to be maintained. Usually, this is done by either creating a “customer/supplier group” named “via Procuros” or by using custom fields on customers/suppliers marking them as “via Procuros”.
**ALL** outgoing document for an **enabled** Trade Partner should be sent via Procuros once it reaches the status that permits transmission. Procuros will determine whether the receiving enabled Trade Partner can and should receive the document. You will not need to handle this complexity on your end.
# Invoice Modifications
Source: https://docs.procuros.io/en/api/v2/features-invoice-modifications
Invoice modifications can be used to add additional charges or allowances (discounts) to line items or entire documents. For example, you might want to add a handling fee for large items or provide a volume discount for large orders. Modifications can be either absolute (e.g. 5€ handling fee) or relative (e.g. 10% volume discount).
Individual modifications are organised in modification groups. Each modification group **must** have a `level` which determines which modification group is applied first. Furthermore, modification groups contain a `basis` attribute. The basis is used to calculate absolute values for relative modifications, e.g. a relative modification of 10% on a basis of 500€ would result in a 50€ modification.
Modifications on item-level are applied to the subtotal (`quantity` \* `unitPrice`) of the item. Document-level modifications are on the other hand applied to the `subtotalAmount` of the invoice.
## Rules
1. Per line item, one or more modifications can be added
2. Per invoice, one or more modifications can be added
3. No modification group should have the same `level` attribute, unless they are on different items or on the document
4. It is only necessary to send taxes on modifications for absolute charges
**Generally for all modifications (discounts or surcharges):**
Relative (%) does not need tax info (will be distributed equally to all line-items). Example: cash discount, EZHG, partner portal, logistics discount, etc.
**Absolute (€) needs for:**
* **Discounts:** no tax info (will be distributed evenly on all line-items). Example: Credit, Coupon, etc.
* **Surcharge:** needs tax info (because comparable to an independent line-item). Example: shipping costs, minimum quantity surcharge, packaging surcharge, etc.
## Examples
### Single charge on document-level
An invoice with an additional 5€ (net) shipping charge on document-level.
```json json theme={null}
{
"header": {...},
"items": [...],
"summary": {
"subtotalAmount": 100,
"totalCharges": 5,
"totalAllowances": 0,
"netAmount": 105,
"grossAmount": 124.95,
"dueAmount": 124.95,
"tax": {...},
"modificationGroups": [
{
"level": 1,
"basis": 100,
"modifications": [
{
"type": "CHARGE",
"reasonCode": "SHIPPING",
"amount": 5,
"tax": {
"amount": 0.95,
"percentage": 19,
"description": "Umsatzsteuer"
}
}
]
}
]
}
}
```
### Multiple modifications on item- and document-level
A more complex scenario with one modification on item-level and two modifications on document-level.
```json json theme={null}
{
"header": {...},
"items": [
{
"lineNumber": 1,
"identifiers": [...],
"isDepositItem": false,
"isInvoicedItem": false,
"quantity": 5,
"unitOfMeasure": "EA",
"description": "Large Item",
"unitPrice": 1000,
"tax": {
"amount": 190,
"percentage": 19,
"description": "Umsatzsteuer"
},
"modificationGroups": [
{
"level": 1,
"basis": 5000,
"modifications": [
{
"type": "ALLOWANCE",
"reasonCode": "DISCOUNT",
"amount": 500
}
]
}
]
}
],
"summary": {
"subtotalAmount": 4500,
"totalCharges": 50,
"totalAllowances": 455,
"netAmount": 4095,
"grossAmount": 4873.05,
"dueAmount": 4873.05,
"tax": {...},
"modificationGroups": [
{
"level": 1,
"basis": 4500,
"modifications": [
{
"type": "CHARGE",
"reasonCode": "SHIPPING",
"amount": 50,
"tax": {
"amount": 9.5,
"percentage": 19,
"description": "Umsatzsteuer"
}
}
]
},
{
"level": 2,
"basis": 4550,
"modifications": [
{
"type": "ALLOWANCE",
"reasonCode": "DISCOUNT",
"percentage": 10,
"description": "Loyal Customer Discount"
}
]
}
]
}
}
```
**Explanation:** First, the modifications on item-level are applied. Since item-level modifications are applied to the subtotal (`quantity` \* `unitPrice`) of the item, the `subtotalAmount` of the invoice is 4.500€. Next, the document-level modifications are applied. For the modification with `level = 1`, we apply the charge to the `subtotalAmount` of the invoice. Thus, the subtotal (without taxes) is 4.500€+50€ after applying the first modification. Finally, we apply the second modification (`level = 2`) to the new subtotal and end up with an invoice `netAmount` of 4.095€.
# Package Identification
Source: https://docs.procuros.io/en/api/v2/features-package-identification
More and more trade partners require shipments to be marked externally with barcodes digitally linking them to shipping notices and thus enabling a far easier and faster goods receival processes.
In this case, shipping notices must include a “shipment hierarchy” that identifies every transport unit (pallet, carton, etc.) using a unique transport unit identifier. The identification system used is usually SSCC (Serial Shipment Container Code)
## Examples
Below, you can see how to build the “shipment hierarchy” for different shipment scenarios.
### Single package
A single package will have a transport label printed on the physical package and list a single transport unit in digital form.
**Physical**
Single SSCC on package
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
}
]
}
```
### Multiple packages
A shipment with multiple package will have a transport label printed on every package and one transport unit listed per package in digital form.
**Physical**
One SSCC on every package
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
},
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "CARTON",
"items": [...] // line items contained in package
}
]
}
```
### Single pallet (homogeneous or mixed content)
A shipment that consists of a single pallet will have a single transport label printed on the pallet shrink wrap. In digital form, a single transport unit is listed and the amount of cartons on the pallet is communicated via the `containedTradeUnitCount` parameter.
**Physical**
Single SSCC on pallet
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 12, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
```
### Sandwich pallet (homogenous pallets stacked)
A pallet that is made up of multiple homogeneous “layers” (sandwich pallet) receives N+1 transport labels. One label on the shirk wrap of the whole stacked pallet and one label per layer. The same is true for the digital form: Transport units describing the different “layers” are contained within a wrapping transport unit describing the whole stacked pallet.
**Physical**
One SSCC on the shrink wrap of the stacked pallet
One SSCC on each sandwich layer
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"transportUnits": [ // further transport units contained within
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 12, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 6, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365379",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 24, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
]
}
```
### Multiple pallets (homogeneous or mixed content)
Shipments that consist of multiple pallets of either homogeneous or mixed content are handled similar to multiple packages. One transport label is attached to every physical pallet and in digital form one transport unit is used for every pallet.
**Physical**
One SSCC on every pallet
**Digital**
```json json theme={null}
{
"transportUnits": [
{
"unitIdentifier": "340000000037365376",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365377",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
},
{
"unitIdentifier": "340000000037365378",
"unitIdentiferDomain": "GS1",
"unitType": "EURO_PALLET",
"containedTradeUnitCount": 96, // Amount of cartons on the pallet
"items": [...] // line items contained in packages on the pallet
}
]
}
```
### Other scenarios
Please contact us if you are unsure or require different scenarios (containers, etc.).
# Product Identification
Source: https://docs.procuros.io/en/api/v2/features-product-identification
Based on various identification data, a product can reliably be identified within the ERP system.
## Identification Data
* EAN/GTIN: Barcode data. (optional but present in 99% of retail use cases)
* Buyer part number: A product ID assigned by the buyer. (optional, used only if EAN/GTIN are not provided)
* Supplier part number: A product ID assigned by the supplier. (optional, used only if EAN/GTIN are not provided)
## Rules
1. Products must be uniquely identified. If multiple products within the ERP system match the provided identification data, an error must be reported to Procuros.
# Taxes (VAT)
Source: https://docs.procuros.io/en/api/v2/features-taxes-vat
## Receiving Taxes
Taxes (mainly VAT) should be handled properly. As pricing and tax data is almost never supplied by the buyer on incoming orders, you need to resolve the correct tax rate that applies to the specific document from the ERP system.
### Rules
1. If the ERP system does not automatically apply correct tax rates when you import a transaction pulled from Procuros, you will need to determine the correct rate yourself the same way the ERP system does when users manually add orders into the system.
***
## Sending Taxes
Each line item of an invoice contains the following information, detailing tax percentage, amount, the VAT category, and a description of why the tax was applied.
```json json theme={null}
"tax": {
"percentage": 19,
"amount": 7.50,
"category": "VAT",
"description": "Total Tax"
}
```
This is how an item that is tax free is represented:
```json json theme={null}
"tax": {
"percentage": 0,
"amount": 0,
"category": "ZERO_RATED",
"description": "Tax free"
}
```
### VAT categories
`category` states how the amount is treated for VAT. Use one of the following:
| Category | Use it for |
| - | - |
| `VAT` | A normal taxed amount, at either the standard or a reduced rate. |
| `ZERO_RATED` | Goods taxed at zero percent. |
| `EXEMPT` | Amounts exempt from VAT. |
| `VAT_REVERSE_CHARGE` | The buyer accounts for the VAT instead of the supplier. |
| `VAT_INTRA_COMMUNITY` | A supply to another EU member state. |
| `VAT_EXPORT` | A supply to a country outside the EU. |
| `VAT_OUT_OF_SCOPE` | Amounts not subject to VAT at all. |
Several countries require the category, and an exemption reason alongside it, on an electronic invoice.
The same `category` is available on each entry of the document-level `summary.tax.items` array.
### Rules
1. Each line item in an invoice must have a `tax` attribute provided in the payload. You will need to determine this tax rate, amount, category, and description from the ERP system.
2. When the category is one of the exempt or zero-rated values, put the reason the exemption applies in the `description` of the matching `summary.tax.items` entry. Several countries require that reason to appear on the invoice.
# Tracking Document Status
Source: https://docs.procuros.io/en/api/v2/features-tracking-document-status
Once an outgoing document is being sent to the Trade Partner through the Procuros API, it should be marked for two reasons:
1. To make sure it is not sent again
2. To give users transparency regarding the status of their documents
Most ERP systems have some way to attach information to documents. If the ERP system you are building a connector for does not support this, please get in touch with us to find an alternative solution.
These data fields should be made available on all outgoing documents:
## Rules
* If Procuros accepted the transaction and intends to forward it to the receiving Trade Partner, it will respond with a `201: Created` status code. In this case, the document **Status** field should be set to `TRANSMITTED`.
* If Procuros accepted the transaction but does not intend to forward it to the receiving Trade Partner, it will respond with a `202: Accepted` status code. In this case, the document **Status** field should be set to `NO_ACTION`. The response will also include a `procurosTransactionId` that can be used as a reference for support or tracking purposes. Possible reasons for Procuros not to forward documents:
1. The trade relationship between the sender (you) and the receiving trade partner is not (yet) active.
2. The receiving trade partner is (currently) not accepting documents of this type
* If Procuros did NOT accept the transaction, it will respond with either a `422: Validation Error` or a `400: Bad Request` status code.
In this case, the document **Status** field should **NOT** be set to make sure the document will be retried the next time you are processing outgoing transactions. The response from Procuros will contain a link to view the error on the Procuros Portal. You can optionally add this link to a "**Error URL**" field attached to the document you were trying to send, giving users easy access to view and resolve errors.
* Only documents that have an empty **Status** field should be retrieved from the ERP for sending via Procuros.
## Retrying Documents
If a document has failed to send to Procuros, as per the rules above it should not be marked with one of these statuses: `TRANSMITTED` or `NO_ACTION`.
You should instead retry the document until it is able to be handled by Procuros. This should occur by the ERP administrators making changes to the document to resolve why it was not valid.
This is why you must [report any errors](/en/api/v2/concept-error-handling) documents have via the API, in order for Procuros to notify the customer.
### Caveats
* Depending on your use case, if you are polling for data very often, you may not want to send a document error every time you poll for data. Instead, you may want to send an error only after a certain number of retries. This is up to you to decide.
# Trade Partner + Party Identification
Source: https://docs.procuros.io/en/api/v2/features-trade-partner-party-identification
## Definition of Terms
**Trade Partner** A terms referring to either a customer or a supplier.
**Party** An entity attached to a trade partner. Example: Ship-To parties are entities receiving deliveries for a trade partner. Bill-To parties are entities receiving invoices.
## Description
Based on the GLN data contained within incoming transactions, a trade partner (customer/supplier) as well as Ship-To (delivery) and Bill-To (billing) parties on that trade partner should reliably be identified within the ERP system.
## Identifiers
* Buyer GLN
* Ship-To GLN (optional, fallback to Buyer GLN if not provided)
* Bill-To GLN (optional, fallback to Buyer GLN if not provided)
## Rules
1. All provided GLN information **MUST** be used and match parties on the same trade partner, meaning no fallbacks to standard settings such as a “standard delivery party” as known to the ERP system are allowed!
**Example 1**: A trade partner can be identified based on the provided Buyer and Bill-To GLN but a delivery party cannot be found using the provided Ship-To GLN on this trade partner. In this case, the corresponding transaction should not be processed and instead an error needs to be reported.
**Example 2**: Buyer GLN and Bill-To GLN on the order are different. A trade partner was uniquely identified using the Bill-To GLN but the Buyer GLN does not appear on the trade partner or one of it’s billing parties. In this case, the corresponding transaction should not be processed and instead an error needs to be reported.
2. If no Ship-To or Bill-To GLN are provided, they are to be considered equal to the mandatory Buyer GLN and transactions should be processed accordingly.
## Implementation Checklist
* ✅ Trade partner can be identified using only the Buyer GLN
* ✅ Trade partner can be identified using Buyer, Ship-To and Bill-To GLN
* ✅ Trade partner identification fails, if ANY of the provided GLNs don't match a party on the same trade partner
# Bulk Mark Transactions Processed
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/bulk-mark-transactions-processed
/en/api/v2/openapi-v2.yaml post /v2/transactions/bulk/mark-processed
Mark a list of incoming transactions as processed in a single request.
For each item, set `success` to `true` once the transaction has been processed, or `false` if processing failed (optionally with an `errorReason`, `errorType`, and `errorContext`).
Transactions previously reported as failed can be recovered by including them again with `success: true` once the issue has been resolved on your side. They move to the delivered state and their associated errors are resolved automatically.
# List Incoming Transactions
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/list-incoming-transactions
/en/api/v2/openapi-v2.yaml get /v2/transactions
List unprocessed incoming transactions from your trade partners.
# Mark Transaction Processed
Source: https://docs.procuros.io/en/api/v2/incoming-transactions/mark-transaction-processed
/en/api/v2/openapi-v2.yaml put /v2/transactions/{procurosTransactionId}
Report whether your system processed an incoming transaction.
Set `success` to `true` once the transaction has been processed, or `false` if processing failed (optionally with an `errorReason`, `errorType`, and `errorContext`).
If a transaction was previously reported as failed, you can recover it by calling this endpoint again with `success: true` once the issue has been resolved on your side (for example, after correcting missing master data in your system). The payload is reused from your system, so there is no need to fetch the transaction again: it moves to the delivered state and its associated error is resolved automatically.
# Test connection to API
Source: https://docs.procuros.io/en/api/v2/misc/test-connection-to-api
/en/api/v2/openapi-v2.yaml get /v2/ping
Send an authorized request to the API to test the connectivity.
# Report Outgoing Error
Source: https://docs.procuros.io/en/api/v2/outgoing-transactions/report-outgoing-error
/en/api/v2/openapi-v2.yaml post /v2/errors
If you encounter an error while building an outgoing transaction payload, you can report it here. The error will enter the same exception handling process as an error reported while processing incoming transactions.
# Send Transaction
Source: https://docs.procuros.io/en/api/v2/outgoing-transactions/send-transaction
/en/api/v2/openapi-v2.yaml post /v2/transactions
Create and send a new transaction to one of your trade partners.
# Credit Notes
Source: https://docs.procuros.io/en/api/v2/receiving-credit-notes
This is the right section for you if you are acting as a customer and looking to receive credit notes from your suppliers.
In this guide you will learn how to receive new credit notes from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the credit notes.
It is important to mark the credit notes as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Credit Notes
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `CREDIT_NOTE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=CREDIT_NOTE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `CREDIT_NOTE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'CREDIT_NOTE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Credit Note as Processed
To mark an credit note as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Credit Notes as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Credit Note
In the event an credit note was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these credit notes as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the credit note not being processed, which will be used for solving the issue.
### Single Credit Note
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Dispatch Instruction Responses
Source: https://docs.procuros.io/en/api/v2/receiving-dispatch-instruction-responses
This is the right section for you if you are acting as a supplier and looking to receive dispatch instruction responses from a fulfillment provider.
In this guide you will learn how to receive new dispatch instruction responses from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the dispatch instruction responses.
It is important to mark the dispatch instruction responses as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Dispatch Instruction Responses
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `DISPATCH_INSTRUCTION_RESPONSE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=DISPATCH_INSTRUCTION_RESPONSE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `DISPATCH_INSTRUCTION_RESPONSE` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'INVOICE' || $item->type === 'DISPATCH_INSTRUCTION_RESPONSE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Dispatch Instruction Response as Processed
To mark an dispatch instruction response as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Dispatch Instruction Responses as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing Dispatch Instruction Response
In the event an dispatch instruction response was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these dispatch instruction responses as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the dispatch instruction response not being processed, which will be used for solving the issue.
### Single Dispatch Instruction Response
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Dispatch Instructions
Source: https://docs.procuros.io/en/api/v2/receiving-dispatch-instructions
This is the right section for you if you are acting as a fulfillment provider and looking to receive dispatch instructions from suppliers.
In this guide you will learn how to receive new dispatch instructions from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the dispatch instructions.
It is important to mark the dispatch instructions as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Dispatch Instructions
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `DISPATCH_INSTRUCTION`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=DISPATCH_INSTRUCTION', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `DISPATCH_INSTRUCTION` and `INVOICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'INVOICE' || $item->type === 'DISPATCH_INSTRUCTION';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Dispatch Instruction as Processed
To mark an dispatch instruction as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Dispatch Instructions as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => true
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing Dispatch Instruction
In the event an dispatch instruction was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these dispatch instructions as "failed to process".
In this case you must set the `hasBeenProcessed` flag to `false`. Additionally you should (but are not required to) add a `reason` for the dispatch instruction not being processed, which will be used for solving the issue.
### Single Dispatch Instruction
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'hasBeenProcessed' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'hasBeenProcessed' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Invoices
Source: https://docs.procuros.io/en/api/v2/receiving-invoices
This is the right section for you if you are acting as a customer and looking to receive invoices from your suppliers.
In this guide you will learn how to receive new invoices from the Procuros API, as well as how to paginate over them, mark them as processed, or report any errors with the invoices.
It is important to mark the invoices as processed (either successfully or not) so that the Procuros network can communicate this to your trade partners. This will also prevent them from re-appearing in future `GET` requests for transactions data, as well as trigger the error management process in case you mark any documents as errors.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
Trade partners may send updated versions of a document. Always check the `isLatestVersion` field before importing — if it is `false`, a newer version exists and this one should be skipped. See [Document Versioning](/en/api/v2/features-document-versioning) for full details.
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Pull New Invoices
The API call [List incoming Transactions](/en/api/v2/incoming-transactions/list-incoming-transactions) is used to fetch all incoming transactions.
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
request('GET', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
$body = json_decode((string) $response->getBody());
$items = $body->items;
```
### Loading Different Document Types
**Scenario 1:** You only want to load a specific document type, e.g. `INVOICE`.
In this case, the easiest way to acheive the filtering is to add the `filter` parameter to the request.
```php php theme={null}
$response = $client->request('GET', 'https://api.procuros.io/v2/transactions?filter[type]=INVOICE', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
```
**Scenario 2:** You want to load multiple document types, e.g. `INVOICE` and `SHIPPING_NOTICE`.
In this case, you may want to load all document types and then filter them in your code, preventing multiple round-trip requests the API. You can filter the results by `type` of each returned item to get the documents you need.
```php php theme={null}
$transactions = array_filter($items, function($item) {
return $item->type === 'SHIPPING_NOTICE' || $item->type === 'INVOICE';
});
```
### Pagination
The response body has a `hasMore` flag. If it's `true` not all items are in the response.
You will then want to fetch the other items as well. Therefore, you can use the `nextPageUrl` flag from the response body and perform the same request with the new URL again.
```php php theme={null}
if ($body->hasMore) {
$response = $client->request('GET', $body->nextPageUrl, [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
]);
... // don't forget to check for errors
$body = json_decode((string) $response->getBody());
$items = array_merge($items, $body->items);
}
```
If you are running your code only once a day or so, we recommend to perform the request with the new URL until `hasMore` is false. When doing so you can be sure to fetch all currently available items.
Please read the [Pagination](/en/api/v2/concept-pagination) section of our API reference for a detailed description.
## Mark an Invoice as Processed
To mark an invoice as processed, use the API call [Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed).
On the happy path of a transaction being processed successfully, you can make an API call such as:
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$transaction_id = 'abc-123'; // Get the transaction ID from the original `GET /v2/transactions` call
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => true
]
]);
... // Remember to check the request was successful
```
### Mark Multiple Invoices as Processed
In addition to the above, you can specify a list of items that should be marked as processed in a single API call, via the [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed) endpoint.
```php php theme={null}
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
// You can find the IDs from the original `GET /v2/transactions` call
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => true
],
[
'procurosTransactionId' => 'def-456',
'success' => true
]
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
... // Remember to check if the request was successful
```
## Report an Error Processing an Invoice
In the event an invoice was not able to be processed, you can use the same 2 API calls listed above ([Mark transaction processed](/en/api/v2/incoming-transactions/mark-transaction-processed) and [Bulk mark transactions processed](/en/api/v2/incoming-transactions/bulk-mark-transactions-processed)) to mark these invoices as "failed to process".
In this case you must set the `success` flag to `false`. Additionally you should (but are not required to) add a `reason` for the invoice not being processed, which will be used for solving the issue.
### Single Invoice
```php php theme={null}
$transaction_id = 'abc-123';
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/{$transaction_id}", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'success' => false,
'reason' => 'Invalid address supplied'
]
]);
```
### Bulk Error Reporting
```php php theme={null}
$items = [
[
'procurosTransactionId' => 'abc-123',
'success' => false,
'reason' => 'Invalid address supplied'
],
[
'procurosTransactionId' => 'def-456',
'success' => true
],
];
$response = $client->request('POST', "https://api.procuros.io/v2/transactions/bulk/mark-processed", [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => [
'items' => $items
]
]);
```
# Credit Notes
Source: https://docs.procuros.io/en/api/v2/sending-credit-notes
This is the right section for you if you are acting as a supplier and looking to send credit notes to your customers.
Throughout this guide you will learn how to send new credit notes to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a credit note to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Credit Notes
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including credit notes.
The following fields are required:
* `type` (Transaction type. In this case `CREDIT_NOTE`)
* `content` (The details of the credit note.)
Inside the `content` you will need to build all credit note items. All details can be found in the `CREDIT_NOTE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'CREDIT_NOTE',
'content' => [
'header' => [
'buyer' => [
'identifiers' => [
[
'identifier' => '3220010000001',
'domain' => 'GS1',
],
],
],
'supplier' => [
'identifiers' => [
[
'identifier' => '3220010000004',
'domain' => 'GS1',
],
],
],
'type' => 'CORRECTION',
'creditNoteIdentifier' => 'valid-credit-note-identifier-1',
'creditNoteDate' => '2022-05-09',
'creditNoteValueDate' => '2022-05-10',
'reason' => 'valid-credit-note-reason-1',
'invoiceIdentifier' => 'valid-invoice-identifier-1',
'invoiceDate' => '2022-05-09',
'shippingNoticeIdentifier' => 'valid-credit-note-shipment-identifier-1',
'shippingNoticeDate' => '2022-05-07',
'orderIdentifier' => 'valid-credit-note-order-identifier-1',
'orderDate' => '2022-05-01',
'paymentTerms' => [],
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
[
'identifier' => 'valid-invoice-item-identifier-1',
'domain' => 'GS1',
],
],
'isDepositItem' => false,
'quantity' => 10,
'unitPrice' => 4.5,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'amount' => 8.55,
'percentage' => 19,
],
],
[
'lineNumber' => 2,
'identifiers' => [
[
'identifier' => 'valid-invoice-item-identifier-2',
'domain' => 'GS1',
],
],
'isDepositItem' => true,
'quantity' => 10,
'unitPrice' => 4.5,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'amount' => 0,
'percentage' => 0,
],
],
],
'summary' => [
'subtotalAmount' => 90,
'grossAmount' => 98.55,
'netAmount' => 98.55,
'dueAmount' => 98.55,
'totalAmountWithoutTax' => 90,
'totalCharges' => 8.55,
'totalAllowances' => 0,
'tax' => [
'total' => 1,
'items' => [
[
'percentage' => 19,
'taxableAmount' => 44.5,
'taxAmount' => 8.5,
'category' => 'Mwst.',
'description' => 'Mehrwertsteuer',
]
],
'description' => 'Tax Summary',
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Dispatch Instruction Responses
Source: https://docs.procuros.io/en/api/v2/sending-dispatch-instruction-responses
This is the right section for you if you are acting as a fulfillment provider and looking to send dispatch instruction responses to a supplier.
Throughout this guide you will learn how to send new dispatch instruction responses to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a dispatch instruction response to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Dispatch Instruction Responses
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including dispatch instruction responses.
The following fields are required:
* `type` (Transaction type. In this case `DISPATCH_INSTRUCTION_RESPONSE`)
* `content` (The details of the dispatch instruction response.)
Inside the `content` you will need to build all dispatch instruction response items. All details can be found in the `DISPATCH_INSTRUCTION_RESPONSE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"DISPATCH_INSTRUCTION_RESPONSE",
"content" => [
"header" => [
"orderId" => null,
"orderDate" => null,
"shipmentId" => "48148",
"shippingNoticeIdentifier" => "SHIPMENT-123",
"shippingNoticeDate" => "2022-10-12T12:53:51.000000Z",
"dispatchInstructionResponseDate" => "2022-10-12T12:53:51.000000Z",
"responseDate" => "2022-10-12T12:53:51.000000Z",
"shipmentDate" => "2022-10-12T12:53:51.000000Z",
"requestedDeliveryDate" => "2022-10-11T22:00:00.000000Z",
"expectedDeliveryDate" => "2022-10-11T22:00:00.000000Z",
"shipFrom" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"shipTo" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"billTo" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"buyer" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"supplier" => [
"name" => "Foo GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "GS1",
],
],
"postalAddress" => [
"name" => "Foo",
"street" => "Musterstraße 123",
"addressExtra" => "1st Floor",
"city" => "Hamburg",
"postalCode" => "12345",
"state" => "HH",
"countryCode" => "DE",
],
"contacts" => [
[
"title" => "Dr.",
"salutation" => "Herr",
"firstName" => "Max",
"lastName" => "Muster",
"phone" => "+49 12345",
"mobile" => "+49 12345",
"email" => "[email protected]",
"fax" => "+49 12345",
],
],
],
"technicalRecipient" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "3220010000006",
],
],
],
"technicalSender" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "3220010000007",
],
],
],
"comments" => null,
],
"transportUnits" => [
[
"unitIdentifier" => "342601560208144493",
"unitType" => null,
"containedTradeUnitCount" => null,
"carrier" => [
"name" => "DHL Express",
"trackingNumber" => "00340434611510850247",
"trackingUrl" => "https://www.dhl.com/track?AWB=00340434611510850247",
],
"items" => [
[
"lineNumber" => 4,
"shippingNoticeLineNumber" => 1,
"shippedQuantity" => 1,
"orderedQuantity" => 1,
"isDepositItem" => false,
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "abc",
],
],
"unitOfMeasure" => "EA",
"unitPrice" => null,
"currency" => null,
"description" => "",
"batches" => [
[
"batchIdentifier" => "abc",
"expirationDate" => "2022-12-31",
"quantity" => 30,
],
],
"parentLineNumber" => null,
"openQuantityAction" => null,
],
],
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Dispatch Instructions
Source: https://docs.procuros.io/en/api/v2/sending-dispatch-instructions
This is the right section for you if you are acting as a supplier and looking to send dispatch instructions to your fulfillment provider.
Throughout this guide you will learn how to send new dispatch instructions to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a dispatch instruction to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Dispatch Instructions
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including dispatch instructions.
The following fields are required:
* `type` (Transaction type. In this case `DISPATCH_INSTRUCTION`)
* `content` (The details of the dispatch instruction.)
Inside the `content` you will need to build all dispatch instruction items. All details can be found in the `DISPATCH_INSTRUCTION` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"DISPATCH_INSTRUCTION",
"content" => [
"header" => [
"orderIdentifier" => "valid-order-id",
"orderDate" => "2023-06-01",
"shipmentIdentifier" => "valid-dispatch-instruction-shipment-id-1",
"noticeDate" => "2023-06-01",
"requestedDeliveryDate" => "2023-06-05",
"customer" => [
"addressId" => "valid-dispatch-instruction-customer-1",
"identifiers" => [
[
"identifier" => "3220010000001",
"domain" => "GS1",
],
],
],
"supplier" => [
"addressId" => "valid-dispatch-instruction-supplier-1",
"identifiers" => [
[
"identifier" => "3220010000002",
"domain" => "GS1",
],
],
],
"shipFrom" => [
"addressId" => "valid-dispatch-instruction-shipFrom-1",
"identifiers" => [
[
"identifier" => "3220010000003",
"domain" => "GS1",
],
],
],
],
"items" => [
[
"orderLineNumber" => 1,
"shippingNoticeLineNumber" => 1,
"shippedQuantity" => 1,
"orderedQuantity" => 1,
"openQuantityAction" => "DISCARDED",
"unitOfMeasure" => "EA",
"identifiers" => [
[
"identifier" => "valid-dispatch-instruction-identifier-1",
"domain" => "GS1",
],
],
],
],
],
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Inventory Reports
Source: https://docs.procuros.io/en/api/v2/sending-inventory-reports
This is the right section for you if you are acting as a fulfilment provider and looking to send inventory reports to your customers.
Throughout this guide you will learn how to send inventory reports to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an inventory report to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send inventory reports
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including inventory reports.
The following fields are required:
* `type` (Transaction type. In this case `INVENTORY_REPORT`)
* `content` (The details of the inventory report items.)
Inside the `content` you will need to build all inventory report items. All details can be found in the `INVENTORY_REPORT` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"INVENTORY_REPORT",
"content" => [
"header" => [
"warehouse" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Test Sender GmbH",
"street" => "Musterstraße 1",
"addressExtra" => "c/o Max Mustermann",
"city" => "Entenhausen",
"postalCode" => "123456",
"countryCode" => "DE"
],
"name" => "Test Sender GmbH"
],
"goodsOwner" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Test Receiver GmbH",
"street" => "Lilienstraße 36",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
],
"name" => "Test Receiver GmbH"
],
"inventoryReportIdentifier" => "Summer 2025",
"inventoryReportDate" => "2024-06-01"
],
"items" => [
[
"unitOfMeasure" => "EA",
"identity" => [
"senderPartnerId" => "PRD-0001",
"receiverPartnerId" => "AB-MM-9988",
"gtin" => "12345678901234",
],
"lineNumber" => 12,
"availableQuantity" => 5,
"unitPrice" => 44.23,
"pricingUnitOfMeasure" => "CT",
"pricingUnitQuantity" => 100,
"name" => "Name of the product",
"hsCode" => "222222",
"originCountryCode" => "US"
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Invoices
Source: https://docs.procuros.io/en/api/v2/sending-invoices
This is the right section for you if you are acting as a supplier and looking to send invoices to your customers.
Throughout this guide you will learn how to send invoices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an invoice to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
1. If products being invoiced are subject to bottle deposit, add additional line items for bottle deposit (see: [Bottle Deposits](/en/api/v2/features-bottle-deposits))
2. Make sure taxes (mainly VAT) are correctly added to line items (see: [Taxes (VAT)](/en/api/v2/features-taxes-vat))
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Invoices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including invoices.
The following fields are required:
* `type` (Transaction type. In this case `INVOICE`)
* `content` (The details of the invoice items.)
Inside the `content` you will need to build all invoice items. All details can be found in the `INVOICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
The example below covers a single shipping notice, so its `shippingNoticeIdentifier` and `shippingNoticeDate` are shared in the header. For an invoice covering multiple shipping notices, omit both header fields and provide them on each item instead; optionally add `shippingNoticeLineNumber` to each item.
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'INVOICE',
'content' => [
'header' => [
'invoiceIdentifier' => 'API-INV-2022-08-31-001',
'invoiceDate' => '2022-08-31',
'invoiceValueDate' => '2022-09-01',
'shippingNoticeIdentifier' => 'SFTP-SHIP-2022-08-31-001',
'shippingNoticeDate' => '2022-08-31',
'orderIdentifier' => 'SFTP-2022-08-31-001',
'orderDate' => '2022-08-31',
'requestedDeliveryDate' => '2022-08-31',
'expectedDeliveryDate' => '2022-08-31',
'paymentTerms' => [
[
'payInNumberOfDays' => 30,
'percentage' => 0
]
],
'supplier' => [
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => 'C10000'
]
]
],
'buyer' => [
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => 'C20000'
]
]
]
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
[
'domain' => 'GS1',
'identifier' => '2330010000019'
]
],
'isDepositItem' => false,
'quantity' => 10,
'unitPrice' => 10,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'tax' => [
'percentage' => 19,
'amount' => 1.9,
'category' => 'VAT',
'description' => 'MwSt. 19%'
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
## Advanced Use Cases
When it comes to sending invoices, there are a number of advanced cases, such as [Invoice Modifications](/en/api/v2/features-invoice-modifications).
Please see the Features section of our API reference for a detailed description of all advanced use cases.
# Order Responses
Source: https://docs.procuros.io/en/api/v2/sending-order-responses
This is the right section for you if you are acting as a supplier and looking to send Order Responses to your customers in response to their orders.
Throughout this guide you will learn how to send Order Responses to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Order Response Types
Order Responses can have one of three types:
* **ACCEPT**: Use when the order is accepted exactly as ordered. The `items` array is optional — omit it to confirm all lines as-is, or include it to selectively confirm specific items with adjusted quantities or dates.
* **REJECT**: Use when the order is fully rejected. The `items` array must not be included.
* **CHANGE**: Use when part of the order is accepted but either line item quantities or delivery date are changed. The `items` array is required and must contain ALL order line items.
Omitting `type` (or setting it to `null`) is treated identically to `REJECT` — the `items` array is prohibited and the order is considered fully rejected. Always provide an explicit `type` to avoid unintended rejections.
## Process
These are usually the steps taken when sending an Order Response to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Order Responses
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including Order Responses.
The following fields are required:
* `type` (Transaction type. In this case `ORDER_RESPONSE`)
* `content` (The details of the Order Response)
Inside the `content` you will need to build the Order Response header and optionally items. All details can be found in the `ORDER_RESPONSE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
### Example: ACCEPT Response
Use this when accepting an order exactly as ordered:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'ACCEPT',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'requestedDeliveryDate' => '2024-01-20',
'confirmedDeliveryDate' => '2024-01-20',
'confirmedShipmentDate' => '2024-01-18',
'currency' => 'EUR'
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
### Example: REJECT Response
Use this when fully rejecting an order:
```php php theme={null}
$transaction = [
'type' => 'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'REJECT',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'currency' => 'EUR',
'comments' => 'Order rejected due to product unavailability'
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
### Example: CHANGE Response
Use this when partially accepting an order with quantity or delivery date changes. The items array must contain ALL order line items, showing both ordered and confirmed quantities:
```php php theme={null}
$transaction = [
'type' => 'ORDER_RESPONSE',
'content' => [
'header' => [
'type' => 'CHANGE',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016310']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '1100001016312']
]
],
'orderResponseIdentifier' => 'RE-PO9383-R45',
'orderResponseDate' => '2024-01-15',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2024-01-14',
'requestedDeliveryDate' => '2024-01-20',
'confirmedDeliveryDate' => '2024-01-22',
'confirmedShipmentDate' => '2024-01-20',
'currency' => 'EUR',
'comments' => 'Partial fulfillment due to limited stock'
],
'items' => [
[
'lineNumber' => 1,
'identifiers' => [
['domain' => 'GS1', 'identifier' => '4300348765432']
],
'isDepositItem' => false,
'orderedQuantity' => 20.0,
'confirmedQuantity' => 15.0,
'unitOfMeasure' => 'EA',
'description' => 'First product description',
'unitPrice' => 0.15,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100
],
[
'lineNumber' => 2,
'identifiers' => [
['domain' => 'GS1', 'identifier' => '4300348765433']
],
'isDepositItem' => false,
'orderedQuantity' => 19.0,
'confirmedQuantity' => 19.0,
'unitOfMeasure' => 'EA',
'description' => 'Second product description',
'unitPrice' => 1.50,
'pricingUnitOfMeasure' => 'CT'
'pricingUnitQuantity' => 100,
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
When using the `CHANGE` type, the `items` array must contain ALL order line items, regardless of whether `orderedQuantity` and `confirmedQuantity` are equal. This allows the buyer to see the complete picture of what will be delivered.
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Orders
Source: https://docs.procuros.io/en/api/v2/sending-orders
This is the right section for you if you are acting as a customer and looking to send orders to your suppliers.
Throughout this guide you will learn how to send new orders to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an order to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Orders
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including orders.
The following fields are required:
* `type` (Transaction type. In this case `ORDER`)
* `content` (The details of the order items.)
Inside the `content` you will need to build all order items. All details can be found in the `ORDER` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
The example below shows commonly used fields. The Order schema supports many additional optional fields including:
* **Header level**: `deliveryInformation`, `purchasingInformation`, `legalInformation`, `attachments`, `finalRecipient` party, `technicalRecipient` party, `technicalSender` party
* **Item level**: `size`, `dimension`, `hsCode`, `cnCode`, `colorCode`, `colorName`, `fscNumber`, `deliveryGracePeriodInDays`, `certificationsRequired`, `attachments`
**Date format**: All date fields (e.g. `orderDate`, `requestedDeliveryDate`) must use ISO 8601 format: `YYYY-MM-DD` (e.g. `2023-12-06`).
For the complete list of available fields, refer to the OpenAPI schema documentation.
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'ORDER',
'content' => [
'header' => [
'orderIdentifier' => 'bestellung-20231203-012',
'orderDate' => '2023-12-03',
'currency' => 'EUR',
'requestedDeliveryDate' => '2023-12-06',
'type' => 'STANDARD',
'comments' => 'Please deliver to loading dock 3',
'contractReference' => 'CONTRACT-2023-ABC',
'buyer' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'supplier' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000003']
]
],
'billTo' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'shipTo' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000011']
]
],
'technicalRecipient' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000010']
]
],
'technicalSender' => [
'identifiers' => [
['domain' => 'GS1', 'identifier' => '3220010000012']
]
],
'AdditionalOrderIdentifiers' => [
'supplierOrderIdentifier' => 'SUP-ORDER-789',
'shipToOrderIdentifier' => 'SHIP-REF-456'
],
'paymentTerms' => [
[
'payInNumberOfDays' => 30,
'percentage' => 5
]
]
],
'items' => [
[
'identifiers' => [
['domain' => 'GS1', 'identifier' => '2330000000083']
],
'lineNumber' => 1,
'quantity' => 10,
'isDepositItem' => false,
'unitOfMeasure' => 'EA',
'description' => 'Premium Organic Coffee Beans 1kg',
'comments' => 'Please handle with care - fragile packaging',
'requestedDeliveryDate' => null,
'requestedEarliestDeliveryDate' => '2023-12-05',
'requestedLatestDeliveryDate' => '2023-12-08',
'minimumRemainingShelfLifeInDays' => 90,
'unitPrice' => 1.23,
'pricingUnitOfMeasure' => 'CT',
'pricingUnitQuantity' => 100,
'recommendedRetailPrice' => 1.85,
'netWeight' => 1000,
'grossWeight' => 1050,
'originCountryCode' => 'BR',
'tax' => [
'percentage' => 7,
'description' => 'Umsatzsteuer'
],
'brand' => 'kela',
'assortment' => 'ME_GEN',
'consumerGroup' => 'Unisex',
'category' => '1008',
'subCategory' => 'Beverages',
'organicControlPointNumber' => 'DE-ÖKO-006',
'certificationsRequired' => [
'fairtrade' => true,
'supplierQa' => false,
'eudr' => true
],
'contractReference' => 'ITEM-CONTRACT-XYZ',
'promotionCode' => 'WINTER2023',
'attachments' => [
[
'fileName' => 'technical_datasheet.pdf',
'url' => 'https://example.com/attachments/technical_datasheet.pdf',
'mimeType' => 'application/pdf',
'type' => 'TECHNICAL_DATASHEET'
],
[
'fileName' => 'product_label.pdf',
'url' => 'https://example.com/attachments/product_label.pdf',
'mimeType' => 'application/pdf',
'type' => 'PRODUCT_LABEL'
]
],
'modificationGroups' => [
[
'basis' => 12.30,
'level' => 1,
'modifications' => [
[
'type' => 'ALLOWANCE',
'calculationType' => 'RELATIVE',
'reasonCode' => 'DISCOUNT',
'description' => 'Contract trade discount',
'percentage' => 7
]
]
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
$responseBody = json_decode($response->getBody()->getContents(), true);
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
$document->updateProcurosTransactionId($responseBody['procurosTransactionId']);
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Product Catalogs
Source: https://docs.procuros.io/en/api/v2/sending-product-catalogs
This is the right section for you if you are acting as a supplier and looking to send product catalogs to your customers.
Throughout this guide you will learn how to send product catalogs to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending an product catalog to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send product catalogs
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including product catalogs.
The following fields are required:
* `type` (Transaction type. In this case `PRODUCT_CATALOG`)
* `content` (The details of the product catalogs items.)
Inside the `content` you will need to build all product catalogs items. All details can be found in the `PRODUCT_CATALOG` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"PRODUCT_CATALOG",
"content" => [
"header" => [
"sender" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Test Sender GmbH",
"street" => "Musterstraße 1",
"addressExtra" => "c/o Max Mustermann",
"city" => "Entenhausen",
"postalCode" => "123456",
"countryCode" => "DE"
],
"name" => "Test Sender GmbH"
],
"receiver" => [
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Test Receiver GmbH",
"street" => "Lilienstraße 36",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
],
"name" => "Test Receiver GmbH"
],
"catalogNumber" => "Summer 2025",
"catalogDate" => "2024-06-01"
],
"items" => [
[
"unitOfMeasure" => "EA",
"identity" => [
"senderPartnerId" => "PRD-0001",
"receiverPartnerId" => "AB-MM-9988",
"gtin" => "12345678901234",
],
"lineNumber" => 12,
"quantity" => 5,
"action" => "NEW",
"currency" => "EUR",
"isOrderable" => true,
"unitPrice" => 44.23,
"pricingUnitOfMeasure" => "CT",
"pricingUnitQuantity" => 100,
"description" => "Description/Name of the product",
"hsCode" => "222222",
"isDangerous" => false,
"hasExpiryDate" => false,
"hasBatchNumber" => false,
"hasSerialNumber" => false,
"originCountryCode" => "US",
"nutritionalInformation" => [
"energy" => [
"totalInKcal" => 250.5,
"totalInKj" => 1047.2
],
"fats" => [
"totalInGrams" => 15.2,
"saturatedInGrams" => 3.5,
"monounsaturatedInGrams" => 6.8,
"polyunsaturatedInGrams" => 4.9
],
"carbohydrates" => [
"totalInGrams" => 30.5,
"sugarsInGrams" => 8.2
],
"proteins" => [
"totalInGrams" => 12.5
],
"saltInGrams" => 0.8,
"vitamins" => [
"vitaminCInMicrograms" => 80.0
]
],
"additives" => [
[
"identifiers" => [
"gdsn" => "E300",
"senderInternal" => "ADD-001"
],
"name" => "Ascorbic Acid (Vitamin C)"
]
],
"certifications" => [
"eudr" => [
"verificationNumber" => "FAHLHGK7",
"referenceNumber" => "24ITYGBJFOS258"
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Receival Notices
Source: https://docs.procuros.io/en/api/v2/sending-receival-notices
This is the right section for you if you are acting as a customer and looking to send receival notices to your suppliers.
Throughout this guide you will learn how to send receival notices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a receival notice to Procuros:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send receival notices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including receival notices.
The following fields are required:
* `type` (Transaction type. In this case `RECEIVAL_NOTICE`)
* `content` (The details of the receival notice.)
Inside the `content` you will need to build the header and transport units with items. All details can be found in the `RECEIVAL_NOTICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
"RECEIVAL_NOTICE",
"content" => [
"header" => [
"receivalAdviceNumber" => "RCV-2024-001",
"receivalDate" => "2024-06-15T10:30:00.000000Z",
"deliveryNoteNumber" => "DN-2024-456",
"customerOrderNumber" => "PO-2024-123",
"deliveryNoteDate" => "2024-06-14T14:00:00.000000Z",
"orderDate" => "2024-06-01T09:00:00.000000Z",
"comments" => "All items received in good condition",
"carrierId" => "DHL",
"carrierDomain" => "SCAC",
"trackingNumber" => "1234567890",
"trackingUrl" => "https://tracking.example.com/1234567890",
"shipFrom" => [
"name" => "Supplier Warehouse GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Supplier Warehouse GmbH",
"street" => "Industriestraße 10",
"addressExtra" => "Building A",
"city" => "Munich",
"postalCode" => "80331",
"countryCode" => "DE"
]
],
"shipTo" => [
"name" => "Customer Warehouse GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Customer Warehouse GmbH",
"street" => "Lagerstraße 25",
"addressExtra" => "Receiving Dock 3",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
]
],
"customer" => [
"name" => "Customer Company GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000654321"
]
],
"postalAddress" => [
"name" => "Customer Company GmbH",
"street" => "Hauptstraße 50",
"city" => "Hamburg",
"postalCode" => "20095",
"countryCode" => "DE"
]
],
"supplier" => [
"name" => "Supplier Company GmbH",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "4200000123456"
]
],
"postalAddress" => [
"name" => "Supplier Company GmbH",
"street" => "Lieferantenweg 15",
"city" => "Munich",
"postalCode" => "80331",
"countryCode" => "DE"
]
]
],
"transportUnits" => [
[
"unitIdentifier" => "342601560208144493",
"unitType" => "EURO_PALLET",
"containedTradeUnitCount" => 4,
"items" => [
[
"lineNumber" => 1,
"receivedQuantity" => 10,
"shippedQuantity" => 10,
"orderedQuantity" => 10,
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "12345678901234"
],
[
"domain" => "BUYER",
"identifier" => "CUST-PROD-001"
]
],
"orderLineNumber" => 1,
"unitOfMeasure" => "EA",
"description" => "Premium Product A",
"unitPrice" => 24.50,
"currency" => "EUR",
"batches" => [
[
"batchIdentifier" => "BATCH-2024-06-001",
"expirationDate" => "2025-12-31",
"quantity" => 10
]
]
],
[
"lineNumber" => 2,
"receivedQuantity" => 18,
"shippedQuantity" => 20,
"orderedQuantity" => 20,
"rejectedQuantity" => 2,
"rejectReason" => "Damaged packaging",
"identifiers" => [
[
"domain" => "GS1",
"identifier" => "98765432109876"
]
],
"orderLineNumber" => 2,
"unitOfMeasure" => "EA",
"description" => "Standard Product B",
"unitPrice" => 12.75,
"currency" => "EUR"
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
# Shipping Notices
Source: https://docs.procuros.io/en/api/v2/sending-shipping-notices
This is the right section for you if you are acting as a supplier and looking to send shipping notices to your customers.
Throughout this guide you will learn how to send shipping notices to the Procuros API.
PHP examples are included but you will likely also want to look at the relevant API calls in the [API reference](/en/api/v2/overview).
## Process
These are usually the steps taken when sending a shipping notice:
1. Check, if this document should be sent via Procuros (see: [Enabled Trade Partners](/en/api/v2/features-enabled-trade-partners))
2. Verify this document has not already been sent (see: [Tracking Document Status](/en/api/v2/features-tracking-document-status))
3. Build the transaction payload to be sent via Procuros.
1. If products being shipped are perishable and thus require shelf-life tracking, batch information needs to be added (see: [Batches & Best Before Dates](/en/api/v2/features-batches-best-before-dates))
2. If you are sending large shipments on Euro Pallets, additional shipment identification needs to be provided. (see: [Package Identification](/en/api/v2/features-package-identification))
4. Send the transaction payload via the Procuros API
## Authentication
You will need an API token to authenticate. We use a bearer token which has to be included in each request you send to the API.
Please read the [Authentication](/en/api/v2/concept-authentication) section of our API reference for a detailed description.
## Error Handling
The API will return a `2xx` status code for successful requests. Anything else indicates an error.
Please read the [Errors](/en/api/v2/concept-error-handling) section of our API reference for a detailed description plus examples of how to handle them.
## Send Shipping Notices
The API call [Send transaction](/en/api/v2/outgoing-transactions/send-transaction) is used to create transactions, including shipping notices.
The following fields are required:
* `type` (Transaction type. In this case `SHIPPING_NOTICE`)
* `content` (The details of the shipping notice items.)
Inside the `content` you will need to build all shipping notice items. All details can be found in the `SHIPPING_NOTICE` schema as described in the [API reference](/en/api/v2/outgoing-transactions/send-transaction).
Each item in `transportUnits` must have a `unitType`. The following values are supported:
| Value | Description |
| - | - |
| `EURO_PALLET` | Euro Pallet (120 × 80 cm) |
| `EURO_PALLET_HALF` | 1/2 Euro Pallet (80 × 60 cm) |
| `EURO_PALLET_QUARTER` | 1/4 Euro Pallet (60 × 40 cm) |
| `PALLET` | Generic / non-Euro pallet |
| `PACKAGE` | Package |
| `CARTON` | Carton |
| `CONTAINER` | Shipping container |
An example request would look like:
```php php theme={null}
// install dependency
// $ composer require guzzlehttp/guzzle
'SHIPPING_NOTICE',
'content' => [
'header' => [
'buyer' => [
'name' => 'ACME Co. Ltd.',
'identifiers' => [
[
'identifier' => '3220010000005',
'domain' => 'GS1'
]
]
],
'supplier' => [
'name' => 'Testsupplier',
'identifiers' => [
[
'identifier' => '3220010000010',
'domain' => 'GS1'
]
]
],
'shipTo' => [
'identifiers' => [
[
'identifier' => '3220010000005',
'domain' => 'GS1'
]
]
],
'billTo' => [
'identifiers' => [
[
'identifier' => '3220010000006',
'domain' => 'GS1'
]
]
],
'technicalRecipient' => [
'identifiers' => [
[
'identifier' => '3220010000006',
'domain' => 'GS1'
]
]
],
'technicalSender' => [
'identifiers' => [
[
'identifier' => '3220010000007',
'domain' => 'GS1'
]
]
],
'shippingNoticeIdentifier' => 'SN9383-R45',
'shippingNoticeDate' => '2021-11-24',
'orderIdentifier' => 'PO9383-R45',
'orderDate' => '2021-11-20',
'despatchDate' => '2021-11-05',
'requestedDeliveryDate' => '2021-11-06',
'expectedDeliveryDate' => '2021-11-06'
],
'transportUnits' => [
[
'unitIdentifier' => '34000000000001',
'unitType' => 'EURO_PALLET',
'containedTradeUnitCount' => 10,
'items' => [
[
'lineNumber' => 1,
'orderLineNumber' => 1,
'orderIdentifier' => 'PO9383-R45',
'identifiers' => [
[
'identifier' => '2330010000061',
'domain' => 'GS1'
],
[
'identifier' => 'filter-coffee',
'domain' => 'BUYER'
],
[
'identifier' => 'supplier-filter-coffee',
'domain' => 'SUPPLIER'
]
],
'isDepositItem' => false,
'orderedQuantity' => 20,
'shippedQuantity' => 20,
'description' => 'First product description.',
'certifications' => [
'eudr' => [
'verificationNumber' => 'FAHLHGK7',
'referenceNumber' => '24ITYGBJFOS258'
]
],
'batches' => [
[
'batchIdentifier' => 'BATCH_ID_1',
'expirationDate' => '2022-12-24',
'quantity' => 15
],
[
'batchIdentifier' => 'BATCH_ID_2',
'expirationDate' => '2022-12-31',
'quantity' => 5
]
]
],
[
'lineNumber' => 2,
'orderLineNumber' => 2,
'orderIdentifier' => 'PO9383-R45',
'identifiers' => [
[
'identifier' => '2330010000019',
'domain' => 'GS1'
],
[
'identifier' => 'bread-crumbs-bulk',
'domain' => 'BUYER'
],
[
'identifier' => 'supplier-bread-crumbs-bulk',
'domain' => 'SUPPLIER'
]
],
'isDepositItem' => false,
'orderedQuantity' => 19,
'shippedQuantity' => 15,
'openQuantityAction' => 'DISCARDED',
'batches' => [
[
'batchIdentifier' => 'BATCH_ID_2',
'expirationDate' => '2022-05-01',
'quantity' => 15
]
],
'description' => 'Sparkling Water - Crate (6x0.75l).'
]
]
]
]
]
];
$response = $client->request('POST', 'https://api.procuros.io/v2/transactions', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ',
],
'json' => $transaction,
]);
```
## Mark Document Status
Finally, as per the instructions mentioned under [Tracking Document Status](/en/api/v2/features-tracking-document-status) you must now track the status of the document locally, based on the returned HTTP response.
The document should be marked with either status `TRANSMITTED` or `NO_ACTION`. If there is an error with the document and it is not accepted, do not mark it with a status so it may be retried. For more information on retrying failed documents, please see: [Retrying Documents](/en/api/v2/features-tracking-document-status#retrying-documents).
For example:
```php php theme={null}
$statusCode = $response->getStatusCode();
if ($statusCode == 201) {
$document->updateProcurosStatus("TRANSMITTED");
} else if ($statusCode == 202) {
$document->updateProcurosStatus("NO_ACTION");
} else {
// No need to do anything if it's not accepted, in an error case the document should be retried.
}
```
## Advanced Use Cases
When it comes to sending shipping notices, there are a number of advanced cases, such as [Bottle Deposits](/en/api/v2/features-bottle-deposits), [Batches & Best Before Dates](/en/api/v2/features-batches-best-before-dates) and [Package Identification](/en/api/v2/features-package-identification).
Please see the Features section of our API reference for a detailed description of all advanced use cases.
# Test Data: Address Identifiers
Source: https://docs.procuros.io/en/api/v2/test-cases-address-identifiers
The following is a list of static test data that exists on our staging system, and which items + identifiers you can expect to find in the data set.
### Legend
* `Partner` - The name of the partner in the test data set
* `Sends` - The types of document this parter can send you on the network
* `Receives` - The types of document this partner can receive from you on the network
* `Domain` - The address identifier domain. `GS1` is used for a `GLN`.
* `Identifier` - The address identifier (GLN, EAN, etc.)
| Partner | Sends | Receives | Domain | Identifier |
| - | - | - | - | - |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000001` |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000002` |
| `Jabbercube` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000003` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000004` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000005` |
| `Mycat` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000006` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000007` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000008` |
| `Flipstorm` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000009` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000010` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000011` |
| `Tagfeed` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE`, `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000012` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000013` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000014` |
| `Flashdog` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000015` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000022` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000023` |
| `Skippad` | `ORDER` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `GS1` | `3220010000024` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000016` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000017` |
| `Avavee` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000018` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000019` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000020` |
| `Izio` | `ORDER_RESPONSE`, `SHIPPING_NOTICE`, `INVOICE` | `ORDER` | `GS1` | `3220010000021` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000025` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000026` |
| `Photobug` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000027` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000028` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000029` |
| `Blogtags` | `DISPATCH_INSTRUCTION` | `DISPATCH_INSTRUCTION_RESPONSE` | `GS1` | `3220010000030` |
# Test Data: Items
Source: https://docs.procuros.io/en/api/v2/test-cases-items
The following is a list of static test data that exists on our staging system, and which items + identifiers you can expect to find in the data set.
### Legend
* `Index` - The index of the item
* `Description` - The description of the item
* `Domain` - The domain of the item. Either `GS1` (a GLN), `BUYER`, or `SUPPLIER`
* `Identifier` - The identifier of the item for that domain
* `Qty` - The quantity of the item
* `Price` - The item price in the test data set
* `UoM` - The Unit of Measure of the item
| Index | Description | Domain | Identifier | Qty | Price | UoM |
| - | - | - | - | - | - | - |
| 1 | Milk, Callets | `BUYER` | `chocolate-milk-callets` | 16 | 70 | `EA` |
| 1 | Milk, Callets | `GS1` | `2330010000001` | 16 | 70 | `EA` |
| 2 | Orecchiette | `BUYER` | `pasta-orecchiette` | 18 | 3.42 | `EA` |
| 2 | Orecchiette | `GS1` | `2330000000002` | 18 | 3.42 | `EA` |
| 3 | | `BUYER` | `bacardiraspberry` | 17 | 20.43 | `EA` |
| 3 | | `GS1` | `2330010000003` | 17 | 20.43 | `EA` |
| 4 | Meat Combo | `BUYER` | `crab-meatcombo` | 19 | 18.94 | `EA` |
| 4 | Meat Combo | `GS1` | `2330000000004` | 19 | 18.94 | `EA` |
| 5 | | `BUYER` | `pralinepaste` | 4 | 57.28 | `EA` |
| 5 | | `GS1` | `2330010000005` | 4 | 57.28 | `EA` |
| 6 | 74 Brights | `BUYER` | `2330000000007` | 18 | 0.69 | `EA` |
| 6 | 74 Brights | `SUPPLIER` | `supplier-port-brights` | 18 | 0.69 | `EA` |
| 6 | 74 Brights | `GS1` | `2330000000007` | 18 | 0.69 | `EA` |
| 7 | Greek Salad | `BUYER` | `2330000000012` | 16 | 11.03 | `EA` |
| 7 | Greek Salad | `SUPPLIER` | `supplier-longos-greeksalad` | 16 | 11.03 | `EA` |
| 7 | Greek Salad | `GS1` | `2330000000012` | 16 | 11.03 | `EA` |
| 8 | Mascarpone | `BUYER` | `2330010000013` | 8 | 31.34 | `EA` |
| 8 | Mascarpone | `SUPPLIER` | `supplier-cheese-mascarpone` | 8 | 31.34 | `EA` |
| 8 | Mascarpone | `GS1` | `2330010000013` | 8 | 31.34 | `EA` |
| 9 | French Vanilla | `BUYER` | `2330010000019` | 2 | 15.33 | `EA` |
| 9 | French Vanilla | `SUPPLIER` | `supplier-yogurt-frenchvanilla` | 2 | 15.33 | `EA` |
| 9 | French Vanilla | `GS1` | `2330010000019` | 2 | 15.33 | `EA` |
| 10 | Crumbs, Bulk | `BUYER` | `bread-crumbs-bulk` | 19 | 15.32 | `EA` |
| 10 | Crumbs, Bulk | `SUPPLIER` | `supplier-bread-crumbs-bulk` | 19 | 15.32 | `EA` |
| 10 | Crumbs, Bulk | `GS1` | `2330010000020` | 19 | 15.32 | `EA` |
| 11 | Cherry | `BUYER` | `piefilling-cherry` | 6 | 1.06 | `EA` |
| 11 | Cherry | `SUPPLIER` | `supplier-piefilling-cherry` | 6 | 1.06 | `EA` |
| 11 | Cherry | `GS1` | `2330000000021` | 6 | 1.06 | `EA` |
| 12 | Italian Corn Meal Poly | `BUYER` | `bread-italiancornmealpoly` | 10 | 54.91 | `EA` |
| 12 | Italian Corn Meal Poly | `SUPPLIER` | `supplier-bread-italiancornmealpoly` | 10 | 54.91 | `EA` |
| 12 | Italian Corn Meal Poly | `GS1` | `2330010000022` | 10 | 54.91 | `EA` |
| 13 | Bones | `BUYER` | `fish-bones` | 12 | 16.09 | `KGM` |
| 13 | Bones | `SUPPLIER` | `supplier-fish-bones` | 12 | 16.09 | `KGM` |
| 13 | Bones | `GS1` | `2330000000023` | 12 | 16.09 | `KGM` |
| 14 | Brisket, Provimi, Bone In | `BUYER` | `veal-brisket-provimi-bone-in` | 19 | 10.52 | `EA` |
| 14 | Brisket, Provimi, Bone In | `SUPPLIER` | `supplier-veal-brisket-provimi-bone-in` | 19 | 10.52 | `EA` |
| 14 | Brisket, Provimi, Bone In | `GS1` | `2330010000025` | 19 | 10.52 | `EA` |
| 15 | | `BUYER` | `bolsmelonliqueur` | 18 | 27.04 | `EA` |
| 15 | | `SUPPLIER` | `supplier-bolsmelonliqueur` | 18 | 27.04 | `EA` |
| 15 | | `GS1` | `2330000000026` | 18 | 27.04 | `EA` |
| 16 | Tongue, Cooked | `BUYER` | `beef-tongue-cooked` | 15 | 17.41 | `EA` |
| 16 | Tongue, Cooked | `SUPPLIER` | `supplier-beef-tongue-cooked` | 15 | 17.41 | `EA` |
| 16 | Tongue, Cooked | `GS1` | `2330000000029` | 15 | 17.41 | `EA` |
| 17 | Radicchio | `BUYER` | `lettuce-radicchio` | 4 | 71.19 | `KGM` |
| 17 | Radicchio | `SUPPLIER` | `supplier-lettuce-radicchio` | 4 | 71.19 | `KGM` |
| 17 | Radicchio | `GS1` | `2330000000031` | 4 | 71.19 | `KGM` |
| 18 | Water | `BUYER` | `crackers-water` | 17 | 70.71 | `EA` |
| 18 | Water | `SUPPLIER` | `supplier-crackers-water` | 17 | 70.71 | `EA` |
| 18 | Water | `GS1` | `2330000000032` | 17 | 70.71 | `EA` |
| 19 | Prime Rib Aaa | `BUYER` | `beef-primeribaaa` | 5 | 43.48 | `EA` |
| 19 | Prime Rib Aaa | `SUPPLIER` | `supplier-beef-primeribaaa` | 5 | 43.48 | `EA` |
| 19 | Prime Rib Aaa | `GS1` | `2330010000036` | 5 | 43.48 | `EA` |
| 20 | | `BUYER` | `chickengiblets` | 19 | 47.27 | `EA` |
| 20 | | `SUPPLIER` | `supplier-chickengiblets` | 19 | 47.27 | `EA` |
| 20 | | `GS1` | `2330000000037` | 19 | 47.27 | `EA` |
| 21 | Cooked Italian | `BUYER` | `ham-cookeditalian` | 6 | 22.64 | `EA` |
| 21 | Cooked Italian | `SUPPLIER` | `supplier-ham-cookeditalian` | 6 | 22.64 | `EA` |
| 21 | Cooked Italian | `GS1` | `2330000000038` | 6 | 22.64 | `EA` |
| 22 | Chardonnay Mondavi | `BUYER` | `wine-chardonnaymondavi` | 3 | 39.11 | `EA` |
| 22 | Chardonnay Mondavi | `SUPPLIER` | `supplier-wine-chardonnaymondavi` | 3 | 39.11 | `EA` |
| 22 | Chardonnay Mondavi | `GS1` | `2330000000039` | 3 | 39.11 | `EA` |
| 23 | Calabrese Baguette | `BUYER` | `bread-calabresebaguette` | 4 | 25.36 | `EA` |
| 23 | Calabrese Baguette | `SUPPLIER` | `supplier-bread-calabresebaguette` | 4 | 25.36 | `EA` |
| 23 | Calabrese Baguette | `GS1` | `2330010000040` | 4 | 25.36 | `EA` |
| 24 | Smoked, Sliced | `BUYER` | `salmon-smoked-sliced` | 2 | 5.18 | `MTR` |
| 24 | Smoked, Sliced | `SUPPLIER` | `supplier-salmon-smoked-sliced` | 2 | 5.18 | `MTR` |
| 24 | Smoked, Sliced | `GS1` | `2330010000050` | 2 | 5.18 | `MTR` |
| 25 | Fettuccine, Egg, Fresh | `BUYER` | `pasta-fettuccine-egg-fresh` | 2 | 8.37 | `KGM` |
| 25 | Fettuccine, Egg, Fresh | `SUPPLIER` | `supplier-pasta-fettuccine-egg-fresh` | 2 | 8.37 | `KGM` |
| 25 | Fettuccine, Egg, Fresh | `GS1` | `2330000000051` | 2 | 8.37 | `KGM` |
| 26 | Butt, Boneless | `BUYER` | `pork-butt-boneless` | 8 | 62.13 | `EA` |
| 26 | Butt, Boneless | `SUPPLIER` | `supplier-pork-butt-boneless` | 8 | 62.13 | `EA` |
| 26 | Butt, Boneless | `GS1` | `2330000000052` | 8 | 62.13 | `EA` |
| 27 | | `BUYER` | `pantscustomdryclean` | 11 | 57.42 | `EA` |
| 27 | | `SUPPLIER` | `supplier-pantscustomdryclean` | 11 | 57.42 | `EA` |
| 27 | | `GS1` | `2330000000053` | 11 | 57.42 | `EA` |
| 28 | Red, Dry | `BUYER` | `lentils-red-dry` | 13 | 36.42 | `EA` |
| 28 | Red, Dry | `SUPPLIER` | `supplier-lentils-red-dry` | 13 | 36.42 | `EA` |
| 28 | Red, Dry | `GS1` | `2330000000059` | 13 | 36.42 | `EA` |
| 29 | Cream Fudge | `BUYER` | `fudge-creamfudge` | 17 | 74.76 | `EA` |
| 29 | Cream Fudge | `SUPPLIER` | `supplier-fudge-creamfudge` | 17 | 74.76 | `EA` |
| 29 | Cream Fudge | `GS1` | `2330010000061` | 17 | 74.76 | `EA` |
| 30 | Coffee | `BUYER` | `filter-coffee` | 20 | 18.46 | `KGM` |
| 30 | Coffee | `SUPPLIER` | `supplier-filter-coffee` | 20 | 18.46 | `KGM` |
| 30 | Coffee | `GS1` | `2330000000063` | 20 | 18.46 | `KGM` |
| 31 | Pina Colada, 355 Ml | `BUYER` | `barmix-pinacolada-355ml-002-001` | 7 | 14.93 | `EA` |
| 31 | Pina Colada, 355 Ml | `SUPPLIER` | `supplier-barmix-pinacolada-355ml-002-001` | 7 | 14.93 | `EA` |
| 31 | Pina Colada, 355 Ml | `GS1` | `2330000000073` | 7 | 14.93 | `EA` |
| 32 | Red | `BUYER` | `cabbage-red` | 16 | 50.68 | `KGM` |
| 32 | Red | `SUPPLIER` | `supplier-cabbage-red` | 16 | 50.68 | `KGM` |
| 32 | Red | `GS1` | `2330010000077` | 16 | 50.68 | `KGM` |
| 33 | Leaves | `BUYER` | `banana-leaves` | 14 | 41.11 | `GRM` |
| 33 | Leaves | `SUPPLIER` | `supplier-banana-leaves` | 14 | 41.11 | `GRM` |
| 33 | Leaves | `GS1` | `2330000000082` | 14 | 41.11 | `GRM` |
| 34 | Vidal Icewine Magnotta | `BUYER` | `wine-vidalicewinemagnotta` | 20 | 32.85 | `EA` |
| 34 | Vidal Icewine Magnotta | `SUPPLIER` | `supplier-wine-vidalicewinemagnotta` | 20 | 32.85 | `EA` |
| 34 | Vidal Icewine Magnotta | `GS1` | `2330000000083` | 20 | 32.85 | `EA` |
| 35 | Sticks, Thin, Plain | `BUYER` | `bread-sticks-thin-plain` | 12 | 77.66 | `EA` |
| 35 | Sticks, Thin, Plain | `SUPPLIER` | `supplier-bread-sticks-thin-plain` | 12 | 77.66 | `EA` |
| 35 | Sticks, Thin, Plain | `GS1` | `2330010000084` | 12 | 77.66 | `EA` |
| 36 | Fresh | `BUYER` | `parsley-fresh` | 100 | 96.37 | `GRM` |
| 36 | Fresh | `SUPPLIER` | `supplier-parsley-fresh` | 100 | 96.37 | `GRM` |
| 36 | Fresh | `GS1` | `2330000000085` | 100 | 96.37 | `GRM` |
| 37 | Original Organic Lager | `BUYER` | `beer-originalorganiclager` | 1 | 31.55 | `EA` |
| 37 | Original Organic Lager | `SUPPLIER` | `supplier-beer-originalorganiclager` | 1 | 31.55 | `EA` |
| 37 | Original Organic Lager | `GS1` | `2330000000087` | 1 | 31.55 | `EA` |
| 38 | Orange, 355ml | `BUYER` | `crush-orange-355ml-001` | 8 | 92.03 | `EA` |
| 38 | Orange, 355ml | `SUPPLIER` | `supplier-crush-orange-355ml-001` | 8 | 92.03 | `EA` |
| 38 | Orange, 355ml | `GS1` | `2330000000092` | 8 | 92.03 | `EA` |
| 39 | Tomato Mush. Florentine | `BUYER` | `soup-tomatomush.florentine` | 17 | 27.22 | `EA` |
| 39 | Tomato Mush. Florentine | `SUPPLIER` | `supplier-soup-tomatomush.florentine` | 17 | 27.22 | `EA` |
| 39 | Tomato Mush. Florentine | `GS1` | `2330000000097` | 17 | 27.22 | `EA` |
| 40 | Linguini, Dry | `BUYER` | `2330010000104` | 19 | 84.12 | `EA` |
| 40 | Linguini, Dry | `SUPPLIER` | `supplier-pasta-linguini-dry` | 19 | 84.12 | `EA` |
| 40 | Linguini, Dry | `GS1` | `2330010000104` | 19 | 84.12 | `EA` |
| 41 | | `BUYER` | `2330000200110` | 20 | 21.66 | `EA` |
| 41 | | `SUPPLIER` | `supplier-bundle-tea` | 20 | 21.66 | `EA` |
| 41 | | `GS1` | `2330000200110` | 20 | 21.66 | `EA` |
| 42 | | `BUYER` | `2330000200111` | 11 | 20.11 | `EA` |
| 42 | | `SUPPLIER` | `supplier-bundle-dinner-for-two` | 11 | 20.11 | `EA` |
| 42 | | `GS1` | `2330000200111` | 11 | 20.11 | `EA` |
| 43 | | `BUYER` | `2330000200112` | 6 | 79.95 | `EA` |
| 43 | | `SUPPLIER` | `supplier-bundle-fruit` | 6 | 79.95 | `EA` |
| 43 | | `GS1` | `2330000200112` | 6 | 79.95 | `EA` |
# Best Practices
Source: https://docs.procuros.io/en/api/v2/test-cases-overview
## Test Data
When testing against staging, we are able to generate static test data for your account. This data is not connected to any real data in your ERP system. It is only used for testing purposes.
We have prepared this data so that you can test different scenarios while building your integration. There are partners that accept different kinds of documents, as well as a list of retail items for your testing needs.
To find a full list of this infromation, please see:
* [Test Data: Address Identifiers](/en/api/v2/test-cases-address-identifiers)
* [Test Data: Items](/en/api/v2/test-cases-items)
## Scenarios you Should Test
When it comes to data integration, it's important to test your integration thoroughly. You should consider the data you will receive or provide to the API. Some scenarios that you should test to ensure that your integration is working correctly are:
* `null` values (Missing dates, missing quantities, etc.)
* Decimal values (quantities, prices, etc.)
* Zeros
Additionally you should consider how your integration handles the following scenarios:
* Validation errors returned from the API
* Can you report an error back to the API, if there is an issue with a document?
* What do you do when there is a duplicate GLN? (Multiple customers were found for the given GLN in the ERP)
* What do you do when there is a duplicate GTIN? (Multiple products were found for the given GTIN in the ERP)
* How to handle missing data in the ERP system?
* Can this data be skipped?
* Should you report an error to the Procuros API?
* How do you handle data received from the API you can't work with?
# Download Transport Label
Source: https://docs.procuros.io/en/api/v2/transport-labels/download-transport-label
/en/api/v2/openapi-v2.yaml get /v2/transactions/{transportLabelUrl}/download
Download the file content of a transport label. Use the value of the `zplUrl` or `pdfUrl` field from the `transportLabel` object of a transport unit (available on Shipping Notice and Dispatch Instruction Response transactions) as the `transportLabelUrl` path parameter, depending on whether you want the raw ZPL or the rendered PDF. The response is the streamed file content for download.