Skip to main content

Client Documentation

info

this section will be revised and adapted for the certified version 2 of the the fiskaly Cloud-TSS! Version 2 does not need a client or service, you can integrate with a pure HTTPS version.

Overview#

The fiskaly Client is a stateless HTTP client which handles requests, has client-side validation for the request schema and communicates with the SMAERS component. It is shipped as a set of shared libraries for different operating systems and architectures on our download page. The client uses a slightly modified version of the JSON-RPC 2.0 Protocol to describe requests, responses and errors. The only deviation from the specification concerns notifications, which are not implemented and cause an error. Please make sure you are familiar with the JSON-RPC 2.0 specification before continuing.

Changelog#

Functions#

The Fiskaly Client exports two functions:

_fiskaly_client_invoke(CString) CString

_fiskaly_client_invoke is used to invoke a JSON-RPC 2.0 method. It takes a complete JSON-RPC 2.0 request as its argument and returns the client response.

_fiskaly_client_free(CString)

_fiskaly_client_free is used to free memory allocated by Invoke.

Methods#

Parameters marked with a star (*) are optional.

Configuration#

Request#

{
"jsonrpc": "2.0",
"method": "config",
"params": {
* "config": {
* "debug_level": int,
* "debug_file": string,
* "client_timeout": int(ms),
* "smaers_timeout": int(ms),
* "http_proxy": string
},
"context": string
},
"id": int
}

Result#

{
"jsonrpc": "2.0",
"result": {
"config": {
"debug_level": int,
"debug_file": string,
"client_timeout": int(ms),
"smaers_timeout": int(ms),
"http_proxy": string
},
"context": string
},
"id": int
}

The config method lets you configure the client and read the current configuration. It always returns all configuration parameters. You can set timeouts for the client and SMAERS independently, as well as enable the debug mode and configure its output. You can find an in-depth description of the debug mode further down the page. Any given parameters from the config property are written to the configuration. If you only want to read the configuration, you can omit the config property completely from the request. If you don't want use system proxy, use - as a value of http_proxy parameter. To log to stdout use -.

Create new context#

Request#

{
"jsonrpc": "2.0",
"method": "create-context",
"params": {
"base_url": string,
* "api_key": string,
* "api_secret": string,
* "email": string,
* "password": string,
* "organization_id": string,
* "environment": string
},
"id": int
}

Result#

{
"jsonrpc": "2.0",
"result": {
"context": string
},
"id": int
}

To make sure the fiskaly Client is stateless we use a context string that holds all needed information. This string needs to be sent with every method (except the version method) and will also be returned in every response. Make sure to update your stored context with the returned one from the response. Depending on the authentication method you want to use, either API-Key or email and password (latter only usable for the management API), you will need to provide the needed params. This will be either api_key and api_secret or email and password. You can also add all of the mentioned params. The client will prioritize authentication via email if the base_url is for the management API. Otherwise it will always use api_key and api_secret.

To prevent unintentional modification, the context, along with its sha256 hash, is encoded to a base64 string. It is recommended to treat the context as read-only and only use the provided methods to change its contents.

API request#

Request#

{
"jsonrpc": "2.0",
"method": "request",
"params": {
"request": {
"method": string,
"path": string,
* "query": json_object,
* "headers": json_object,
* "body": base64_string,
* "destination_file": string
},
"context": string
},
"id": int
}

Result#

{
"jsonrpc": "2.0",
"result": {
"response": {
"status": int,
"header": json_object,
"body": base64_string
},
"context": string
},
"id": int
}

The request method is used to send HTTP requests. The URL is composed of the Base URL defined in the context and the request path. The Client will automatically validate your inputs. In case of a request to the transaction endpoint of the KassenSichV API the client will also validate the request body and sign it using the SMAERS component.

If your intention is to download a file from one of our APIs (for example in case of an export in the KassenSichV API) you can provide a destination file path. The client will then store the received data in that file. The JSON-RPC response will contain no body in this case.

Version#

Request#

{
"jsonrpc": "2.0",
"method": "version",
"params": {},
"id": int
}

Result#

{
"jsonrpc": "2.0",
"result": {
"client": {
"version": string,
"source_hash": string,
"commit_hash": string
},
"smaers": {
"version": string
}
},
"id": int
}

The version method returns the version information of the currently used client and SMAERS.

Echo#

Request#

{
"method": "echo",
"params": json_object
}

Result#

{
"result": json_object
}

The echo method returns the params field from the request unmodified. This is used to check if the UTF-8 Encoding in the SDK is done correctly.

Self-test#

Request#

{
"method": "self-test",
"params": {
"context": string
}
}

Result#

{
"result": {
"proxy": string,
"backend": string,
"smaers": string
}
}

The self-test method checks the internal state of the fiskaly Client and fiskaly SMAERS and tries to connect to the fiskaly API. It returns the results of all individual tests.

Errors#

The fiskaly Client will return errors as defined in the JSON-RPC 2.0 specification. To provide more detailed information on the error cause, the following additional, custom-defined errors can be returned by the fiskaly Client:

HTTP Error#

{
"jsonrpc": "2.0",
"error": {
"code": -20000,
"message": "HTTP error",
"data": {
"response": {
"status": 400,
"headers": {
"X-Request-Id": ["0123456789"]
},
"body": base64_string
}
}
},
"id": int
}

HTTP Timeout#

{
"jsonrpc": "2.0",
"error": {
"code": -21000,
"message": "HTTP timeout"
},
"id": int
}

Request Error#

{
"jsonrpc": "2.0",
"error": {
"code": -7353,
"message": "Request Error"
},
"id": int
}

Debug mode#

To assist troubleshooting, the fiskaly Client includes a debug mode. When enabled, information with variable granularity will be written to a log file. The verbosity is controlled by the debug_level field in the configuration. Valid debug levels are -1 (no output), 1 (errors only), 2 (errors+warnings) and 3 (errors+warnings+info). The output file can also be set via the config method. Default is /tmp/fiskaly.log. To write logs into stdout, use - as a value of debug_file parameter.

Integration#

1. Load the shared library file#

The client is provided as a native library for common target platforms. Implementation-specific details vary between programming languages, therefore detailed instructions cannot be provided in this context. The necessary function signatures can be taken from the Functions section of this document. As all of our SDKs are OSS, you can always use them as a reference implementation.

2. Create a new context#

The returned context contains the provided parameters and the default configuration. Store the context for future reuse and send it with every request. Any method call may modify the context, so it is important to always update the stored context with the returned one. Modifying the context directly may lead to undefined behavior and is strongly discouraged.

{
"jsonrpc": "2.0",
"method": "create-context",
"params": {
"api_key": "example_uj3hBUmddscBeWYeU9HRpFjgqp4ZTf",
"api_secret": "gBmxxMXN5s4wVuKaaEZCKMGxrZEBJl0iRZfiAbBZefq",
"base_url": "https://kassensichv.io/api/v1/"
},
"id": 1
}

3. Add custom settings#

This step is optional and only needed if you want to override the default configuration parameters.

{
"jsonrpc": "2.0",
"method": "config",
"params": {
"config": {
"debug_level": 2,
"debug_file": "/var/log/fiskaly.log",
"client_timeout": 5000,
"smaers_timeout": 2000,
"http_proxy": "http://127.0.0.1:8080"
},
"context": "T4QgYdRI6YH7vS_CBw0io7R2uK6DgCd3n2kW0TUdcBZ7IndyYXBwZXJfdmVyc2lvbiI6Ik5vIFdyYXBwZXIgVmVyc2lvbiIsImFwaV9rZXkiOiJleGFtcGxlX3VqM2hCVW1kZHNjQmVXWWVVOUhScEZqZ3FwNFpUZiIsImFwaV9zZWNyZXQiOiJnQm14eE1YTjVzNHdWdUthYUVaQ0tNR3hyWkVCSmwwaVJaZmlBYkJaZWZxIiwiYmFzZV91cmwiOiJodHRwczovL2thc3NlbnNpY2h2LmlvL2FwaS92MS8iLCJhY2Nlc3NfdG9rZW4iOiIiLCJyZWZyZXNoX3Rva2VuIjoiIiwiYWNjZXNzX3Rva2VuX2V4cGlyZXNfYXQiOjAsInJlZnJlc2hfdG9rZW5fZXhwaXJlc19hdCI6MCwiY29uZmlnIjp7ImRlYnVnX2xldmVsIjotMSwiY2xpZW50X3RpbWVvdXQiOjEwMDAsInNtYWVyc190aW1lb3V0IjoxMDAwfX0"
},
"id": 2
}

4. Send requests#

The request method receives and returns the message body as base64-encoded binary data. This allows any data format to be uploaded and downloaded.

{
"jsonrpc": "2.0",
"method": "request",
"params": {
"request": {
"method": "PUT",
"path": "/tss/ecb75169-680f-48d1-93b2-52cc10abb9ff/tx/9cbe6566-e24c-42ac-97fe-6a0112fb3c63",
"query": { "last_revision": "0" },
"headers": { "Content-Type": "application/json" },
"body": "eyJzdGF0ZSI6ICJBQ1RJVkUiLCJjbGllbnRfaWQiOiAiYTYyNzgwYjAtMTFiYi00MThhLTk3MzYtZjQ3Y2E5NzVlNTE1In0="
},
"context": "aYqkp0feiGAiyKfcNu9sp0whSGCvaoykbmeC-R90Qcx7IndyYXBwZXJfdmVyc2lvbiI6Ik5vIFdyYXBwZXIgVmVyc2lvbiIsImFwaV9rZXkiOiJleGFtcGxlX3VqM2hCVW1kZHNjQmVXWWVVOUhScEZqZ3FwNFpUZiIsImFwaV9zZWNyZXQiOiJnQm14eE1YTjVzNHdWdUthYUVaQ0tNR3hyWkVCSmwwaVJaZmlBYkJaZWZxIiwiYmFzZV91cmwiOiJodHRwczovL2thc3NlbnNpY2h2LmlvL2FwaS92MS8iLCJhY2Nlc3NfdG9rZW4iOiIiLCJyZWZyZXNoX3Rva2VuIjoiIiwiYWNjZXNzX3Rva2VuX2V4cGlyZXNfYXQiOjAsInJlZnJlc2hfdG9rZW5fZXhwaXJlc19hdCI6MCwiY29uZmlnIjp7ImRlYnVnX2xldmVsIjoyLCJkZWJ1Z19maWxlIjoiL3Zhci9sb2cvZmlza2FseS5sb2ciLCJjbGllbnRfdGltZW91dCI6NTAwMCwic21hZXJzX3RpbWVvdXQiOjIwMDB9fQ"
},
"id": 3
}

Body encoding example#

Plain text (JSON)

{
"body": {
"some-field": 23,
"another-field": "hello, world"
}
}

Base64 encoded

{
"body": "ewogICAgInNvbWUtZmllbGQiOiAyMywKICAgICJhbm90aGVyLWZpZWxkIjogImhlbGxvLCB3b3JsZCIKICB9"
}

5. Download files#

To store the response body in a file, provide a value to the destination_file property. HTTP status and header information will still be returned in the response, but the body will be written to the provided file path.

{
"jsonrpc": "2.0",
"method": "request",
"params": {
"request": {
"destination_file": "/tmp/output.txt",
"method": "GET",
"path": "/something"
},
"context": "aYqkp0feiGAiyKfcNu9sp0whSGCvaoykbmeC-R90Qcx7IndyYXBwZXJfdmVyc2lvbiI6Ik5vIFdyYXBwZXIgVmVyc2lvbiIsImFwaV9rZXkiOiJleGFtcGxlX3VqM2hCVW1kZHNjQmVXWWVVOUhScEZqZ3FwNFpUZiIsImFwaV9zZWNyZXQiOiJnQm14eE1YTjVzNHdWdUthYUVaQ0tNR3hyWkVCSmwwaVJaZmlBYkJaZWZxIiwiYmFzZV91cmwiOiJodHRwczovL2thc3NlbnNpY2h2LmlvL2FwaS92MS8iLCJhY2Nlc3NfdG9rZW4iOiIiLCJyZWZyZXNoX3Rva2VuIjoiIiwiYWNjZXNzX3Rva2VuX2V4cGlyZXNfYXQiOjAsInJlZnJlc2hfdG9rZW5fZXhwaXJlc19hdCI6MCwiY29uZmlnIjp7ImRlYnVnX2xldmVsIjoyLCJkZWJ1Z19maWxlIjoiL3Zhci9sb2cvZmlza2FseS5sb2ciLCJjbGllbnRfdGltZW91dCI6NTAwMCwic21hZXJzX3RpbWVvdXQiOjIwMDB9fQ"
},
"id": 4
}

Subscribe to the Dev-Newsletter