Flexperto API Developer Guide (EN)


The Flexperto API is powerful, as it provides most of Flexperto’s functionality programmatically. Whatever your desires, if you need to integrate Flexperto in your CRM or simply require access to individual features, like persisting archives, this guide has you covered.


  • Tenant - A tenant is an Enterprise Customer for which flexperto provides platform services. Tenants are strictly separated and have unique ids which related to their dedicated platform within the flexperto infrastructure. Throughout this document, the tenant demo will be used

  • Platform and Environment - As mentioned prior, a platform is a tenants dedicated and isolated space. In addition, the flexperto infrastructure provides a platform on the following environments:

    • test - an environment without SLA guarantees, meant for integration and implementation purposes. A tenants test platform is available at https://{tenantID (eg. "demo")}.test.flexperto.com

    • live - an environment with SLA guarantees, meant for productive use. A tenants live platform is available at https://{tenantID (eg. "demo")}.live.flexperto.com.

  • Expert - An expert typically is an employee of a tenant. Depending on your business domain, you can read expert for example as agent, broker, consultant or doctor.

  • Customer - A customer is a tenant's end customer, typically the entity a tenant's expert is providing the tenant's business service for

  • Admin - A admin is a special user on a tenant with elevated rights. Administrators have full access to the API, and can impersonate other users when interacting with the API.

  • CRM - A system that is operated by the tenant and provides services for expert's. Typically the services enable:

    • Documenting Communication and Interaction between experts and customers

    • Engaging in Communication between experts and customers (eg. Scheduling an appointment or delivery of legal documentation to a customer)

  • API - The flexpertos Application Programming Interface which is JSON/REST/OpenAPI2.0 based. API-clients can be generated based on the OpenAPI2.0 specification of the flexperto API (for a general introduction to OpenAPI2.0 refer to https://swagger.io/specification/v2/)


The listed use cases have the following requirements for implementation:

  • Administrative access to a dedicated platform.

  • A way of sending HTTP requests to the Flexperto API, be that manually via tools like Postman, or programmatically via a service or CRM.

Base URL Schema

The base URL for any API call follows this schema:

1 https://{tenant}.{environment}.flexperto.com

where {tenant} refers to the tenant ID of your company, e.g. mlpfinanzberatung or quirinprivatbank, {environment} refers to the platform environment, e.g. test or live. The base URL for your use case may look like:

1 2 https://mlpfinanzberatung.live.flexperto.com https://quirinprivatbank.test.flexperto.com

When you encounter {baseurl} in this document, replace it with your own base URL.

Use Cases

The following use cases are recurring journeys that tenants on the flexperto platform want to provide to their experts. All of these use cases are powered by the Flexperto API.


As all following use cases for an Integration require interaction with the flexperto API. Generally, authentication against the flexperto API happens via an API-Key in the form of a JSONWebToken. An API-Key has a direct relation to a User and is valid for 2 years. Therefore an API-Key can be owned by an Expert, a Customer, or even an Admin (which would be a technical user for system integrations in these scenarios). There are two approaches:

  • self-service integration

  • integration via a technical user

Self-Service Authentication

The result of a self-service authentication is an API-Key that is owned by the authenticating User. The API-Key can only be used to act in the name of the user, and can only be obtained if the user is already registered on the flexperto platform and is in possession of email and password he used to sign up on the flexperto platform. Most use cases we have seen do not require self-service authentication, which is why documentation on how this could be achieved is left out here. If your use case requires self-service authentication, please reach out to us.

Administrative Authentication

With administrative authentication, your integration makes use of an API-Key owned by an administrator and therefore has full access to the flexperto API. In order to obtain an administrative API-Key, please log in to your tenant and navigate to the “Create new API Token“ page: https://demo.test.flexperto.com/admin/api/token/new

Once you created an API Key, please copy it and store it somewhere safe. Flexperto does not possess a copy of the API-Token, and can not recover it. You will be redirected to the API Token Management page, which is where you can also create new tokens or redeem old tokens (in case your token expires or you would like to rotate tokens more often than every 2 years).

Treat the API-Key as a secret. As mentioned it grants global read/write access to your tenant. It should never be exposed to anyone except your backend and the maintaining entity for the purpose of debugging and API-Key rotation.

If desired, the Administrative Authentication can also be automated via the API-Key Management API

Expert Provisioning

Most of the services that the flexperto platform provides, require at least an expert to be registered with the flexperto platform. In case of a Self-Service Authentication, an expert will already have registered himself on the flexperto platform, which is why this Scenario is omitted here. In the case of an Administrative Authentication, the expert might not yet be registered on the flexperto platform. As a very first step you should extend the user data of the expert with another property called flexperto_account_id. The property will contain the id of the experts account on the flexperto platform, and you will use it later on as a reference to such. If this property has not been set yet, this is also your datapoint to decide whether to find or create the experts account on the flexperto platform. The primary and unique identifier of flexperto accounts is the email of a user. As such the very first thing you should do, is to verify if the expert has already in some way been registered in the platform using the ListUsers Endpoint:

1 2 3 curl '{baseurl}/api/v2/users/users?limit=1&role=expert&email=max.mustermann@example.invalid' \ -H 'Accept: application/json' \ -H 'api-key: {Your.Api.Key}'

In case the Expert is already registered, the response will include his account:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "items": [ { "id": 53, "salutation": "MR", "firstName": "Max", "lastName": "Mustermann", "email": "max.mustermann@example.invalid", "roles": [ "EXPERT" ], } ], "count": 1, "offset": 0, "limit": 20, "total": 1 }

In this case, you should store the id as the previously mentioned flexperto_account_id and stop the routine. If the account does not exist yet, it’s time to create it via the CreateUser Endpoint:

1 2 3 4 5 curl '{baseurl}/api/v2/users/users?supressMails=true' \ --request POST \ -H 'Accept: application/json' \ -H 'api-key: {Your.Api.Key}' --data '{"salutation: "MR", "firstName": "Max", "lastName": "Mustermann", "password": "pssst", "email": "max.mustermann@example.invalid", "roles": ["EXPERT"]}'

The response will again include the id property, which should store as mentioned flexpert_account_id.

You might have recognized the additional query parameter supressMails. This query parameter is a general-purpose parameter that is available on every endpoint that would cause an email to be sent out. If set to false for this endpoint, the user would receive a confirmation email. If you do not want the expert to be notified, feel free to set it to false - which is recommended for this UseCase

You might have recognized that a password has to be provided. We recommend to generate a strong random value here and to not save or share it with the expert. This would also mean that once registered in this way, the expert would not be able to login to the flexperto platform using the username/password method. For most use cases this is fine since it is desired that platform access happens from within the back end. If you anyways require a login-by-link method, please approach us. SAML login will of course still be possible - which is recommended at all times.

Next, the email address of the account needs to be confirmed. In a non-integration scenario, the expert would have received an email with a confirmation link. In an integration scenario, it is up to you to confirm the email address. In most cases, the email address of the expert is already confirmed, which means you can simply continue with confirming the email using the ConfirmEmail Endpoint:

1 2 3 4 5 curl '{baseurl}/api/v2/users/users/53/confirm?supressMails=true' \ --request POST \ -H 'Accept: application/json' \ -H 'api-key: {Your.Api.Key}' --data '{"salutation: "MR", "firstName": "Max", "lastName": "Mustermann", "password": "pssst", "email": "max.mustermann@example.invalid", "roles": ["EXPERT"]}'

Note the usage of the additional query parameter supressMail

Once you did run through these steps, the expert is registered on the flexperto platform and his account is fully functional. You now, in addition, have access to the experts flexperto_account_id which you will require for subsequent use cases.

Starting a Video-Call

A common use case is to enable experts to start a video-call from within the service or CRM. Typically a button to do so is placed in relation to a customer (for example on a single view of a customer). Assuming, such a button has been implemented in the service or CRM, once the expert clicks on the button, you will have to first obtain the customer's personal data and the experts flexperto_account_id from your persistence layer. Using this data, you can perform the following API Call:

1 2 3 4 5 6 curl '{baseurl}/api/v2/communication/meetings/reserve?supressMails=true' \ --request POST \ -H 'Accept: application/json' \ -H 'x-user-id: {flexperto_account_id}' \ -H 'api-key: {Your.Api.Key}' --data '{"access_link_valid_until: "2020-08-27T11:00:00.000Z", "access_link_not_before": "2020-08-27T13:00:00.000Z", "participants": [{"email": "john.doe@example.invalid", "firstname": "John", "lastname": "Doe"}]}'

The API-Call will cause a meeting to be reserved on the flexperto Platform. The meeting will be moderated by the expert with the given flexperto_account_id, and given participants will be able to initially participate (inviting additional participants from within the meeting room, later on, is obviously still possible). Strictly speaking, no information about other participants is required (the participants property can very well have a value of [{}]). However, we do recommend to hand over information that is available, since it eases use and improves the User Experience by personalizing the Meeting Room (eg. showing the name of the participants).

As a response the API will return:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "id": 15, "moderator": { "link": "https://demo.test.flexperto.com/xyz }, "participants": [ { "email": "john.doe@example.invalid", "firstname": "John", "lastname": "Doe", "link": "https://demo.test.flexperto.com/abc "meta": {} } ] }

The response contains a few important things to note:

  • First, there is the id (from here on referred to as the meetingId). Upon successful response, you should document in the service or CRM, that the expert started a Video-Call with the customer, and save the meetingId next to the documentation. The meetingId will, later on, be required for obtaining flexperto side documentation of the call.

  • Next, there is the moderators join link. Using this link, anyone can authenticate as the expert, and will immediately join the meeting.

  • For each participant included in the meeting, an individual link is generated and returned. These links also authenticate the user as the related participant and forward him immediately into the meeting.

All links are only valid for a limited amount of time. Which timespan this is, you can define when reserving the meeting (access_link_valid_until and access_link_not_before). You can now redirect the expert to the moderators join link - he will automatically join the Video-Call and wait for the customer to join.

The links use Compressed JSONWebTokens for authentication, PII that you initially specified is included in these links. Keep in mind that JSONWebTokens by nature are secure, but NOT private.

Note the usage of the additional query parameter supressMail. When set to false, the flexperto platform will immediately send out invitation emails to all participants. The invitation emails will include the join links for them to join. If you set supressMail to true, the platform will not deliver any links to any participant. In this case, the transport and delivery is up to you to handle.

Recording conferences

Flexperto affords experts to record conferences in one of two ways: automated, or manual. Administrators of a platform can enable either by toggling the enableAutomaticRecording (for automatic) or enableRecordingVerbalConsent (for manual) configuration settings. Note that these are mutually exclusive. Recordings include all streamed media (video, audio, shared screens) in one combined video file (codec information: video: h264, audio acc, format: mp4).

How can I record a conference?

Automated recordings start immediately, as soon as any participant of a conference begins enabling their camera, microphone, or shares their screen. It does not stop until the conference has ended and all participants have stopped streaming media.

Manual recordings can be started by the expert, by clicking the start recording button in the menu. A popup will appear, prompting the expert to ask participants for consenting to the recording. Once approved, the recording will start, and won’t stop until the expert manually stops it, or the conference has ended and all participants have stopped streaming media.

How can I retrieve a recorded conference?

Currently, recordings can only be retrieved as part of an archive.

Archiving (MiFID II)

Flexperto provides archiving of all data associated with a business interaction between the expert and their customers. Administrators of a platform can enable archiving by toggling the enableAutomaticArchivingOfConferences configuration setting.

What is in an archive?

The archive file is a single, compressed file (zip) that holds aggregated information about a conference, including data such as:

  • folder whiteboard:

    • whiteboard event history (JSON)

    • uploaded documents (binary)

  • folder themis:

    • text-chat history (JSON)

    • uploaded files (binary)

    • multimedia recordings of video and audio tracks and shared screen (mp4)

    • metadata of the conference (JSON), including (but not limited to):

      • the tenant ID

      • moderator E-Mail, name, and account ID

      • participant E-Mails and names (when given), account IDs, and permissions

      • start and end date-time of the conference

  • folder mithra:

    • contracts signed via E-Signature as part of a conference (PDF), this does not include asynchronous contract sessions created on the dashboard

Archive files are kept on the platform until they are claimed, at which point they enter an expiration period. After a short delay (3 days by default), the archives are deleted.

The archive record (retrievable via the API) is a JSON object describing relevant associative data of the archive, including conference start and end dates, expert and participant information. The object structure is described in the CommunicationConferencesArchiveResponse model in our API documentation.

Are archives guaranteed to be immutable?

On creation, an archive file is hashed, and its hash is stored in the archive record. In retrospect, this hash can be used to verify the integrity of the archive. If a notification is registered against the Flexperto API (see below), consumers are also immediately notified of the available archive, including the hash.

How can I interact with the flexperto API to manage my archives?

These API endpoints are relevant for the archiving process:

Colloquial Name



Colloquial Name



list archive records

GET /communication/conferences/archives

Lists all available archive records of the tenant

get archive record

GET /communication/archives/archives/{archiveId}

Finds a single archive record by its unique ID.

download archive

GET /communication/archives/archives/{archiveId}/download

Downloads the compressed archive file.

abandon archive

POST /communication/conferences/conferences/{conferenceId}/archive/abandon

Abandons an archive, which signals that it has been claimed. After an archive has been abandoned, it is marked for deletion, which is triggered three days after abandoning it.

register webhook

POST /communication/notifications/notifications/webhook

Registers a webhook that is triggered once an archive becomes available.


These endpoints can only be accessed by via API token by authenticated admins of the platform.

What is the life cycle of an archive?

Assuming a conference has been recorded, and the archiving feature is enabled on the platform, an archive is created:

  1. While being processed, the archive transitions through several internal states that mark steps in creating the archive (PROCESSING, ARTIFACT_GATHERING_COMPLETE, PACKING). In these states, the compressed file is not yet available, and can not yet be downloaded via the download archive endpoint.

  2. Once all data has been aggregated, and the zip finalized, the status transitions to AVAILABLE. Now the archive can be downloaded via the API.

  3. If there have been any failures in the process, the status is set to FAILED, and the error field describes the failure.

  4. When the abandon archive endpoint has been called, the archive is scheduled for expiration. The status changes to ABANDONED. In the expiration period (which defaults to 3 days), the archive file can still be downloaded via the download archive endpoint.

  5. After the expiration period has passed, the archive record transitions to the EXPIRED status and the file can no longer be downloaded via the download archive endpoint. The file is deleted from the flexperto platform.

When are archives deleted?

Archives are not automatically deleted, unless they are claimed, by calling the abandon archive endpoint.

How can I claim archives?

How, specifically, you can integrate the flexperto archiving process into your service or CRM depends on your business processes. We offer two distinct approaches for claiming archives, registering a webhook, or regularly polling the API. The code examples are using bash, but any language can be used.

Approach: Registering a webhook

This approach includes registering a webhook against the flexperto API, which is triggered when an archive becomes available.

Step 1: Create a server with a new endpoint. The service should expose a public POST endpoint, for example, POST https://internal.mycompany.de/callbacks/archive, that receives callbacks from flexperto in JSON format. The received notification POSTed against your callback follows the ProduceNotificationRequest model in our API documentation, where the data field is populated with the archive-id and archive_subject. A notification would look like the following snippet.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "data": { "archive_id": "abc123", "archive_subject": { "conference_id": "xzy789", "meta": {/* flexperto conference data */} } }, "meta": { "audience": "*", "tenant": "mycompany", "topic": "archive.available" } }

Step 2: Register the webhook. Replace {api-key} with your API token, and {your-callback-url} with the previously exposed endpoint, e.g. https://internal.mycompany.de/callbacks/archive.

1 2 3 4 5 curl '{baseurl}/api/v2/communication/notifications/notifications/webhook' \ -X POST \ -H 'api-key: {api-key}' \ -H 'Content-Type: application/json' \ -d '{"topic": "archive.available", "audience": "*", "url": "{your-callback-url}"}'

Step 3: On receiving a notification for an available archive, extract the archiveId from response.body.data.archive_id and the conferenceId from response.body.data.archive_subject.conference_id. You will need both later.

Step 4: Download and persist the compressed file. The response here will be a 302 (Found), redirecting to our S3. We recommend that you persist the file in your object storage of choice (e.g. S3). Replace {archiveId} with what you extracted in step 3.

1 2 3 curl '{baseurl}/api/v2/communication/archives/archives/{archiveId}/download' \ -X GET \ -H 'api-key: {api-key}'

Step 5: Signal that you have claimed the archive by calling the abandon archive endpoint. This will change the archive status to ABANDONED. Replace {api-key} and {conferenceId} as before.

1 2 3 curl '{baseurl}/api/v2/communication/conferences/conferences/{conferenceId}/archive/abandon' \ -X POST \ -H 'api-key: {api-key}'

Step 6: We recommend persisting the archive record in your database of choice for an easier association between archive files, archive records, and your own compliance business processes. At the very least, persist the conferenceId, archiveId and sha256CheckSum fields.

Approach: Polling the API on a regular schedule

This approach involves running a script on a regular basis, via cron job, MongoDB agendas, Postgres pg_cron, etc. As part of your back end, regularly query all available archives from the flexperto API, and persist them.

Step 1: Fetch all available archives. Replace {api-key} with your API token.

1 2 3 4 curl '{baseurl}/api/v2/communication/conferences/archives \ -X GET \ -H 'Accept: application/json' \ -H 'api-key: {api-key}'

The response will be an object, which includes the key items, which holds the list of available archive records.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 { "items": [ { "id": "000000000000000000000000", "tenant": "CUSTOMER", "sha256CheckSum": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "subject": { "conference_id": "BBBBBBBBBBBBBBBBBBBBBBBB", "meta": { "moderator": { "account_id": "9999", "firstname": "Max", "lastname": "Musterman", "email": "max.musterman@flexperto.com" }, "tenant": "CUSTOMER", "meeting_id": "9999", "participants": [ { "permissions": { "presenting": true, "publishing": true }, "connection_ids": [], "created_at": "2021-01-01T00:00:00.000Z", "updated_at": "2021-01-01T00:00:00.000Z", "account_id": "9999", "firstname": "Max", "lastname": "Musterman", "email": "max.musterman@flexperto.com" }, { "permissions": { "presenting": false, "publishing": true }, "connection_ids": [], "created_at": "2021-01-01T00:00:00.000Z", "updated_at": "2021-01-01T00:00:00.000Z", "account_id": "8888", "firstname": "Marianne", "lastname": "Musterman", "email": "marianne.musterman@google.com" }, ], "created_at": "2021-01-01T00:00:00.000Z", "updated_at": "2021-01-01T00:00:00.000Z", "closed_at": "2021-01-01T00:00:00.000Z", } }, "status": "AVAILABLE", "fileId": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", "created_at": "2021-01-01T00:00:00.000Z", "updated_at": "2021-01-01T00:00:00.000Z", } ], "limit": 100, "offset": 0, "total": 1 }

Step 2: For each archive, extract the id as archiveId, and the subject.conference_id as conferenceId. Download and persist the compressed file. Replace {api-key} as before, and {archiveId} with the archive ID you extracted. The response here will be a 302 (Found), redirecting to our S3. We recommend that you persist the file in your object storage of choice (e.g. S3).

1 2 3 curl '{baseurl}/api/v2/communication/archives/archives/{archiveId}/download' \ -X GET \ -H 'api-key: {api-key}'

Step 3: Signal that you have claimed the archive by calling the abandon archive endpoint. This will change the archive status to ABANDONED. Replace {api-key} and {conferenceId} as before.

1 2 3 curl '{baseurl}/api/v2/communication/conferences/conferences/{conferenceId}/archive/abandon' \ -X POST \ -H 'api-key: {api-key}'

Step 4: We recommend persisting the archive record in your database of choice for an easier association between archive files, archive records, and your own compliance business processes. At the very least, persist the conferenceId, archiveId and sha256CheckSum fields.


Linking to Expert Profiles