Skills gained:
knowledge of the custom button
implementing acquired knowledge directly in ABRA Flexi
In the previous training sessions, we learned the basics of REST API, a number of clever techniques for retrieving data and sending data to ABRA Flexi. We always had to use external tools — cURL or the Postman application — or copy data retrieval requests directly into a web browser.
In this final training session, we will show how all these techniques can be implemented directly in ABRA Flexi, how to display the functionality within the application, and how to allow users to conveniently trigger an action just like any other — straight from the application.
So if you use various systems or web portals in your work, custom buttons give you direct access to them right from ABRA Flexi. At the basic Apprentice level, we will show how to set it up in the application with a simple example of a button that links to an external application, such as the MFČR portal. At the Warrior level, we will demonstrate implementing a button for one of the REST API techniques we have learned. The API Ninja will see an example of how to connect a custom button to a custom PHP script. The final training is here — get ready, let's dive in!
Level: Apprentice
First, let's define the button. The button is based on Flexi XML documentation, which we already know. The XML can be imported into the application via the menu Tools > Import > Import XML; however, an API student can certainly send it as a request using the API and the POST method:
<?xml version="1.0"?>
<winstrom version="1.0">
<custom-button>
<id>code:MFCR-ARES</id>
<url><![CDATA[
https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_res.cgi?ico=${object.ic}&jazyk=cz&xml=1]]>
</url>
<title>Kontrola IČ</title>
<description>Validace IČ z faktury vydané na ARES</description>
<evidence>faktura-vydana</evidence>
<location>detail</location>
<browser>desktop</browser>
</custom-button>
</winstrom>
Excellent! After importing the button definition, an application restart is required, and our first button is ready.
The custom button register is called custom-buttom. Let's now describe the structure of the request body:
ID — already familiar to us — is the identifier; when creating a custom button, this element must be provided with a code (abbreviation).
URL is the key field — it specifies the URL of the web page or network resource that will be opened when the button is clicked.
The URL must be provided in full, absolute form — i.e., it must include the scheme and the server's domain address (such as our example https://wwwinfo.mfcr.cz/)
We recommend entering the URL in
<![CDATA[ ]]>so that the presence of the '&' character does not result in invalid XML.The
fileURI scheme used for accessing locally stored files is not supported in URL values. Custom button definitions containing URLs withfile://will be rejected as not permitted during import.An important part is the values from the application passed as variables. In our example, we use the company registration number (IČ) from the issued invoice. Variables are evaluated by FreeMarker at application runtime and ensure that values are passed from the application. The string
objectis mandatory in variable names and is used to reference the current record of the selected register.
How did we find out the URL structure for the MFČR portal?
The URL https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_res.cgi?ico=63469588&jazyk=cz&xml=1 was obtained directly from a web browser. Simply search for any company registration number on the MFČR website, then navigate to ARES, and the address will appear in the browser's address bar.
From the URL it is clear that the MFČR website passes the selected company registration number as a parameter in the address — we simply need to replace it with our ${object.ic} from the application, and we're done. Back to the remaining definition fields:
title and description describe the button and are displayed to the user in the application — title is the button name, description is the tooltip shown when hovering over the button with the mouse
evidence is also a very important field — it specifies where the button will be used and displayed, and its value is the register code from the evidence list.
location indicates whether the button will be displayed in the record editing window — detail, or in the register record list view — list
browser specifies whether, after clicking the button, the URL opens in ABRA Flexi's internal browser — automatic, or in an external browser on the PC — desktop
Good — the object is faktura-vydana, but how did we know we could use the company registration number, apprentice?
A sharp apprentice will have noticed that we used the variable ${object.ic} and can surely imagine further possibilities. As mentioned, using the string object we have access to all fields in the register — but that can't be everything, right? There are additional variables that can be used when making a call:
objectIds– a comma-separated list ofIDof selected records. This means that if you check records using the checkboxes in the application, all their IDs will be passed. Important note: the variablesobjectandobjectIdsare mutually exclusive!user– you can also pass the first and last name of the currently logged-in userurl– you can pass the URL from which the button was clicked, for example in our case https://developer.flexibee.eu/c/ninja/faktura-vydana/{ID faktury}.companyUrl– the API address of the company in which the button is placed, in our case https://developer.flexibee.eu/c/ninja.evidence– the name of the register on which the button is placed (faktura-vydana).authSessionId– an authentication token for the current user session. It can be used to authenticate requests for the duration of the session. We were introduced to the authentication token in training session 3 at the Ninja level.customerNo– the customer number corresponding to the license.licenseId– the license identifier.
Apprentice, you now know how to use a custom button. I'm sure you can think of further usage examples — such as calling techniques from previous training sessions or linking to your own external websites. Go for it, the possibilities are endless!
Level: Warrior
At the Apprentice level, we learned the button definition, how to add it to the application, and an example of how to call an external website. Now we will show how to define some of the more advanced REST API services using a custom button. In general, without a custom script, we can only use services and outputs sent via the GET method, since a button cannot trigger a POST request. So what other button can we add to the application without writing a script, given that services and buttons are already available in the application?
First, let's show how to retrieve a PDF of an invoice with a single click. We will place the button in the issued invoices register in the record list view:
<?xml version="1.0"?>
<winstrom version="1.0">
<custom-button>
<id>code:FAV-PDF</id>
<url><![CDATA[${url}.pdf?report-name=NINJAFAV&report-sign=true]]>
</url>
<title>PDF</title>
<description>Stáhnout PDF faktury<description>
<evidence>faktura-vydana</evidence>
<location>list</location>
<browser>desktop</browser>
</custom-button>
</winstrom>
Looking through the definition, we notice that in the <url> field we used the variable ${url} directly. This technique allows us to import the button into any ABRA Flexi instance and always pick up the correct address from which to retrieve the document. We also specified the code of a custom print template NINJAFAV (which must exist) and requested a form signed with a certificate (which must also exist). With a single click, we can now display invoice PDFs in the browser.
Let's move on to another handy button. Directly from the application, we can display the currently logged-in active users. The button definition looks as follows:
<?xml version="1.0"?>
<winstrom version="1.0">
<custom-button>
<id>code:SESSIONS</id>
<url>
<![CDATA[https://developer.flexibee.eu/status/session]]>
</url>
<title>Přihlášení uživatelé</title>
<description>Seznam přihlášených uživatelů </description>
<evidence>uzivatel</evidence>
<location>list</location>
<browser>desktop</browser>
</custom-button>
</winstrom>
Information about logged-in users is located at the page /status/session. The button can again be placed anywhere — this time we choose the register uzivatel — Persons and users.
Warrior, can you figure out why we didn't use the variable companyUrl in the URL? Hint: compare the URL with the contents of the variable.
The last handy button combines our knowledge of data filtering with the capabilities of the custom button. Let's say we need to export to XML every day the invoices that have a due date of today and are still unpaid. We will use filtering, a detail, and the button:
<?xml version="1.0"?>
<winstrom version="1.0">
<custom-button>
<id>code:NEUHRAZENEFAV</id>
<url>
<![CDATA[${companyUrl}${evidence}
/(datSplat=now()%20and%20stavUhrK<>'stavUhr.uhrazeno').xml?
detail=custom:kod,sumCelkem,varSym&limit=0]]>
</url>
<title>FAV bez uhrady</title>
<description>
Faktury vydané se splatnostní dnes a bez úhrady
</description>
<evidence>faktura-vydana</evidence>
<location>list</location>
<browser>desktop</browser>
</custom-button>
</winstrom>
The button definition syntax is already familiar to us. What's interesting in this example is the URL. For demonstration purposes, we use the variables companyUrl and evidence. The button can therefore be used in other registers and companies as well. The rest of the syntax is also familiar — filtering for documents with a due date of today and a payment status of unpaid. The final parameters specify a custom XML detail, and we must remember to set limit=0 to retrieve all invoices in the XML.
Warrior, you now know a wealth of ways to enhance the application for your users!
Level: Ninja
At the Ninja level, we will show how to use a custom button with your own scripts. An example can be seen here. It is a custom query dispatcher written in PHP and triggered by a custom button. But let's walk through our own example — what do you say, Ninja?
Let's consider a scenario where we want to send invoices that are due today and still unpaid to the boss for review. We already know the button definition — for our purposes, the URL element will look slightly different:
<?xml version="1.0"?>
<winstrom version="1.0">
<custom-button>
<id>code:NEUHRAZENEFAV</id>
<url><![CDATA[https://ninja.webserver.cz/PHP/neuhrazene-faktury.php]]></url>
<title>Report neuhrazených FAV</title>
<description>Odešle na email šéfovy neuhrazené faktury</description>
<evidence>faktura-vydana</evidence>
<location>list</location>
<browser>desktop</browser>
</custom-button>
</winstrom>
Notice, Ninja, that the URL element contains the path to a PHP script — for simplicity, we are not even passing any information from Flexi. The script handles everything. Let's go!
The script in our example is very straightforward — the goal of this training is not to learn PHP, but to understand the power of the custom button as one of every API Ninja's most effective techniques.
<?php
include('./httpful.phar');
$flexiLogin = 'ninja';
$flexiHeslo = 1234;
$uri = 'https://developer.flexibee.eu/c/ninja/faktura-vydana/(datSplat=now()%20and%20stavUhrK<>"stavUhr.uhrazeno").csv?detail=custom:kod,sumCelkem,varSym,nazFirmy&limit=0';
$response = \Httpful\Request::get($uri)
->expectsXML()
->authenticateWith($flexiLogin, $flexiHeslo)
->send();
//případné další zpracování odpovědi z Flexi
// příprava zprávy
$to = 'velkysef@ninja.cz';
$subject = 'Nezaplacené faktury';$message = 'Dobrý den, šéfe, zasílám report neplatičů:\n' . $response->body;
//odeslání emailu
mail($to, $subject, $message);
?>
By clicking the button in the application, you can send the boss an overview of unpaid invoices at any time. Or anything else, for that matter. You now know all the possibilities, Ninja — your power with the API is unlimited. You can take on the final challenge and earn your API Ninja certificate!











