Receiving document data (d.velop smart invoice)
You can receive document data from d.velop invoices for further processing in two ways: via webhook or via the API for retrieving outstanding transfers. If you choose to process the data via a webhook, d.velop invoices calls your implemented web service with the data of the document to be transferred. If you process the data by retrieving the transfers, your application is responsible for the regular retrieval of the outstanding documents within a configurable time frame, processing them and reporting whether or not processing was successful to d.velop invoices.
When is a webhook the better option and when is retrieval via API?
The retrieval of data via API and receipt of the data via webhook basically offer the same scope of functions. You get the same document data with both variants, and both variants require you to report whether or not processing was completed. So when should you choose to retrieve the data via API and when should you choose to receive it via webhook?
A webhook lets you respond to document data more quickly, because d.velop invoices actively contacts your application as soon as there is data to be processed. You can immediately check the data for validity and provide a reply, for instance. If you retrieve the data via API, your application checks whether new data is available at regular intervals. If this check is performed once an hour, for example, your application only transfers data to the external system once an hour as well. If errors occur and you report the process to be unsuccessful, the users only find out about this with this delay too.
To retrieve document data via API, your application must be able to access the d.velop invoices API. If you are using the cloud version of d.velop invoices, your application must therefore have internet access. To ensure that you can receive data via a webhook, d.velop invoices must be able to reach your application. If you are using the cloud version of d.velop invoices, your application must be accessible from the internet.
Format of the document data
Both methods deliver the document data to you in a standardized format.
{ "event_type": "integration.export", "_links": { "dmsobject": { "href": "https://example.d-velop.cloud/dms/r/21b9b52f-19e3-4b3d-8ac6-b32d991f83e0/o2/P000000001" } }, "workflow": { "voucher": { "doc_id": "P000000001", "company": { "nr": "01", "name": "docures AG" }, "vendor": { "nr": "50001", "name": "Schrauben Meier GmbH" }, "vendor_bank_account": { "id": "", "iban": "" }, "currency": { "id": "EUR", "name": "Euro", "code": "EUR" }, "net_amount": 100.0, "gross_amount": 119.0, "pay_amount": null, "vat_amount": 19.0, "document_date": "2020-05-05T00:00:00+00:00", "internal_number": "INT010291", "external_number": "INV12310", "payment_date": "2020-05-10T00:00:00+00:00", "date_of_supply": "2020-05-05T00:00:00+00:00" "financially_correct": false, "document_type": { "id": "inv", "name": "Invoice", "credit_note": false }, "payment_terms": { "id": "NET30", "net_days": 30, "cashback_days1": 10, "cashback_percentage1": 2.5 }, "posting_period": "2020-05-09", "posting_date": "2020-05-09T00:00:00+00:00", "posting_text": "M3x3mm screws", "barcode": "BC1234", "custom1": "Sales" "line_items": { "5afe1329-83cd-4ccc-b806-f9ee458522b7": { "internal_id": "5afe1329-83cd-4ccc-b806-f9ee458522b7", "line_no": 1, "verified": true, "verifier": { "type": "user", "name": "mmus", "display_name": "Max Mustermann" }, "verified_by": { "type": "user", "id": "257659", "name": "mmus", "display_name": "Max Mustermann" }, "verified_at": "2020-05-05T10:25:00+01:00", "gl_account": { "nr": "6300" }, "cost_center": { "nr": "1000" }, "cost_unit": { "nr": "PJ0001" }, "net_amount": 100.0, "gross_amount": 119.0, "pay_amount": null, "vat_amount": 19.0, "tax_code": { "id": "DE_S", "name": "Vorsteuer 19%", "percentage": 19.0 }, "order_number": "PO001", "order_line": 1, "order_id": "PO_001", "order_line_id": "PO_001_1", "quantity": { "invoiced": 2 }, "unit": "Pcs.", "unit_price": 50.0, "description": "Schraubendreher", "item_number": "4711", "discount_absolute": 0, "discount_per_unit": 0, "discount_percent": 0, "discount2_percent": 0, "discount3_percent": 0, "discount4_percent": 0, "discount5_percent": 0, "custom1": "Neubau" } } }, "step": { "id": "64576949-ff8e-4e45-b0ec-7b4e25436331", "title": "Verification" } }, "connection": { "from_step": { "id": "9080a8d4-6698-4613-b5c1-6c1ca103daab", "title": "Verification" }, "to_step": { "id": "fd51ab72-aceb-4c1d-b775-ea3d411c9284", "title": "Approval" }, "end_mode": null } }
At the highest level, you receive the following data:
Property | Description |
---|---|
event_type | The type of the transferred event. At present, only the event integration.export is transferred. |
_links | Links to related resources. At present, only the following types are supported:
|
workflow | The workflow object. This object contains document data and status information about the workflow. It is described in more detail below. |
connection | Information about the current step connection in the workflow. Always filled for events of the type integration.export. |
Information about the step connection
An export (event type integration.export) is always triggered in the context of a connection between two workflow steps. This information helps you to determine, for example, whether the workflow ends with the transfer.
Property | Description |
---|---|
from_step | The starting step in the connection. If the workflow begins immediately, this property is zero. |
to_step | The target step in the connection. If the workflow ends immediately, this property is zero. |
end_mode | If the workflow ends with this connection, then end_mode contains information about the mode in which the workflow ends. Possible options:
|
Information about the current workflow status (workflow object)
Property | Description |
---|---|
voucher | The document data for the workflow. |
step | The current step in the workflow. Caution: Since exports are usually triggered as part of step connections, the step changes when the workflow is completed. You can find the next step using the connection property on the highest level of the JSON structure. |
Document header data (voucher object)
All the document header data is grouped together in this object.
Property | Description |
---|---|
doc_id | The ID of the document in the underlying document management system (d.velop documents or SharePoint). |
company | The company (invoice recipient) for this document.
|
vendor | The vendor (supplier/invoice issuer) for this document.
|
vendor_bank_account | The vendor bank account for this document.
|
currency | The currency in which the invoice was issued.
|
net_amount | The total net amount of the document. |
vat_amount | The total tax amount of the document. |
gross_amount | The total gross amount of the document. |
document_date | The document/invoice date in the format yyyy-MM-ddTHH:mm:ssZ. |
internal_number | The internal document number. |
external_number | The external document number. The vendor’s invoice number. |
date_of_supply | The date of supply in the format yyyy-MM-ddTHH:mm:ssZ. |
document_type | The document type.
|
payment_terms | The payment terms for the invoice.
|
payment_date | The payment date in the format yyyy-MM-ddTHH:mm:ssZ. |
posting_period | The posting period for the invoice. The format is not specified. If the external system works with a posting date, we recommend using the field posting_date as an alternative. |
posting_date | The posting date for the invoice in the format yyyy-MM-ddTHH:mm:ssZ. If the external system works with a posting period instead of a date, we recommend using the field posting_period as an alternative. |
posting_text | The posting text for the invoice. |
barcode | The barcode for the invoice. |
regional_ch | Regional fields for customers from Switzerland.
|
custom1 to custom20 | Custom fields at header level. |
Information about document line items (line item object)
Each individual document line item supports the following properties:
Property | Description |
---|---|
internal_id | The unique ID of the document line item. |
line_no | The line number of the document line item. |
verified | Indicates whether the line item is marked as factually correct. Caution: This property is unavailable if you are using the “Advanced verification” preview feature. |
verifier | Indicates the person who is authorized to mark this line item as factually correct. Caution: This is not necessarily the person that actually marked the line item as factually correct. This person can be found in the property verified_by. Attention: This property is unavailable if you are using the “Advanced verification” preview feature. |
verified_by | Indicates the person who marked this line item as factually correct. Caution: This property is unavailable if you are using the “Advanced verification” preview feature. |
verified_at | The time at which this line item was marked as factually correct. In the format yyyy-MM-dd HH:mm:ss, time zone UTC. Caution: This property is unavailable if you are using the Advanced verification preview feature. |
gl_account | The G/L account of the document line item.
|
cost_center | The cost center of the document line item.
|
cost_unit | The cost unit of the document line item.
|
procurement_category | The procurement category of the document line item.
|
net_amount | The net amount of the document line item. |
tax_code | The tax code of the document line item.
|
vat_amount | The tax amount for the document line item. Caution: If the field is a writable field in d.velop invoices, the tax amount may differ from the tax rate of the selected tax code. |
gross_amount | The gross amount of the document line item. |
unit | The unit of measure of the document line item. |
quantity | The quantity of the document line item.
|
unit_price | The unit price of the document line item. |
price_unit | The price unit of the document line item. The price unit is relevant if the supplier and company do not work with the same unit of measure for the quantity. The unit price is divided by the price unit before it is multiplied by the quantity. |
item_number | The item number of the document line item. |
description | The description of the document line item. |
order_number | The number of the order belonging to this document line item. |
order_line | The number of the order line belonging to this document line item. |
order_id | The ID of the order belonging to this document line item (corresponds to the ID transferred in the master data). |
order_line_id | The ID of the order line belonging to this document line item (corresponds to the ID transferred in the master data). |
goods_receipt_nr | The number of the goods receipt belonging to this document line item. |
goods_receipt_line_no | The number of the goods receipt line item belonging to this document line item. |
goods_receipt_id | The ID of the goods receipt belonging to this document line item (corresponds to the ID transferred in the master data). |
goods_receipt_line_item_id | The ID of the goods receipt line belonging to this document line item (corresponds to the ID transferred in the master data). |
discount_absolute | Absolute discount on the net amount of the line item. |
discount_per_unit | Absolute discount on the unit price of the line item. |
discount_percent | First percentage discount on the net amount of the line item. |
discount2_percent | Second percentage discount on the net amount of the line item. |
discount3_percent | Third percentage discount on the net amount of the line item. |
discount4_percent | Fourth percentage discount on the net amount of the line item. |
discount5_percent | Fifth percentage discount on the net amount of the line item. |
custom1 to custom20 | Custom fields at line item level. |
Receiving data via webhook
You can use webhooks to receive document data from d.velop smart invoice in an external system via HTTP. To do so, you can use an integrating application where you store an HTTP endpoint.
What are webhooks?
d.velop smart invoice can use webhooks to inform an external application (such as an ERP system, for example) when certain events occur. The external application can then respond to this event, for example, by generating a posting proposal.
From a technical perspective, a webhook can be created in any kind of technology as long as the application provides an HTTP endpoint that can receive POST requests in a format specified by d.velop smart invoice.
Implementing a webhook endpoint
To implement a webhook endpoint, you must first make a new endpoint available in your application. The way to do so depends on the technology that you are using: for example, it may be a new .php file in a PHP application or a new route in Microsoft ASP.NET MVC.
The endpoint is then tasked with extracting and processing the JSON from the POST request. At the end of processing, you must return an HTTP status code that indicates whether processing was successful to d.velop smart invoice.
The data that d.velop smart invoice sends to the endpoint corresponds to the event object from the API.
You should also authenticate the incoming requests to ensure that they actually originate from d.velop smart invoice.
Status codes and return values
If you were able to process the webhook request correctly, you should respond with HTTP status code 200. If errors occurred, you should respond with status code 500 if there is a program error on your side.
If the cause was invalid information (for example, a G/L account that did not exist), you should respond with error 400. In this case, you can also enter an error message in the response. This error message is displayed for the user in d.velop smart invoice. You must enter the error message in German and English.
For example:
{ "error": { "de": "Die Buchungsperiode wurde bereits geschlossen.", "en": "The posting period has already been closed." } }
Authenticating requests
When you implement a webhook endpoint, you must ensure that incoming requests actually originate from d.velop smart invoice. For this purpose, each request includes a signature in the header X-Smart-Invoice-Signature. To verify the signature, you require the secret from the webhook integration settings. The secret differs in each integrating application.
The header X-Smart-Invoice-Signature contains the signature and a timestamp. This timestamp is specified as a Unix timestamp in the key t. You can find the signature in the key v1.
X-Smart-Invoice-Signature: t=12839891289,v1=38941389418903890128930jaskldjl221
The signature is generated by d.velop smart invoice in accordance with the HMAC-SHA256 method. To check the signature, proceed as follows:
Compare the timestamp
Compare the timestamp from the header X-Smart-Invoice-Signature with the actual time. If the values are more than five minutes apart, then you should discard the request as not authenticated and respond with an appropriate HTTP status code.
Link the timestamp and body
Link the timestamp from the header X-Smart-Invoice-Signature and the body of the request with:
timestamp.body
Calculate the HMAC-SHA256 value
Use the secret from the integrating webhook application to calculate an HMAC-SHA256 value in a hexadecimal representation from the character string that was just created.
Compare the signatures
Now compare the value that you have just calculated with the value from the header X-Smart-Invoice-Signature. To do so, you should use a comparison function that performs comparisons in a constant time to prevent a timing attack. If the values differ from each other, you should discard the request as not authenticated. Otherwise, you can continue processing the request.
Retrieving transfers via API
You can retrieve the documents that are available for transfer from an external application using a d.velop smart invoice REST API. For this purpose, you have access to interfaces for retrieving documents and confirming a successful transfer.
The processing sequence
When document data is made available for retrieval by d.velop smart invoice, it stays available for retrieval for a maximum of two days. The external application must retrieve the document data within this time frame and report whether processing was successful. If the time passes without any response from the external application, the transfer is marked as failed. The document is then diverted to the error location configured in d.velop smart invoice.
If the external application reports that the transfer was successful, the document is then further processed based on the d.velop smart invoice configuration. This often means that the workflow ends following a successful transfer.
If a problem occurs and the external application therefore reports an error, the document is diverted to the configured error location. The error message provided from the external application is displayed for the user.
The time frame of max. two days can be shortened by admin, but not extended.
Integration key
Each external application requires an integration key to request document data. This integration key is automatically generated by d.velop smart invoice and can be viewed in the administration interface. The integration key is not an authentication feature; instead, it serves only to differentiate between transfers for different applications.
Retrieving transfers
You can regularly retrieve a list of all the outstanding transfers for your integration key as follows:
Request
GET /smartinvoice/api/v1/transfers?integration_key=abc Accept: application/json
Response
{ "_links": { "next": { "href": "https://test.d-velop.cloud/smartinvoice/api/v1/transfers/..." }, "previous": { "href": "https://test.d-velop.cloud/smartinvoice/api/v1/transfers/..." }, }, "transfers": [ { "_links": { ... }, "workflow": { ... } } ] }
Property | Description |
---|---|
_links | Transfers may be returned in multiple pages. Use the URLs specified here to retrieve additional pages.
|
transfers | The workflows that are available for transfer. The format of each transfer corresponds to the document data format described at the start. |
Reporting the results
After you have processed the data from a transfer, you have to report a result. If you do not return a result on time, the transfer is classed as failed.
To report a result, send a POST request to the URL specified under _links and report_results_async in the transfer.
Request
POST /smartinvoice/api/v1/transfers/:id Content-Type: application/json { "successful": false, "error": { "de": "Transfer fehlgeschlagen.", "en": "Transfer failed." } }
Property | Description |
---|---|
successful | Boolean. Mandatory. Indicates whether the transfer was successful. If you enter false here, you must also send the error object. If you enter true, you must not send the error object. |
error | If errors occur, you can save error messages in various languages. The languages German and English are mandatory. Messages entered here are displayed for the end user. |
/smartinvoice