Using the ABRA Flexi REST API opens up a wide range of possibilities for integrating the system with other applications and automating common processes. However, to ensure that your integration works reliably and efficiently, you need to follow certain rules and best practices. The right approach saves developers time, reduces the load on the system, and prevents unnecessary errors when working with data.
This article focuses on recommended best practices that will help you get the most out of the API – from query optimization, proper pagination, and retry strategies to working with error codes and understanding them. You will also learn how to avoid duplicates, how to work with limits, and why it is important to think about security and data consistency from the very start of your integration design.
The goal is not just to "get the data," but to do so efficiently – with regard to system performance, security, and the reliability of the entire integration.
Authentication and security
Secure authentication
Authentication is a fundamental element of security when working with the REST API. If it is not set up correctly, sensitive data may be leaked or the system may be accessed without authorization. It is therefore necessary to use secure methods for logging in and transferring data, and to avoid outdated or risky practices that could compromise the security of the entire integration.
Always carry out all communication over HTTPS so that data is encrypted in transit.
Never send passwords in the URL (they are visible in logs and browser history).
Use only API users with correctly configured permissions. Make sure that the credentials have only the permissions that are actually needed (the principle of least privilege).
Secure handling of credentials
Credentials (usernames, passwords, API tokens) are the key to your data. If they fall into the wrong hands, a serious security incident may occur. It is therefore necessary to handle them with the utmost care and to follow best practices that minimize the risk of leakage.
Never store credentials directly in code (hard-coding). Use configuration files or a secrets management system (Secrets Manager, Vault).
Do not share tokens or passwords in emails or chats, where they could be intercepted.
Rotate tokens and passwords regularly and limit their validity period if the system allows it.
Store sensitive data securely – for example, encrypted in a database or in secure storage.
Use separate accounts for test and production environments to avoid mix-ups.
Query optimization and efficient data handling
The goal is not to "download everything," but to quickly get exactly what you need, with minimal load on both the network and the server. Think about how you use the data: what you will actually display, how often it changes, whether you need to load it immediately, or whether part of it can be precomputed or cached. Well-designed queries and data flows shorten response times, conserve API limits, and increase the stability of the entire integration.
Query only the necessary fields – limit the selection to specific columns (level of detail); smaller payload = lower latency.
Use filters and pagination – transfer only relevant records (filtering).
Pagination - query records in batches (pagination). In the cloud, pagination over the journal (accounting ledger) is not allowed – it places an extreme load on the database, which is why it is blocked.
Batch operations - it is more efficient to send one bulk batch than hundreds of individual requests. The whole batch counts toward the daily limit as one request.
Response caching – store the results of frequently used queries (code lists and rarely changing lists)
Changes API and webhooks
You do not have to download all the data again – it is more efficient to retrieve only the changes. Change feeds (Changes API) and push notifications (webhooks) serve this purpose. The Changes API is ideal for reliable delta synchronization driven by the client (polling + cursor), while webhooks are best for quick reaction to events without unnecessary polling. In practice, it is often best to combine both approaches.
Working with delta export
Instead of downloading the entire record set on every synchronization, it is better to retrieve only what has actually changed. Delta export significantly reduces data transfers, lowers the load on the API and database, and speeds up the integration – especially for larger record sets or regular reporting.
Use the
lastUpdatefield to load only new or changed records.In BI integrations, often used for accounting reports, download data incrementally rather than the entire history.
Store the time of the last synchronization and load only the delta changes from that point onward.
Limits and load
Parallel requests
When working with the REST API, do not run multiple identical requests at the same time. If this is overdone, the system becomes overloaded, and the result is usually slowdowns or error responses. We block excessive overloading as a last resort, and unblocking may need to be resolved with our support team.
It is therefore a good idea to work with parallel requests carefully and to spread calls out intelligently over time.
Summary in points:
Do not create an avalanche of parallel requests – it may overload the system and result in blocking on our side.
Parallel downloading is fine as long as it stays within the request limit. The key is to wait for a response before sending the next request – do not send, for example, 1,000 requests at once.
Spread out the load and group requests into logical sequences.
For more demanding endpoints (e.g., payment matching or document recalculation), wait for a response before sending the next request.
Throttling & Retry
When communicating with the API, a situation may arise in which the server rejects further requests because it is currently overloaded. This typically manifests as the error code 429 – Too Many Requests.
In such a case, it is not advisable to retry the request immediately, as this would increase the load even more. The correct practice is to use so-called exponential backoff – that is, gradually increasing the waiting time between subsequent attempts.
If you receive a 429 error or the server reports an overload, do not retry immediately.
Use exponential backoff – after each unsuccessful attempt, increase the waiting time (e.g., 1s → 2s → 4s → 8s).
This gives the system time to process previous requests and increases the chance that the next attempt will succeed.
Rate limiting
Respect the daily request limit. The default limit for your license may differ depending on the volume purchased.
Number of API requests | Included | up to 50,000 / day | up to 100,000 / day | up to 200,000 / day |
ABRA Flexi Basic | 5,000 / day | not available as an add-on | not available as an add-on | not available as an add-on |
ABRA Flexi Business | 10,000 / day | CZK 1,000 / month | CZK 2,500 / month | CZK 5,000 / month |
ABRA Flexi Premium | 20,000 / day | CZK 1,000 / month | CZK 2,500 / month | CZK 5,000 / month |
ℹ️ Daily limits apply to cloud usage. No API limits apply on your own server or in a private cloud.
Reliability
Working with HTTP error codes
Correctly evaluating HTTP error codes is key to a reliable integration. Each code has its own meaning and helps distinguish whether the problem is on the client side (bad request, invalid data, missing permissions) or on the server side (temporary unavailability, internal error). This allows the application to respond correctly – either by fixing the data and resending the request, or by waiting and trying the action again later.
Distinguish 4xx errors (client errors) – usually a bad request that you must fix (e.g., a missing parameter, an invalid value, access without permission).
Distinguish 5xx errors (server errors) – a temporary problem on the API side; it is advisable to repeat the action later (e.g., a service outage).
Set up error alerts – if the API starts returning a large number of 4xx or 5xx responses, you need to know about it. On the client side, it pays off to log and monitor such situations.
Error message table
Code | Mapper | Message | Explanation |
400 | NamedUsersLimitExceededExceptionMapper | Your license does not allow you to create a user of type '%p'. To modify your license, please contact the ABRA Flexi sales department. | You have no free access slot for another user; you need to purchase an additional license. |
400 | WSUserEmailDuplicatedExceptionMapper | This email is already used by another user. | The email address is already registered in the system. |
400 | OldAppServerExceptionMapper | The database version of company %p is newer than the ABRA Flexi server version. | The database was created in a newer version of the system than your server. |
400 | PgRestoreRTExceptionMapper | (general message from the exception) | The database restore failed; the system returns a technical error. |
400 | QueryExceptionMapper | (general message from the exception) | The database query is incorrect or invalid. |
400 | UnsupportedOperationExceptionMapper | (general message from the exception) | The requested operation is not supported by the system. |
400 | WSAccessDeniedExceptionMapper | You do not have access to this action. | You do not have permission to perform this action. |
400 | WSApplicationExceptionMapper | (composite messages from the exception and its causes) | An application error occurred; details are provided in the message. |
400 | WebApplicationExceptionMapper | Invalid JSON format: %p | The data is in the wrong format and the system cannot read it. |
400 | InternalErrorMapper | (for WSUserErrorException – general message) | A user error occurred in the application. |
400 | LocalizedBusinessException | General localized exception | A business error occurred (e.g., in settings or data). |
400 | MissingParameterException | Parameter '%p' is required for requested operation | A required value is missing from the request. |
400 | IncompatibleParameterValuesException | Parameters %p have incompatible values! | The combination of parameters is invalid. |
400 | IllegalParameterFormatException | Parameter '%p' is expected in the format '%p'. | The parameter value is not in the correct format. |
400 | ErrorParsingFileException | The file could not be read because: '%p'. | The system was unable to read the file (invalid content or format). |
400 | UnsupportedParameterValueException | Parameter '%p' has unsupported value! Choose one from following options: %p | The value entered is not supported; choose one of the allowed values. |
402 | PaymentRequiredExceptionMapper | The feature is not enabled in the license. | You do not have a license to use this feature. |
403 | ActionNotSupportedExceptionMapper | This action is not supported here. | The feature is not available in this context. |
403 | LicenseExpiredExceptionMapper | (general message from the exception) | The license has expired. |
403 | NotAuthorizedExceptionMapper | (general message from the exception) | You do not have permission to access this. |
403 | UnauthorizedExceptionMapper | (general message from the exception) | The access attempt was denied due to missing permissions. |
403 | WarrantyExpiredException | You are attempting to update the data source to a newer version of ABRA Flexi than your paid Annual Support service entitles you to… | You do not have active annual support, which is required to install a new version. |
403 | CompanyAccessForbiddenException | Your access to the company's accounting is blocked. | You are not allowed to access this company. |
404 | CompanyNotFoundExceptionMapper | Company %p does not exist. | The requested company was not found. |
404 | NotFoundExceptionMapper | The address is not valid. / The address %p is not valid. | The URL is incorrect or does not exist. |
404 | UserNotFoundExceptionMapper | User '%p' does not exist. | The user was not found. |
404 | WSApplicationExceptionMapper | (for WSObjectNotFoundException) | The requested object was not found. |
406 | UnsupportedOutputFormatExceptionMapper | (general message from the exception) | The requested output format is not supported. |
409 | ConcurrentAccessExceptionMapper | (general message from the exception) | The operation cannot be performed because someone else is working with the data. |
429 | TooManyRequestsException | This company is currently processing a large number of earlier requests; please wait. | There are too many simultaneous requests; try again later. |
500 | InternalErrorMapper | (for general exceptions – general message) | An unexpected server error occurred. |
500 | ResourceNotFoundException | Requested resource '%p' was not found | The requested resource was not found. |
503 | ServiceUnavailableException | The service is currently unavailable; please try again later. | The service is temporarily unavailable; try again later. |
503 | ServerStartingException | The server is starting; please wait. | The server is starting up; you need to wait a moment. |
503 | CompanyStateException | Company '%s' is in '%s' state. | The company is in a different state (e.g., locked, under maintenance) and cannot be worked with. |
Idempotency
When writing data through the API, it is important to ensure that a repeated request is not processed multiple times and does not create duplicates. A typical situation occurs when a connection drops or a retry strategy is used – the client is not sure whether the request went through and sends it again. Without idempotency, multiple invoices, orders, or other documents could be created, which is a problem especially in accounting.
For write operations, always make sure that a repeated request does not create a duplicate record.
Use an external ID – when creating a new record, assign it an identifier from the source database or system the data comes from.
If the same request is sent again with the same external ID, the API returns the original result instead of creating a duplicate.
Example
{
"winstrom":{
"@version":"1.0",
"faktura-vydana":[
{
"id":[
"ext:123",
"code:VF1-0035/21"
],
"popis":"popis"
}
]
}
}
Logging requests and responses
When integrating with the REST API, it is very useful to keep records of the requests sent and the responses received. Logs allow you to quickly find out why something is not working, what the API actually returned, or what request was sent to the server. Logging is also an invaluable aid when communicating with customer support – instead of a vague description such as "something went wrong," you have specific data at your disposal.
Keep logs of all important requests and responses
Keep them at least for a limited period during which you may need to investigate the cause of a problem.
Logs make it easier to debug errors and help determine whether the problem occurred on the client side or the server side.
When working with support to resolve an issue, you can provide the exact request and response, which will considerably speed up finding the cause.
Consistency and versioning
The API evolves over time – new fields are added, and sometimes the format or logic of a response changes. If your application is not prepared for this, it may stop working after a change. It is therefore important to write integrations so that they are resilient to changes, while also keeping track of API developments.
Forward compatibility – design your integration so that it ignores unknown fields and can handle minor format changes.
Follow the change log – regularly check for API changes and verify that they do not affect your integration.
Verify the availability of records – not everything is available through the REST API. For example, payment reminders are currently not available in the API.
User experience & integration
A quality integration is not just about calling the API correctly, but also about how easy it is to deploy, test, and maintain. Separating the test and production environments reduces the risk of errors, as does the right approach to data backups – it is better to handle those through the web interface than through the API.
Test in a sandbox – separate the test and production environments (use a company backup to create a copy of your live data) so that you do not put real data at risk.
Do not use the API for backups in the cloud – download automatic backups from the web application; the API is not primarily intended for this purpose.
Monitoring and management
Without ongoing visibility into how many API calls you make and how often, problems are detected too late. Basic monitoring helps you keep track of limits, tune performance, and prevent integration outages.
Monitor API usage – check the number of requests against daily limits directly in the web application so that you can avoid possible blocking on our side if the limits are exceeded.
Conclusion
Following best practices when working with the ABRA Flexi REST API will help you build stable, secure, and long-term sustainable integrations. Whether it is query optimization, error handling, or secure handling of credentials, it always pays to invest in a sound design from the very beginning.
If you are not sure how to use the API in your specific scenario, or you need more detailed recommendations, you can arrange an individual consultation, where we will be happy to help you with the implementation.
