|
|
|
[[_TOC_]]
|
|
|
|
|
|
|
|
# Communication API between Datovka and a Document Service Application
|
|
|
|
|
|
|
|
The following document describes an API for uploading data messages (datové zprávy) in ZFO format from Datovka into a document service application. The API is currently supported only in the desktop version of Datovka. Although the proposed API allows uploading of delivery infos (doručenky) Datovka currently supports only uploading of messages.
|
|
|
|
|
|
|
|
We are using a HTTPS-based communication channel which is using token authentication. This is achieved by sending *Authentication* header with a text value representing the access token.
|
|
|
|
|
|
|
|
### Example
|
|
|
|
|
|
|
|
The document service URL is `https://document.service.cz/publicapi/v1/` and you are using the token `kjdkKJDWDHWOnc39KCJSKS` and you want to call the service `upload_hierarchy`:
|
|
|
|
|
|
|
|
```
|
|
|
|
curl "https://document.service.cz/publicapi/v1/upload_hierarchy" -H "Authentication: kjdkKJDWDHWOnc39KCJSKS"
|
|
|
|
```
|
|
|
|
|
|
|
|
### HTTPS Requirements
|
|
|
|
* `GET` for receiving JSON documents
|
|
|
|
* `POST` for sending JSON structured data
|
|
|
|
|
|
|
|
## API Description
|
|
|
|
|
|
|
|
### Obtaining Information about the Service Provider (`service_info`)
|
|
|
|
|
|
|
|
Obtains basic information about the service for the purposes of identifying the service in the client application.
|
|
|
|
|
|
|
|
```
|
|
|
|
GET https://document.service.cz/publicapi/v1/service_info
|
|
|
|
```
|
|
|
|
|
|
|
|
JSON response:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"logo_svg": "base64-encoded service logo",
|
|
|
|
"name": "service name",
|
|
|
|
"token_name": "token identifier"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `logo_svg` contains a string with base64-encoded SVG containing the service logo.
|
|
|
|
* `name` contains the name of the storage service at is should be used by the application.
|
|
|
|
* `token_name` name of the token used for the communication with the service. This serves as a convenient way how to check which token is used.
|
|
|
|
|
|
|
|
### Request for Storage Hierarchy (`upload_hierarchy`)
|
|
|
|
|
|
|
|
Downloads the hierarchy of the 'directories' (nodes, places, etc.) where a (ZFO) file can be uploaded. Initiated via a GET request. Returns JSON hierarchy and response status.
|
|
|
|
|
|
|
|
```
|
|
|
|
GET https://document.service.cz/publicapi/v1/upload_hierarchy
|
|
|
|
```
|
|
|
|
|
|
|
|
The response must consist of a hierarchy of following JSON objects:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"name": "name of the client or document",
|
|
|
|
"id": "location identifier",
|
|
|
|
"metadata": ["some", "additional", "information"],
|
|
|
|
"sub": [{...}, {...}, ...]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Each such JSON object identifies a node and contains the following information:
|
|
|
|
|
|
|
|
* `name` is the name of the node in the hierarchy. May be `null ` if it is the root node and the name of the root should not be displayed/used. When displaying the hierarchy in the client application the value of `name` must be used for filtering or searching.
|
|
|
|
* `id` is a unique string identifier of the place in the hierarchy. The obtained value may be `null` in cases when there is no possibility to upload a file into this location. Empty strings must not be used as `id`. The value of `id` must be used to identify the place where a (ZFO) file (message or delivery info) should be uploaded when using the **upload_file** service.
|
|
|
|
* `metadata` contains an array of strings according to which the location can be searched or filtered on the client site. The array may be empty if no such data are provided. If array is non-empty, then values in the list must be used as additional data for filtering and searching in the hierarchy in the client application.
|
|
|
|
* `sub` contains an array of subordinate nodes (described by similar JSON objects). The array is empty if the node is a leaf.
|
|
|
|
|
|
|
|
**Note:** There is no purpose of sending leaf nodes (i.e. with empty list in `sub`) that have `id` equal to `null` in the response JSON document. Such nodes don't have any sub-nodes nor there is any possibility to upload files into such nodes.
|
|
|
|
|
|
|
|
The following example of an obtained JSON document
|
|
|
|
```
|
|
|
|
{ "name": null, "id": null, "metadata": [], "sub":
|
|
|
|
[
|
|
|
|
{ "name": "Prvni Klient", "id": null, "metadata": ["jednicka", "12582"], "sub":
|
|
|
|
[
|
|
|
|
{ "name": "Prvni spis", "id": "af51ef52yx", "metadata": ["jednicka", "v supliku"], "sub": [] },
|
|
|
|
{ "name": "Druhy spis", "id": "af51ef52yz", "metadata": ["jednicka", "taky v supliku"], "sub": [] }
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{ "name": "Druhy Klient", "id": null, "metadata": ["jednicka", "12582"], "sub":
|
|
|
|
[
|
|
|
|
{ "name": "Dalsi spis", "id": "aabbccddee", "metadata": [], "sub": [] }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
could be interpreted in the following manner:
|
|
|
|
```
|
|
|
|
(root) [ Not shown, because no name was provided. ]
|
|
|
|
|
|
|
|
|
+- "Prvni Klient" [ Does not have an id - data cannot be uploaded here. But additional data for filtering are provided. ]
|
|
|
|
| |
|
|
|
|
| +- "Prvni spis" [ Has an id. Additional data for filtering are also provided. ]
|
|
|
|
| |
|
|
|
|
| +- "Druhy spis"
|
|
|
|
|
|
|
|
|
+- "Druhy Klient"
|
|
|
|
|
|
|
|
|
+- "Dalsi spis" [ Has an id. No additional data for filtering are provided. Only the name is used for filtering. ]
|
|
|
|
```
|
|
|
|
|
|
|
|
### Upload a ZFO File into the Storage (`upload_file`)
|
|
|
|
|
|
|
|
Uploads a given (ZFO) file into a given place in the storage hierarchy. A JSON document is sent via a POST request. The JSON document from the response contain the id of the stored file, description where the ZFO file is stored (i.e. all locations) or an error description.
|
|
|
|
|
|
|
|
```
|
|
|
|
POST https://document.service.cz/publicapi/v1/upload_file
|
|
|
|
```
|
|
|
|
|
|
|
|
JSON request:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"ids": [ "af51ef52yx", "aabbccddee" ],
|
|
|
|
"file_name": "ZFO file name",
|
|
|
|
"file_content": "base64-encoded file content"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `ids` is an array of location identifiers (strings) where the file should be uploaded. The identifiers are obtained by using the **upload_hierarchy** service and correspond to the content of selected `id` entries. At least one location identifier must be provided.
|
|
|
|
* `file_name` is the actual name of the uploaded ZFO file. The string should not be empty.
|
|
|
|
* `file_content` is a base64-encoded string containing the content of the uploaded file. This string must not be empty.
|
|
|
|
|
|
|
|
JSON response:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"id": "uploaded file identifier",
|
|
|
|
"error": {
|
|
|
|
"code": "error code",
|
|
|
|
"description": "explanatory error description"
|
|
|
|
},
|
|
|
|
"locations": ["here", "and here", "and also here", ...]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `id` is the identifier of the uploaded file. It must be `null` if the upload fails and the file is not already located in the storage service. The value of `id` is generally a string and does not have to correspond to the message identifier (as used in ISDS). The sole purpose is to provide the information that the file has been uploaded or is already present in the service. If the upload fails (for any reason) and it could not be determined whether the file is already present in the service then the value must be `null`.
|
|
|
|
* `error` contains `null` if the upload succeeded or a JSON object containing an error description if the upload fails for some reason. Value of `error` cannot be `null` if the value of `id` is `null`.
|
|
|
|
* `locations` is an array of all locations (human readable strings corresponding to `name` entries of **upload_hierarchy** response) where the document has been stored (including the new location) immediately after finishing the upload attempt. The list may be empty if the current upload fails and the uploaded file is nowhere to be found in the document service. The list serves for informative purposes such as notifying the user where the file is located. These values may be cached by the client application and may be used to indicate the presence in the document service by the client application.
|
|
|
|
|
|
|
|
'error' (if it is not `null`) is always a JSON object containing:
|
|
|
|
* `code` is a string holding one of the defined set of strings (codes).
|
|
|
|
* `description` is a string containing a more detailed description of the error. This value may be displayed by the client application on error occasions.
|
|
|
|
|
|
|
|
Values of error `code` in **upload_file** responses:
|
|
|
|
* `"UNSPECIFIED"` - unspecified internal error; `description` should give a more or less detailed explanation of what has happened.
|
|
|
|
* `"MALFORMED_REQUEST"` - the JSON request is corrupt.
|
|
|
|
* `"MISSING_IDENTIFIER"` - no identifier was supplied in the request.
|
|
|
|
* `"WRONG_IDENTIFIER"` - at least one wrong identifier was supplied in the `ids` section of the request. The description should contain a list of all wrong identifiers that have been supplied in the request.
|
|
|
|
* `"UNSUPPORTED_FILE_FORMAT"` - uploaded file format is not supported (i.e. is not a ZFO file or the ZFO file is corrupt).
|
|
|
|
* `"ALREADY_PRESENT"` - the file is already present in the selected location; `description` should contain the name of the location where the file was intended to be stored the name of the already stored file that corresponds with the uploaded file and a statement that the file is already present.
|
|
|
|
|
|
|
|
**Current status:**
|
|
|
|
|
|
|
|
There is no need for additional error codes.
|
|
|
|
|
|
|
|
**Discussion:**
|
|
|
|
|
|
|
|
1. Should the client application differentiate between data message (**dm**) and a delivery information (**di**)?
|
|
|
|
|
|
|
|
>> ad 1. The document service does not distinguish between data messages (**dms**) and delivery infos (**dis**).
|
|
|
|
>
|
|
|
|
> The problem is, that the Datovka application makes a difference between a **dm** (which contains all the attachment files) and a **di** (which does not contain any attachments but contains only information about the delivery status). Therefore `locations` should be related only to the uploaded **dm** or **di**; `locations` must not mix **dms** and **dis** with equal ISDS identifier to prevent any confusion in Datovka application.
|
|
|
|
|
|
|
|
### Query for ZFO Files Held within the Record Management (**stored_files**)
|
|
|
|
|
|
|
|
Queries the storage service for the presence of data messages or delivery information files.
|
|
|
|
|
|
|
|
```
|
|
|
|
POST https://document.service.cz/publicapi/v1/stored_files
|
|
|
|
```
|
|
|
|
|
|
|
|
JSON request:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"dm_ids": ["125682", "124345", ...],
|
|
|
|
"di_ids": ["586445", "4557373", ...]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `dm_ids` is a list of data message identifiers (strings holding integer numbers as used by ISDS) whose location in the record management service we want to obtain. The list may be empty.
|
|
|
|
* `di_ids` is a list of delivery info identifiers (strings holding integer numbers as used by ISDS) whose location we want to obtain. The list may be empty.
|
|
|
|
|
|
|
|
We use strings containing positive integers because of the ambiguity in integer representation/size when converting from/to JSON on various architectures/implementations. We need to ensure that 64-bit integers are safely accommodated within the structure. It is necessary that 64-bit integers are used when converting these identifiers to numbers as the ISDS data message identifiers are soon going to exceed the range of 32-bit integers.
|
|
|
|
|
|
|
|
Means how to limit the amount of queried files within a single request are provided. The service provider needs to make sure that every batch will be processed in time (therefore the limit to the size of the batch).
|
|
|
|
|
|
|
|
**Discussion:**
|
|
|
|
|
|
|
|
>> Question is, if we need to differentiate between **dm** & **di**. On our side (SingleCase), those two queries will be implemented in the exactly same way (we don’t differentiate explicitly)
|
|
|
|
>
|
|
|
|
> In Datovka application need to clearly distinguish between a **dm** and a **di**. Primarily we are going to notify the user whether **dms** have been uploaded (ignoring **dis** for a start). We want to avoid any confusion therefore we want a clear information that a specific **dm** or **di** has been uploaded. Here we want to avoid any mistakes which could be introduced by treating **dms** and **dis** in the same manner.
|
|
|
|
|
|
|
|
JSON response:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"dms": [{...}, ...],
|
|
|
|
"dis": [{...}, ...],
|
|
|
|
"limit": 200
|
|
|
|
"error": {
|
|
|
|
"code": "error code",
|
|
|
|
"description": "explanatory error description"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `dms` list of JSON objects identifying the location of the stored files. The list must contain entries for all queried messages.
|
|
|
|
* `dis` list of JSON objects identifying the location of stored delivery information. The list must contain entries for all queried delivery infos.
|
|
|
|
* `limit` integer value greater than zero. The value provides information about the maximal number of identifiers (i.e. sum of **dm** and **di** identifiers) that can be processed within a single query. This value must be returned always (regardless whether the request succeeded or failed). Recommended (it is only a estimation now) limit is 200, but may be (dynamically) changed by the service operator. Changes in the limit should not happen very fast - time must be given for the client to adapt to the newly acquired limit (an immediate request obeying a freshly received `limit` value should be almost guaranteed to succeed).
|
|
|
|
* `error` contains `null` if the operation succeeds or an JSON object describing the error.
|
|
|
|
|
|
|
|
Proposed values of error `code`:
|
|
|
|
* `"UNSPECIFIED"` - unspecified internal error; `description` should give a more or less detailed explanation of what has happened.
|
|
|
|
* `"MALFORMED_REQUEST"` - the JSON request is corrupt.
|
|
|
|
* `"WRONG_IDENTIFIER"` - at least one wrong identifier (i.e. empty string, a string that does not contain a positive integer) was supplied in the request. The description should contain a list of all wrong identifiers that have been supplied in the request.
|
|
|
|
* `"LIMIT_EXCEEDED"` - too many identifiers in a single request. The client application should adapt to the value in `limit` and repeat the request.
|
|
|
|
|
|
|
|
JSON object describing a data message entry:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"dm_id": "data message identifier (as used in ISDS)",
|
|
|
|
"locations": ["here", "and here", "and also here", ...]
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
"di_id": "delivery info identifier (as used in ISDS)",
|
|
|
|
"locations": ["here", "and here", "and also here", ...]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `dm_id` and `di_id` are data message (**dm**) and delivery info (**di**) identifiers as used in ISDS and in Datovka application (strings containing positive integers).
|
|
|
|
* `locations` list of all locations where the corresponding message or delivery info is stored. This may be an empty list if the corresponding **dm** or **di** is not stored by the service.
|
|
|
|
|
|
|
|
**Current status:**
|
|
|
|
|
|
|
|
There is no need for obtaining the internal service identifier of the **dms** or **dis**. These identifiers are irrelevant for Datovka application. |
|
|
|
\ No newline at end of file |