# What is Renda.io?

## MICROSERVICES FOR SAP

Renda.io is a microservice platform for SAP ERP and S/4HANA.

It is a powerful SAAS platform from Arch delivering low cost, high value microservices to complement SAP development tools.

Use the library of powerful REST-based APIs to accelerate your enterprise application development.

### DESIGNED FOR SAP

Every Renda.io microservice is designed for SAP developers.  Detailed documentation and sample code for calling each API is supplied, including integrations for  ABAP, SAPUI5 and CONVERSATIONAL AI scenarios.

### EASY INTEGRATION

Use Renda microservices from back-end applications, Fiori apps or chatbots.

<div align="center"><img src="https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MBsuqFhmeYvQwkhzDUn%2F-MKEnUTTS0oF68rXjJgN%2F-MKEna0ItI8vsQMJQVZh%2FRenda1.png?alt=media&amp;token=56d61f51-4515-433f-a956-78f754119b6d" alt="Renda Schematic"></div>

## Microservices&#x20;

Renda offers an array of powerful Rest based APIs to perform a variety functions to accelerate enterprise application development&#x20;

![](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MBsuqFhmeYvQwkhzDUn%2F-MKEpafHqxtBDSHvb47Q%2F-MKEur5Iwp79Vhth2deM%2Ffeatures.png?alt=media\&token=cc4ea649-50a1-47e5-8890-32ac2009967e)


# HTML to PDF

Renda offers a host of transformation functions to support a variety of enterprise document output needs.

## Transform HTML to PDF

With Renda' HTML to PDF transformation API - HTML output can be converted to PDF document. Optionally the  PDF document can also password protected by using AES 256 encryption algorithm. &#x20;

{% hint style="info" %}
API calls are region specific. Please make sure you are subscribed to a specific region before making API calls.
{% endhint %}

## Ping

<mark style="color:blue;">`GET`</mark> `https://api-<region>.renda.io/v2/ping/`

This API perform a heartbeat check to verify if the configuration is all setup correctly from your application. \
\
**Region specific URLs:**\
\
Ireland(Europe): **`https://api-eu.renda.io/v2/ping`**\
North Virginia(US): **`https://api-us.renda.io/v2/ping`**\
Mumbai (Asia Pacific): **`https://api-apac.renda.io/v2/ping`**

#### Headers

| Name      | Type   | Description                                                                              |
| --------- | ------ | ---------------------------------------------------------------------------------------- |
| x-api-key | string | <p>Renda.io API Key<br><br>A valid renda.io user account is required to view API Key</p> |

{% tabs %}
{% tab title="200 Successful Ping" %}

```javascript
{
    "message": "Renda.io ping Successful"
}
```

{% endtab %}

{% tab title="403 Invalid API Key" %}

```
{
"message”:”We are unable to service your request. Things to verify: 
1) A valid API Key should be passed in ‘x-api-key’ request header parameter.
 2) An active Renda.io subscription 3) API being invoked must be Subscribed 
 using the Subscribe button in Renda developer portal. Please refer to Renda 
 documentation for more details - https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## Generate PDF&#x20;

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/v2/generatePDF`

This API enables conversion of HTML and text documents in PDF. Optionally the generated PDF can also be encrypted \
\
Region specific URLs:\
\
Ireland(Europe): `https://api-eu.renda.io/v2/generatePDF`\
North Virginia(US): `https://api-us.renda.io/v2/generatePDF`\
Mumbai(APAC):`https://api-apac.renda.io/v2/generatePDF`

#### Headers

| Name                                        | Type   | Description                       |
| ------------------------------------------- | ------ | --------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | string | Renda API Key                     |
| Accept                                      | string | application/pdf                   |
| Content-type                                | string | application/x-www-form-urlencoded |

#### Request Body

| Name          | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| inputPayload  | string  | HTML payload to transform to PDF format                                                                                                                                                                                                                                                                                                                                                                          |
| encryptionKey | string  | Encryption key to password protect the generated PDF                                                                                                                                                                                                                                                                                                                                                             |
| landscape     | boolean | <p>Paper orientation. <br><br><strong>Defaults to false</strong></p>                                                                                                                                                                                                                                                                                                                                             |
| format        | string  | <p>Paper Format. <br><br><strong>Defaults to A4</strong><br><br>Valid Options: Letter, Legal, Tabloid, Ledger, A0,A1,A2,A3,A4,A5,A6<br><br>Letter: 8.5in X 11in<br>Legal: 8.5in x 14in<br>Tabloid: 11in x 17in<br>Ledger: 17in x 11in<br>A0: 33.1in x 46.8in<br>A1: 23.4in x 33.1in<br>A2: 16.54in x 23.4in<br>A3: 11.7in x 16.54in<br>A4: 8.27in x 11.7in<br>A5: 5.83in x 8.27in<br>A6: 4.13in x 5.83in<br></p> |
| marginTop     | string  | <p>Paper Margin top <br><strong>Defaults to blank</strong><br>Top margin, accepts values labeled with units<br><em><strong>Example: 50px</strong></em></p>                                                                                                                                                                                                                                                       |
| marginRight   | string  | <p>Paper Margin right<br><strong>Defaults to blank</strong><br>Right margin, accepts values labeled with units</p>                                                                                                                                                                                                                                                                                               |
| marginBottom  | string  | <p>Paper Margin bottom <br><strong>Defaults to blank</strong><br>Bottom margin, accepts values labeled with units<br></p>                                                                                                                                                                                                                                                                                        |
| marginLeft    | string  | <p>Paper Margin Left<br><strong>Defaults to blank</strong><br>Left margin, accepts values labeled with units</p>                                                                                                                                                                                                                                                                                                 |
| header        | string  | HTML payload for PDF header                                                                                                                                                                                                                                                                                                                                                                                      |
| footer        | string  | HTML payload for PDF footer                                                                                                                                                                                                                                                                                                                                                                                      |

{% tabs %}
{% tab title="200 A valid PDF document is returned as a success response" %}

```javascript
%PDF-1.4
%����
1 0 obj
<</Creator (Chromium)
/Producer (Skia/PDF m83)
........
....<PDF Content>...
.......
%%EOF
```

{% endtab %}

{% tab title="500 PDF Generation error will be notified via HTTP 500 errors" %}

```javascript
{
"<Error Response from Server>"
}
```

{% endtab %}

{% tab title="403: Forbidden Invalid API Key" %}

```javascript
{
"message”:”We are unable to service your request. Things to verify: 
1) A valid API Key should be passed in ‘x-api-key’ request header parameter.
 2) An active Renda.io subscription 3) API being invoked must be Subscribed 
 using the Subscribe button in Renda developer portal. Please refer to Renda 
 documentation for more details - https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}


# PDF Transformation

The following API services are now available for PDF transformation.

* [Convert PDF to PNG image](#transform-pdf-to-png-image)
* [Convert PDF to Postscript ](#transform-pdf-to-postscript)

{% hint style="info" %}
PDF transformation APIs are available in EU region only. Please make sure you are subscribed to a specific region before making API calls.
{% endhint %}

## Transform PDF to PNG image

Convert single and multi page PDF documents into static PNGs.

## Generate PNG Image

<mark style="color:green;">`POST`</mark> `https://api-eu.renda.io/converter/generateImage`

This API enables conversion of PDF document into PNG Image.&#x20;

A single page PDF will return PNG payload as a response.&#x20;

A multi-page PDF will be transformed into multiple PNGs based on the number of pages in the PDF document. A zip archived payload of the PNGs will be returned as a API response.\
\
Region specific URLs:\
\
Ireland(Europe): `https://api-eu.renda.io/converter/generateImage`<br>

#### Headers

| Name                                           | Type   | Description         |
| ---------------------------------------------- | ------ | ------------------- |
| x-api-key<mark style="color:red;">\*</mark>    | String | Renda API Key       |
| Content-type<mark style="color:red;">\*</mark> | String | multipart/form-data |

#### Request Body

| Name                                          | Type | Description  |
| --------------------------------------------- | ---- | ------------ |
| pdfDocument<mark style="color:red;">\*</mark> | File | PDF Document |

{% tabs %}
{% tab title="200: OK PNG image will be returned for a single page PDF. A zip archive will be returned for multi page PDF" %}

```javascript
{
    //Single page PDF will return application/png as API response
    //Multi page PDF will return application/zip as API response containing one PNG for each page
}
```

{% endtab %}

{% tab title="400: Bad Request Processing error" %}

```javascript
{
    // Response from server
}
```

{% endtab %}

{% tab title="403: Forbidden Invalid API Key" %}

```json
{
"message":"We are unable to service your request. Things to verify: 
1) A valid API Key should be passed in ‘x-api-key’ request header parameter.
 2) An active Renda.io subscription 3) API being invoked must be Subscribed 
 using the Subscribe button in Renda developer portal. Please refer to Renda 
 documentation for more details - https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## Transform PDF to Postscript

Convert single and multi page PDF documents into printer friendly postscript document.

## Generate Postscript document

<mark style="color:green;">`POST`</mark> `https://api-eu.renda.io/converter/generatePostscript`

This API enables conversion of PDF document into postscript document.&#x20;

#### Headers

| Name                                           | Type   | Description         |
| ---------------------------------------------- | ------ | ------------------- |
| x-api-key<mark style="color:red;">\*</mark>    | String | Renda API Key       |
| Content-Type<mark style="color:red;">\*</mark> | String | multipart/form-data |

#### Request Body

| Name                                          | Type | Description  |
| --------------------------------------------- | ---- | ------------ |
| pdfDocument<mark style="color:red;">\*</mark> | File | PDF Document |

{% tabs %}
{% tab title="200: OK Postscript document will be returned" %}

```javascript
{
    // Payload with application/postscript will be returned
}
```

{% endtab %}

{% tab title="400: Bad Request Processing error" %}

```javascript
{
    // Error Response from server
}
```

{% endtab %}

{% tab title="403: Forbidden Invalid API Key" %}

```json
{
"message":"We are unable to service your request. Things to verify: 
1) A valid API Key should be passed in ‘x-api-key’ request header parameter.
 2) An active Renda.io subscription 3) API being invoked must be Subscribed 
 using the Subscribe button in Renda developer portal. Please refer to Renda 
 documentation for more details - https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}


# Time based Authentication

TOTP Generation and validation APIs

{% hint style="info" %}
**API calls are region specific. Please make sure you are subscribed to a specific region and have a valid Renda API Key before making API calls.**

Region Specific URLs:\
\
Ireland(Europe): \*\*<https://api-eu.renda.io**\\>
North Virginia(US): \*\*<https://api-us.renda.io**\\>
Mumbai(APAC): **<https://api-apac.renda.io>**
{% endhint %}

## Get Ping

<mark style="color:blue;">`GET`</mark> `https://api-<region>.renda.io/totp/ping`

Region specific URLs:\
Ireland(Europe):**`https://api-eu.renda.io/totp/ping`**\
North Virginia(US): **`https://api-us.renda.io/totp/ping`**\
Mumbai(APAC): **`https://api-apac.renda.io/totp/ping`**

#### Headers

| Name      | Type   | Description   |
| --------- | ------ | ------------- |
| x-api-key | string | Renda API Key |

{% tabs %}
{% tab title="200 Ping successful" %}

```
    {
        "type": "Success",
        "message": "Renda.io ping successful"
    }
]
```

{% endtab %}

{% tab title="403 Invalid API Key " %}

```
{
    "message”:”Please check the following: 1) An *active* Renda.io 
    subscription 2) API being invoked must be *Subscribed* in Renda 
    developer portal 3) A valid *API Key* must be passed in ‘x-api-key’ 
    request header parameter. Please refer to Renda documentation for 
    more details - https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## generateQRCode

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/totp/generateQRCode`

Generate QR Code API encodes any form data such as text, URL, phone numbers etc., into a QR code.

#### Headers

| Name         | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| x-api-key    | string | Renda API Key                     |
| Accept       | string | \*/\*                             |
| Content-type | string | application/x-www-form-urlencoded |

#### Request Body

| Name | Type   | Description                       |
| ---- | ------ | --------------------------------- |
| data | string | Data to be encoded in the QR Code |

{% tabs %}
{% tab title="200 QR code in png format" %}

```
<QR Code in png format>
```

{% endtab %}

{% tab title="400 " %}

```
[
    {
        "type": "Error",
        "message": "No Data provided to generate QR Code"
    }
]
```

{% endtab %}

{% tab title="403 Invalid API Request" %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## onboardUser

<mark style="color:green;">`POST`</mark> `https://api-<region>/renda.io/totp/onboardUser`

Onboard user API generates a secret key based on userid(which can be email address, name, number etc.,) and application ID. This API is useful to build user onboarding/authentication module whereby users can be authenticated using **time based one time password (TOTP) generated by any soft token generator.** \
\
This API returns a secret key, OTP URL, QR Code image encoded with the OTP URL which can be scanned to setup any soft key generator and a current TOTP passcode

#### Headers

| Name         | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| x-api-key    | string | Renda API Key                     |
| Content-Type | string | application/x-www-form-urlencoded |

#### Request Body

| Name          | Type   | Description                                 |
| ------------- | ------ | ------------------------------------------- |
| userID        | string | User ID (Email address, Employee ID etc.,)  |
| applicationID | string | Application ID (Name of the app)            |
| tokenValidity | string | Token refresh interval - Default is 30 secs |
| tokenLength   | string | Token Length - Default is 6 digits          |

{% tabs %}
{% tab title="200 " %}

```
{
    "secretKey": "LVJFKZI5AJZXIZKG",
    "otpURL": "otpauth://totp/Renda:jafferali?secret=LVJFKZI5AJZXIZKG&period=30&digits=6&algorithm=SHA1&issuer=Renda",
    "QRCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMQAAADECAYAAADApo5rAAAAAklEQVR4AewaftIAAAi5SURBVO3BQY4cOxYEwXCi7n9ln8YsiLciQGRW60sIM/yRqvq/laraVqpqW6mqbaWqtpWq2laqalupqm2lqraVqtpWqmpbqaptpaq2laraVqpqW6mq7ZOHgPwmNROQSc0EZFIzAZnUnAC5oeYEyImaEyCTmhtAJjUnQE7UTEB+k5onVqpqW6mqbaWqtk9epuZNQJ5QMwG5AWRSMwGZ1ExATtQ8oeYGkEnNCZA3qXkTkDetVNW2UlXbSlVtn3wZkBtqfpOaCcikZgJyQ80E5AaQG2qeADKpmYBMap4AckPNN61U1bZSVdtKVW2f/OXUTEBuAJnUTEAmNTeAnACZ1JyoOQFyouYGkBMgk5q/2UpVbStVta1U1fbJXw7IpOYGkAnICZAbaiYgJ0AmNROQEzUTkAnIiZoTIJOaf8lKVW0rVbWtVNX2yZep+SY1b1JzA8ik5oaaG2puqJmATGpuqHmTmv+SlaraVqpqW6mq7ZOXAflNQCY1E5BJzQ0gk5obQCY1E5BJzQRkUjMBmdRMQCY1E5BJzQRkUjMBmdScAPkvW6mqbaWqtpWq2vBH/iFAJjUTkDepOQFyouYGkEnNBOSGmieATGr+ZitVta1U1bZSVdsnDwGZ1JwA+SY1T6iZgJwAOVHzJjUTkEnNCZATIDfUTEAmNSdAJjUTkBtqnlipqm2lqraVqto+eRmQEzVvAjIBmdScqLmh5gaQEzUTkBtqToDcUDMBOQHyhJoJyKRmAvJNK1W1rVTVtlJV2ycvUzMBmYA8oWZSMwGZgExqToB8k5o3AZnUPAFkUnMC5F+yUlXbSlVtK1W1ffKQmgnIDTUTkEnNDTU3gDwB5E1q3qTmTUAmNSdAJjUTkBtqvmmlqraVqtpWqmrDH3kAyA01N4DcUHMDyA01J0DepOZNQCY1bwIyqfkmIJOaJ1aqalupqm2lqrZPHlIzAZnUTEAmNSdqJiA3gExqbqg5ATKpOQEyqTkBckPNBGRS8yYgN4D8l61U1bZSVdtKVW2f/GFAJjUTkCfUnKg5AfImNSdATtRMQE7UTEAmNROQEzWTmhMgJ2puAPmmlaraVqpqW6mq7ZOHgExqJiAnak7UTEDeBOSGmgnIBOSGmhtAbgCZ1ExAJjVPAHkCyImaCcibVqpqW6mqbaWqtk9eBuREzQ0gJ2pOgNxQMwGZgExqToDcUHMCZFIzAXkTkEnNiZon1JwA+aaVqtpWqmpbqaoNf+RFQCY1E5BJzQRkUnMCZFIzATlRcwLkhpoTIJOaG0C+Sc0TQCY1J0AmNX/SSlVtK1W1rVTV9slDQE6APAHkTWomICdq3qTmBMgNNROQEzUnQE7U3AAyqTkBMqk5ATKpeWKlqraVqtpWqmr75D9GzQ0gT6iZgExAJjUTkBtqTtScAJmAnKiZgExqTtRMQP5lK1W1rVTVtlJVG/7Ii4CcqJmATGomICdqJiCTmhMgk5oJyA01J0DepOYGkCfUTEAmNROQSc0NIDfUPLFSVdtKVW0rVbV98jI1E5An1NxQMwE5UXNDzQTkBMik5gaQSc0E5ETNpGYCcqJmAjKpOVFzAuREzW9aqaptpaq2lara8EdeBOREzQTkhpoJyImaCcgTar4JyKTmBpBJzW8CMqmZgJyo+ZNWqmpbqaptpao2/JFfBOREzQ0gT6g5ATKpOQFyQ80NIJOaEyCTmgnIiZoJyKTmCSCTmgnIpOabVqpqW6mqbaWqtk9eBuRNQE7UTEBO1NxQc0PNCZAJyKRmAjKpmYCcqJmATGreBOREzaRmAjKpOQEyqXlipaq2laraVqpq++SXqZmAnKiZgNxQcwPIpOYJIJOaEyAnQCY1TwCZ1JyomYCcqLmhZgLym1aqalupqm2lqrZPHgIyqTkBcgLkCTUTkCeATGomICdqJiCTmhM1N4DcUHMDyKRmAnIDyImaCcg3rVTVtlJV20pVbZ88pGYCMqm5oeYEyATkNwF5E5ATIJOa3wRkUjMBmdRMQJ4AMqmZgLxppaq2laraVqpqwx/5g4DcUDMBmdScADlRMwGZ1JwAuaFmAjKpmYBMap4AMqmZgJyomYCcqDkBMqn5TStVta1U1bZSVRv+yANAbqg5ATKpmYBMaiYgk5oTIJOaCciJmj8JyImaCcgNNROQSc0E5DepedNKVW0rVbWtVNWGP/IAkCfUTEBO1DwBZFIzAZnUTEBO1ExATtTcADKpmYCcqJmATGomICdqToBMaiYgb1LzxEpVbStVta1U1fbJl6mZgNxQMwGZ1ExATtRMQE6AfBOQSc0Tak6ATGpuqJmATGomNSdqToD8ppWq2laqalupqu2TLwMyqZmATGomICdATtRMQCY1bwLyJiCTmhMgk5obQE6AnAD5m61U1bZSVdtKVW34I38xIJOaEyCTmgnIiZoJyKTmBMgNNSdAJjUnQG6omYCcqLkBZFJzAmRS86aVqtpWqmpbqartk4eA/CY1N4BMaiYgJ2pO1ExAbqg5ATKpOQFyouYGkEnNBOQEyKTmBMiJmm9aqaptpaq2laraPnmZmjcBuQFkUnOiZgJyA8iJmgnICZAbaiYgk5o/Sc0NNSdATtQ8sVJV20pVbStVtX3yZUBuqHlCzQTkRM2k5k1AnlBzQ80E5IaaJ4B8k5oJyJtWqmpbqaptpaq2T/4xQE7U3AByQ80JkDcBOVEzAZnUnKiZgExqJiCTmhtAJjW/aaWqtpWq2laqavvkL6dmAnIDyBNqToBMak7UTEBuqPkmNROQG0BO1JwA+aaVqtpWqmpbqartky9T85vUTEBO1ExAJjXfBGRSc0PNCZBJzQ0gk5pJzQRkAjKpmYDcUDMBedNKVW0rVbWtVNX2ycuA/CYgJ2omIJOav4maCciJmifUTEBO1JwAeZOaN61U1bZSVdtKVW34I1X1fytVta1U1bZSVdtKVW0rVbWtVNW2UlXbSlVtK1W1rVTVtlJV20pVbStVta1U1bZSVdv/AHH/jc369bkDAAAAAElFTkSuQmCC",
    "token": "605250"
}
```

{% endtab %}

{% tab title="400 Parameters missing" %}

```
[
    {
        "type": "Error",
        "message": "User ID is mandatory"
    },
    {
        "type": "Error",
        "message": "Application ID is mandatory"
    }
]
```

{% endtab %}
{% endtabs %}

## getOTP

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/totp/getOTP`

This API fetches the current valid OTP for a specified secret key. Token validity and token length parameters can be passed if they customised to be more than 30 seconds in duration and 6 digits in length

#### Headers

| Name         | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| x-api-key    | string | Renda API Key                     |
| Content-Type | string | application/x-www-form-urlencoded |

#### Request Body

| Name          | Type   | Description                         |
| ------------- | ------ | ----------------------------------- |
| secret        | string | Secret Key                          |
| tokenValidity | string | Token validity (default to 30 secs) |
| tokenLength   | string | Token length (defaults to 6 digits) |

{% tabs %}
{% tab title="200 " %}

```
{
    "currentToken": "667122",
    "timeUsed": 10,
    "timeRemaining": 20,
    "previousToken": "008989",
    "nextToken": "390535"
}
```

{% endtab %}

{% tab title="400 Bad request" %}

```
[
    {
        "type": "Error",
        "message": "secret cannot be empty"
    }
]
```

{% endtab %}

{% tab title="403 " %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## verifyOTP

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/totp/verifyOTP`

This API method verifies the provided one time password(OTP) against a specific Secret key. Token validity can be passed in the validity period needs to be extended beyond the default 30 seconds.

#### Headers

| Name         | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| x-api-key    | string | Renda API key                     |
| Content-Type | string | application/x-www-form-urlencoded |

#### Request Body

| Name          | Type   | Description                         |
| ------------- | ------ | ----------------------------------- |
| secret        | string | Secret Key                          |
| token         | string | OTP Token                           |
| tokenValidity | string | Token validity (Default 30 seconds) |

{% tabs %}
{% tab title="200 " %}

```
{
    "isValid": false,
    "token": "911726",
    "timeUsed": 27,
    "timeRemaining": 3
}
```

{% endtab %}

{% tab title="400 Mandatory parameters missing" %}

```
[
    {
        "type": "Error",
        "message": "Token cannot be empty"
    },
    {
        "type": "Error",
        "message": "Secret cannot be empty"
    }
]
```

{% endtab %}

{% tab title="403 Invalid API Call" %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}


# Communication

The communication API enables text message delivery. Authentication systems can be quickly build using a combination of TOTP API and Communication API to authenticate and onboard users

## Ping

<mark style="color:blue;">`GET`</mark> `https://api-<region>.renda.io/communication/ping`

Heartbeat Check

#### Headers

| Name      | Type   | Description   |
| --------- | ------ | ------------- |
| x-api-key | string | Renda API Key |

{% tabs %}
{% tab title="200 Cake successfully retrieved." %}

```
[
    {
        "type": "Success",
        "message": "Renda.io ping successful"
    }
]
```

{% endtab %}

{% tab title="403 Could not find a cake matching this query." %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}

## Send SMS

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/communication/sendSMS`

#### Headers

| Name      | Type   | Description |
| --------- | ------ | ----------- |
| x-api-key | string |             |

#### Request Body

| Name       | Type   | Description                                                                                                                          |
| ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| number     | string | <p>Valid Mobile number <br><br>+441234567890<br>00441234567890<br><br>\<country code> + \<mobile number></p>                         |
| message    | string | SMS Text                                                                                                                             |
| senderName | string | <p>Sender Name<br><br>3-11 chars if alphanumeric <br>3-15 chars if numeric <br>Spaces and special characters are not allowed<br></p> |

{% tabs %}
{% tab title="200 " %}

```
{
    "messageid": "612733016353393435",
    "status": "SENT"
}
```

{% endtab %}

{% tab title="400 " %}

```
//When invalid mobile number and message is provided
[
    {
        "type": "Error",
        "message": "Invalid mobile number"
    },
    {
        "type": "Error",
        "message": "Invalid message content"
    }
]


//When Invalid destination number is provided
{
    "status": "error",
    "errorCode": 4004,
    "message": "Invalid destination number.",
    "permanent": true
}
```

{% endtab %}

{% tab title="403 " %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details https://documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}


# QR Code Generation

{% hint style="info" %}
**API calls are region specific. Please make sure you are subscribed to a specific region and have a valid Renda API Key before making API calls.**

Region Specific URLs:\
\
Ireland(Europe): \*\*<https://api-eu.renda.io**\\>
North Virginia(US): \*\*<https://api-us.renda.io**\\>
Mumbai(APAC): **<https://api-apac.renda.io>**
{% endhint %}

## Generate QR Code

<mark style="color:green;">`POST`</mark> `https://api-<region>.renda.io/totp/generateQRCode`

Region specific URLs:\
Ireland(Europe): `https://api-eu.renda.io/totp/generateQRCode`\
North Virginia(US): `https://api-us.renda.io/totp/generateQRCode`\
Mumbai(APAC): `https://api-apac.renda.io/totp/generateQRCode`<br>

#### Headers

| Name         | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| x-api-key    | string | Renda API Key                     |
| Accept       | string | \*/\*                             |
| Content-type | string | application/x-www-form-urlencoded |

#### Request Body

| Name | Type   | Description                       |
| ---- | ------ | --------------------------------- |
| data | string | Data to be encoded in the QR Code |

{% tabs %}
{% tab title="200 QR Code in png format" %}

```
<QR Code data>
```

{% endtab %}

{% tab title="400 " %}

```
[
    {
        "type": "Error",
        "message": "No Data provided to generate QR Code"
    }
]
```

{% endtab %}

{% tab title="403 " %}

```
{
    "message": "Unsupported API request. Please refer to Renda 
    documentation for more details documentation.renda.io"
}
```

{% endtab %}
{% endtabs %}


# Floe

## Overview

Floe is an e-mail generator for SAP through which you can manage e-mail templates and dynamic business rules in order to produce tailored, branded e-mail output. Floe can be used for any SAP e-mail communication and can be incorporated into existing business processes easily.

Find out all the product details at [www.floe.com](http://www.floe.com/).

#### The following Renda integrations are available for Floe.

{% content-ref url="/pages/m5PYJDKWtArwUbReJZrF" %}
[Generate PDF](/integrations/floe/generate-pdf)
{% endcontent-ref %}

{% content-ref url="/pages/nHnjiqd9v1ss56Nds5nl" %}
[Send SMS](/integrations/floe/send-sms)
{% endcontent-ref %}


# Generate PDF

## Renda Integration

Rich HTML output generated by Floe can be transformed into a PDF document using Renda. As part of the PDF utilities collection, Renda offers an API that can be invoked to convert any HTML output to PDF document.&#x20;

Floe 210 now supports  PDF generation, so Floe emails can be sent with either a PDF equivalent attached or a completely different Floe-generated PDF.&#x20;

<div align="center"><img src="https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MBsuqFhmeYvQwkhzDUn%2F-MKEo--wlxXP8vrakGTw%2F-MKEoNeXfICOEXWpoBMz%2FRenda%2BFloe.png?alt=media&amp;token=20cc4825-5c36-46ef-917a-771d8e6bd7d7" alt="Floe + Renda Integration"></div>

## Configuration

### Setup SM59 Connection

1. Login into Renda developer portal
2. Subscribe to **Generate PDF** Service in Renda portal
3. Copy API Service URL to notepad
4. Logon to SAP system where Floe is installed
5. Go to transaction SM59
   1. Create a new HTTP Connection to External Server - Type G
   2. Key in **RENDA.IO** in RFC Destination field
   3. Enter description as **Renda.io connection for HTML transformation**
   4. Under Technical Settings tab - Paste API Service URL based on the region you signed up
      * EU Region - api-eu.renda.io
      * APAC Region - api-apac.renda.io
      * US Region - api-us.renda.io
   5. Enter **/v2/generatePDF** in the Path Prefix field
   6. Enter Service No. as **443**
   7. Under the **Logon & Security** tab - Set SSL to active
   8. Test Connection&#x20;

{% hint style="warning" %}
Please remember to whitelist **API Service URL** from within your corporate firewall. This will enable outbound calls to be made from your SAP system to Renda engine in the cloud.
{% endhint %}

![Renda SM59 Connection Setup](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2FCAPqWgbmOoBl3OnkQCaD%2Fimage.png?alt=media\&token=87dada32-1bab-4873-b185-d7f707d4657e)

![Renda SM59 Connection Setup](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2F2uvlUAc0Begabw75O7OX%2Fimage.png?alt=media\&token=c809a485-9f76-469f-ab26-005c8201030b)

### Floe system specific settings

1. Go to SPRO->Cross Application Functions->Floe->Administration->System specific settings
2. Under Renda.io PDF Conversion Service Settings
   1. Select the RFC Destination setup for Renda.io using search help
   2. Enter the following requests
      1. **x-api-key** : **\<API Key from Renda Developer Dashboard>**
      2. **Accept** : **application/pdf**
      3. **Content-Type** : **application/x-www-form-urlencoded**

![Renda system specific configuration](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2FpqL1hcEcVmHg0ApCfsCv%2Fimage.png?alt=media\&token=95c51787-1f61-4ae4-a492-c02d49274354)

{% embed url="<https://youtu.be/O3pgqBcLg3Y>" %}


# Send SMS

## Renda Integration

Floe 220 now supports dynamic SMS content creation and integrates with Renda communicaiton API to send SMS messages.

Find out all the product details at [www.floe.com](http://www.floe.com/).

## Configuration

### Setup SM59 Connection

1. Login into Renda developer portal
2. Subscribe to **Communication** Service in Renda portal
3. Copy API Service URL to notepad
4. Logon to SAP system where Floe is installed
5. Go to transaction SM59
   1. Create a new HTTP Connection to External Server - Type G
   2. Key in **RENDA.SMS** in RFC Destination field
   3. Enter description as **Renda.io SMS service**
   4. Under Technical Settings tab - Paste API Service URL based on the region you signed up
      * EU Region - api-eu.renda.io
      * APAC Region - api-apac.renda.io
      * America Region - api-us.renda.io
   5. Enter **/communication/sendSMS** in the Path Prefix field
   6. Enter Service No. as **443**
   7. Under the **Logon & Security** tab - Set SSL to active
   8. Test Connection&#x20;

{% hint style="warning" %}
Please remember to whitelist **API Service URL** from within your corporate firewall. This will enable outbound calls to be made from your SAP system to Renda engine in the cloud.
{% endhint %}

![Renda SM59 Connection Setup](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2FznckY14BKrQo61HulX2H%2Fimage.png?alt=media\&token=16f3554d-f015-43cf-a682-b8e2f7a9c2e6)

![Renda SM59 Connection Setup](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2F2uvlUAc0Begabw75O7OX%2Fimage.png?alt=media\&token=c809a485-9f76-469f-ab26-005c8201030b)

### Floe system specific settings

1. Go to SPRO->Cross Application Functions->Floe->Administration->System specific settings
2. Under Renda.io SMS Service Settings
   1. Select the RFC Destination setup for **Renda.SMS** using search help
   2. Enter API Key from Renda Developer Dashboard

![Renda system specific configuration](https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MBsuqFhmeYvQwkhzDUn%2Fuploads%2FwlM0qd6cOOUnvhO6UOk8%2Fimage.png?alt=media\&token=82d8af45-ec53-45cc-a2da-0d414ae8846b)

{% embed url="<https://youtu.be/O3pgqBcLg3Y>" %}


# SAP On-premise

## Import Renda SSL Certificate

{% hint style="warning" %}
Renda is hosted on AWS. You will need to install AWS root certificate in your SAP landscape to enable communication between your SAP system and Renda APIs.&#x20;

Please remember to import the SSL certificate across all the systems in your SAP landscape
{% endhint %}

{% file src="/files/9pbQSH2n10G0uHsS1ztv" %}

1. Download AWS Root - Renda SSL certificate&#x20;
2. Go to transaction STRUST
3. Go to SSL Client SSL Client(Standard) and select entry corresponding to your system
4. Import the certificate
5. Click on "Add to certificate list"
6. Save

## Setup SM59 Connection

1. Login into Renda developer portal
2. Subscribe to HTML->PDF service
3. Copy API Service URL to notepad
4. Go to transaction SM59
   1. Create a new HTTP Connection to External Server - Type G
   2. Key in **RENDA.IO** in RFC Destination field
   3. Enter description as **Renda.io connection for HTML transformation**
   4. Under Technical Settings tab - Paste region specific API Service URL
   5. Under Logon & Security -> Security Options - Status of Secure Protocol->SSL is **active**&#x20;
   6. Enter Service No. as **443**
   7. Test Connection&#x20;

{% hint style="info" %}
You should receive a HTTP 200 success code if everything is setup successfully.
{% endhint %}

{% hint style="warning" %}
Please remember to whitelist **API Service URL** from within your corporate firewall. This will enable outbound calls to be made from your SAP system to Renda engine in the cloud.
{% endhint %}

## Invoking REST API

The following code demonstrates how Renda can be invoked from ABAP function to convert HTML output  to PDF document

{% tabs %}
{% tab title="ABAP Code - To Convert HTML output to PDF document" %}

```java
FUNCTION zgenerate_pdf.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_HTML) TYPE  STRING
*"     VALUE(IM_ENCRYPTION_KEY) TYPE  STRING OPTIONAL
*"     VALUE(IM_LANDSCAPE) TYPE  STRING OPTIONAL
*"     VALUE(IM_FORMAT) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_TOP) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_RIGHT) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_BOTTOM) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_LEFT) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_PDF) TYPE  XSTRING
*"----------------------------------------------------------------------
*
  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Accept'
      value = 'application/pdf' ).
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'inputPayload'
    value  = im_html ).
*
  IF im_encryption_key IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'encryptionKey'
      value  = im_encryption_key ).
*
  ENDIF.
*
  IF im_landscape IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'landscape'
      value  = im_landscape ).
*
  ENDIF.
*
  IF im_format IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'format'
      value  = im_format ).
*
  ENDIF.
*
  IF im_margin_top IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginTop'
      value  = im_margin_top ).
*
  ENDIF.
*
  IF im_margin_right IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginRight'
      value  = im_margin_right ).
*
  ENDIF.
*
  IF im_margin_bottom IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginBottom'
      value  = im_margin_bottom ).
*
  ENDIF.
*
  IF im_margin_left IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginLeft'
      value  = im_margin_left ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    ex_pdf = lo_http_client->response->get_data( ).
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}


# SAP Fiori

{% embed url="<https://youtu.be/3B_tMJM4Mek>" %}


# SAP Conversational AI

<div align="center"><img src="https://2586501859-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MBsuqFhmeYvQwkhzDUn%2F-MKEoThWzvcmBHQ1cc-p%2F-MKEpPVtVs-QK6Vjsryo%2FRenda%2BChatbot.png?alt=media&amp;token=01250e2b-829b-4e8c-b920-289e99cde2cd" alt="SAP CAI + Renda.io"></div>


# MS Teams

Please watch this space for further updates


# Code Samples

{% embed url="<https://documentation.renda.io/code-samples/abap-code-samples>" %}
Code samples - ABAP on premise
{% endembed %}

{% embed url="<https://documentation.renda.io/code-samples/abap-code-samples-1>" %}
Code samples - ABAP in the cloud
{% endembed %}


# SAP On-premise

### Generate PDF from HTML

{% tabs %}
{% tab title="HTML to PDF" %}

```java
FUNCTION zgenerate_pdf.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_HTML) TYPE  STRING
*"     VALUE(IM_ENCRYPTION_KEY) TYPE  STRING OPTIONAL
*"     VALUE(IM_LANDSCAPE) TYPE  STRING OPTIONAL
*"     VALUE(IM_FORMAT) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_TOP) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_RIGHT) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_BOTTOM) TYPE  STRING OPTIONAL
*"     VALUE(IM_MARGIN_LEFT) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_PDF) TYPE  XSTRING
*"----------------------------------------------------------------------
*
  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Accept'
      value = 'application/pdf' ).
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'inputPayload'
    value  = im_html ).
*
  IF im_encryption_key IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'encryptionKey'
      value  = im_encryption_key ).
*
  ENDIF.
*
  IF im_landscape IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'landscape'
      value  = im_landscape ).
*
  ENDIF.
*
  IF im_format IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'format'
      value  = im_format ).
*
  ENDIF.
*
  IF im_margin_top IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginTop'
      value  = im_margin_top ).
*
  ENDIF.
*
  IF im_margin_right IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginRight'
      value  = im_margin_right ).
*
  ENDIF.
*
  IF im_margin_bottom IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginBottom'
      value  = im_margin_bottom ).
*
  ENDIF.
*
  IF im_margin_left IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'marginLeft'
      value  = im_margin_left ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    ex_pdf = lo_http_client->response->get_data( ).
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}

### Generate QR Code&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
FUNCTION zgenerate_qr_code.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_DATA) TYPE  STRING
*"  EXPORTING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_QR_CODE) TYPE  XSTRING
*"----------------------------------------------------------------------
*
  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Accept'
      value = '*/*' ).
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'data'
    value  = im_data ).
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    ex_qr_code = lo_http_client->response->get_data( ).
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}

### Onboard user for TOTP

{% tabs %}
{% tab title="ABAP" %}

```java
FUNCTION zonboard_user.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_USER_ID) TYPE  STRING
*"     VALUE(IM_APPLICATION_ID) TYPE  STRING
*"     VALUE(IM_TOKEN_VALIDITY) TYPE  STRING OPTIONAL
*"     VALUE(IM_TOKEN_LENGTH) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_SECRET_KEY) TYPE  STRING
*"     VALUE(EX_OTP_URL) TYPE  STRING
*"     VALUE(EX_QR_CODE) TYPE  STRING
*"     VALUE(EX_TOKEN) TYPE  STRING
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"----------------------------------------------------------------------
  TYPES: BEGIN OF ltyp_response,
           secretkey TYPE string,
           otpurl    TYPE string,
           qrcode    TYPE string,
           token     TYPE string,
         END OF ltyp_response.

  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data,
        ls_response    TYPE ltyp_response.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'userID'
    value  = im_user_id ).
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'applicationID'
    value  = im_application_id ).
*
  IF im_token_validity IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'tokenValidity'
      value  = im_token_validity ).
*
  ENDIF.
*
  IF im_token_length IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'tokenLength'
      value  = im_token_length ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
    ex_secret_key = ls_response-secretkey.
    ex_otp_url = ls_response-otpurl.
    ex_qr_code = ls_response-qrcode.
    ex_token = ls_response-token.
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}

### Validate OTP using secret key

{% tabs %}
{% tab title="ABAP" %}

```java
FUNCTION zverify_otp.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_SECRET) TYPE  STRING
*"     VALUE(IM_TOKEN) TYPE  STRING
*"     VALUE(IM_TOKEN_VALIDITY) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_IS_VALID) TYPE  FLAG
*"     VALUE(EX_TOKEN) TYPE  STRING
*"     VALUE(EX_TIME_USED) TYPE  STRING
*"     VALUE(EX_TIME_REMAINING) TYPE  STRING
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"----------------------------------------------------------------------
  TYPES: BEGIN OF ltyp_response,
           isvalid       TYPE flag,
           token         TYPE string,
           timeused      TYPE string,
           timeremaining TYPE string,
         END OF ltyp_response.

  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data,
        ls_response    TYPE ltyp_response.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'secret'
    value  = im_secret ).
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'token'
    value  = im_token ).
*
  IF im_token_validity IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'tokenValidity'
      value  = im_token_validity ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
    ex_is_valid = ls_response-isvalid.
    ex_token = ls_response-token.
    ex_time_used = ls_response-timeused.
    ex_time_remaining = ls_response-timeremaining.
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}

### Retrieve OTP for a secret key

{% tabs %}
{% tab title="ABAP" %}
{% code title="zget\_otp" %}

```java
FUNCTION zget_otp.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_SECRET) TYPE  STRING
*"     VALUE(IM_TOKEN_VALIDITY) TYPE  STRING OPTIONAL
*"     VALUE(IM_TOKEN_LENGTH) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_CURRENT_TOKEN) TYPE  STRING
*"     VALUE(EX_TIME_USED) TYPE  STRING
*"     VALUE(EX_TIME_REMAINING) TYPE  STRING
*"     VALUE(EX_PREVIOUS_TOKEN) TYPE  STRING
*"     VALUE(EX_NEXT_TOKEN) TYPE  STRING
*"     VALUE(EX_MESS) TYPE  STRING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"----------------------------------------------------------------------
  TYPES: BEGIN OF ltyp_response,
           currenttoken  TYPE string,
           timeused      TYPE string,
           timeremaining TYPE string,
           previoustoken TYPE string,
           nexttoken     TYPE string,
         END OF ltyp_response.

  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data,
        ls_response    TYPE ltyp_response.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'Content-Type'
      value = 'application/x-www-form-urlencoded' ).
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'secret'
    value  = im_secret ).
*
  IF im_token_validity IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'tokenValidity'
      value  = im_token_validity ).
*
  ENDIF.
*
  IF im_token_length IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'tokenLength'
      value  = im_token_length ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ELSE.
*
    /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
    ex_current_token = ls_response-currenttoken.
    ex_time_used = ls_response-timeused.
    ex_time_remaining = ls_response-timeremaining.
    ex_previous_token = ls_response-previoustoken.
    ex_next_token = ls_response-nexttoken.
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Send SMS&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
FUNCTION zsend_sms.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_RFCDEST) TYPE  RFCDEST
*"     VALUE(IM_API_KEY) TYPE  STRING
*"     VALUE(IM_NUMBER) TYPE  STRING
*"     VALUE(IM_MESSAGE) TYPE  STRING
*"     VALUE(IM_SENDER_NAME) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"     VALUE(EX_MESS) TYPE  STRING
*"----------------------------------------------------------------------
*
  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_http_rc     TYPE i,
        lv_response    TYPE string,
        lv_json        TYPE /ui2/cl_json=>json,
        lr_data        TYPE REF TO data.
*
  FIELD-SYMBOLS: <data>  TYPE data,
                 <field> TYPE any.
*
* Setup IF_HTTP_Client object
*
  CALL METHOD cl_http_client=>create_by_destination
    EXPORTING
      destination        = im_rfcdest
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
*
  IF sy-subrc IS NOT INITIAL.
    ex_mess = 'Error creating new IF_HTTP_Client object. Process aborted.'.
    ex_subrc = 4.
    RETURN.
  ENDIF.
*
* Set protocol version
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
  lo_http_client->request->set_header_field(
      name  = 'x-api-key'
      value = im_api_key ).
*
* Set form fields/attributes
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'number'
    value  = im_number ).
*
  lo_http_client->request->if_http_entity~set_form_field(
    name   = 'message'
    value  = im_message ).
*
  IF im_sender_name IS NOT INITIAL.
*
    lo_http_client->request->if_http_entity~set_form_field(
      name   = 'senderName'
      value  = im_sender_name ).
*
  ENDIF.
*
  lo_http_client->request->set_method( 'POST' ).
*
  lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
*
* Send request
*
  CALL METHOD lo_http_client->send
    EXPORTING
      timeout                    = 60   " 15 Seconds
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2.
*
  IF sy-subrc IS NOT INITIAL.
*
    ex_mess = 'HTTP Post error. Process aborted'.
    ex_subrc = 4.
*
    CALL METHOD lo_http_client->close
      EXCEPTIONS
        http_invalid_state = 1
        OTHERS             = 2.
*
    FREE lo_http_client.
    RETURN.
*
  ENDIF.
*
* Read the Response
*
  CALL METHOD lo_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3.
*
  lo_http_client->response->get_status( IMPORTING code   = lv_http_rc ).
  lo_http_client->response->get_status( IMPORTING reason = ex_mess ).
  lv_response = lo_http_client->response->get_cdata( ).
*
  IF lv_http_rc NE '200'.
*
* Get error message back from Renda
*
    ex_subrc = 4.
    lv_json = lv_response.
    lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
    IF lr_data IS BOUND.
      ASSIGN lr_data->* TO <data>.
      ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data> TO <field>.
      IF <field> IS ASSIGNED.
        lr_data = <field>.
        ASSIGN lr_data->* TO <data>.
        ex_mess = <data>.
      ENDIF.
    ENDIF.
*
  ENDIF.
*
  CALL METHOD lo_http_client->close
    EXCEPTIONS
      http_invalid_state = 1
      OTHERS             = 2.
*
  FREE lo_http_client.
*
ENDFUNCTION.
```

{% endtab %}
{% endtabs %}


# SAP BTP - ABAP in the cloud

### Generate PDF from HTML

{% tabs %}
{% tab title="HTML to PDF" %}

```java
CLASS zgenerate_pdf DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: generate_pdf
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_html)           TYPE  string
        VALUE(im_encryption_key) TYPE  string OPTIONAL
        VALUE(im_landscape)      TYPE  string OPTIONAL
        VALUE(im_format)         TYPE  string OPTIONAL
        VALUE(im_margin_top)     TYPE  string OPTIONAL
        VALUE(im_margin_right)   TYPE  string OPTIONAL
        VALUE(im_margin_bottom)  TYPE  string OPTIONAL
        VALUE(im_margin_left)    TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_pdf)            TYPE  xstring,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zgenerate_pdf IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc TYPE sysubrc,
          lv_mess  TYPE string,
          lv_xpdf  TYPE xstring.
*
    CALL METHOD generate_pdf
      EXPORTING
        im_url     = 'https://api-eu.renda.io/v2/generatePDF'
        im_api_key = '<your api key>'
        im_html    = '<html>Hello World!</html>'
*       im_encryption_key =
*       im_landscape      =
*       im_format  =
*       im_margin_top     =
*       im_margin_right   =
*       im_margin_bottom  =
*       im_margin_left    =
      IMPORTING
        ex_subrc   = lv_subrc
        ex_mess    = lv_mess
        ex_pdf     = lv_xpdf.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_xpdf ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD generate_pdf.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Accept'
            i_value = 'application/pdf' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'inputPayload=' im_html INTO lv_req_body.
*
    IF im_encryption_key IS NOT INITIAL.
      CONCATENATE: lv_req_body '&encryptionKey=' im_encryption_key INTO lv_req_body.
    ENDIF.
*
    IF im_landscape IS NOT INITIAL.
      CONCATENATE: lv_req_body '&landscape=' im_landscape INTO lv_req_body.
    ENDIF.
*
    IF im_format IS NOT INITIAL.
      CONCATENATE: lv_req_body '&format=' im_format INTO lv_req_body.
    ENDIF.
*
    IF im_margin_top IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginTop=' im_margin_top INTO lv_req_body.
    ENDIF.
*
    IF im_margin_right IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginRigth=' im_margin_right INTO lv_req_body.
    ENDIF.
*
    IF im_margin_bottom IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginBottom=' im_margin_bottom INTO lv_req_body.
    ENDIF.
*
    IF im_margin_left IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginLeft=' im_margin_left INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      TRY.
          lo_response->get_binary(
            RECEIVING
              r_value  = ex_pdf
          ).
        CATCH cx_web_message_error.
          ex_mess = 'Error reading response. Process aborted'.
          ex_subrc = 4.
      ENDTRY.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Generate QR Code&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zgenerate_qr_code DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: generate_qr_code
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_data)           TYPE  string
      EXPORTING
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_qr_code)            TYPE  xstring,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zgenerate_qr_code IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc   TYPE sysubrc,
          lv_mess    TYPE string,
          lv_qr_code TYPE xstring.
*
    CALL METHOD generate_qr_code
      EXPORTING
        im_url     = 'https://api-eu.renda.io/totp/generateQRCode'
        im_api_key = '<your API key>'
        im_data    = 'www.google.com'
      IMPORTING
        ex_subrc   = lv_subrc
        ex_mess    = lv_mess
        ex_qr_code = lv_qr_code.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_qr_code ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD generate_qr_code.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Accept'
            i_value = '*/*' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'data=' im_data INTO lv_req_body.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      TRY.
          lo_response->get_binary(
            RECEIVING
              r_value  = ex_qr_code ).
        CATCH cx_web_message_error.
          ex_mess = 'Error reading response. Process aborted'.
          ex_subrc = 4.
      ENDTRY.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Onboard user for TOTP

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zonboard_user DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: onboard_user
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_user_id)        TYPE  string
        VALUE(im_application_id) TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
        VALUE(im_token_length)   TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_secret_key)     TYPE  string
        VALUE(ex_otp_url)        TYPE  string
        VALUE(ex_qr_code)        TYPE  string
        VALUE(ex_token)          TYPE  string
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zonboard_user IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc      TYPE sysubrc,
          lv_mess       TYPE string,
          lv_secret_key TYPE string,
          lv_otp_url    TYPE string,
          lv_qr_code    TYPE string,
          lv_token      TYPE string.
*
    CALL METHOD onboard_user
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/onboardUser'
        im_api_key        = '<your API key>'
        im_user_id        = 'johnSmith@gmail.com'
        im_application_id = 'Renda.io'
        im_token_validity = '120'
        im_token_length   = '7'
      IMPORTING
        ex_secret_key     = lv_secret_key
        ex_otp_url        = lv_otp_url
        ex_qr_code        = lv_qr_code
        ex_token          = lv_token
        ex_mess           = lv_mess
        ex_subrc          = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_secret_key ).
    out->write( lv_otp_url ).
    out->write( lv_qr_code ).
    out->write( lv_token ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD onboard_user.
*
    TYPES: BEGIN OF ltyp_response,
             secretkey TYPE string,
             otpurl    TYPE string,
             qrcode    TYPE string,
             token     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'userID=' im_user_id '&applicationID=' im_application_id INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenValidity=' im_token_validity INTO lv_req_body.
    ENDIF.
    IF im_token_length IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenLength=' im_token_length INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_secret_key = ls_response-secretkey.
      ex_otp_url = ls_response-otpurl.
      ex_qr_code = ls_response-qrcode.
      ex_token = ls_response-token.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Validate OTP using secret key

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zverify_otp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: verify_otp
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_secret)         TYPE  string
        VALUE(im_token)          TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_is_valid)       TYPE  abap_boolean
        VALUE(ex_token)          TYPE  string
        VALUE(ex_time_used)      TYPE  string
        VALUE(ex_time_remaining) TYPE  string
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zverify_otp IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc          TYPE sysubrc,
          lv_mess           TYPE string,
          lv_is_valid       TYPE abap_boolean,
          lv_token          TYPE string,
          lv_time_used      TYPE string,
          lv_time_remaining TYPE string.
*
    CALL METHOD verify_otp
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/verifyOTP'
        im_api_key        = '<your API key>'
        im_secret         = '<secret>'
        im_token          = '<token>'
        im_token_validity = '120'
      IMPORTING
        ex_is_valid       = lv_is_valid
        ex_token          = lv_token
        ex_time_used      = lv_time_used
        ex_time_remaining = lv_time_remaining
        ex_mess           = lv_mess
        ex_subrc          = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    IF lv_subrc IS INITIAL.
      IF lv_is_valid IS INITIAL.
        out->write( 'Token is not valid' ).
      ELSE.
        out->write( 'Token is valid' ).
      ENDIF.
    ENDIF.
    out->write( lv_token ).
    out->write( lv_time_used ).
    out->write( lv_time_remaining ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD verify_otp.
*
    TYPES: BEGIN OF ltyp_response,
             isvalid       TYPE abap_boolean,
             token         TYPE string,
             timeused      TYPE string,
             timeremaining TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'secret=' im_secret '&token=' im_token INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenDuration=' im_token_validity INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        "ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_is_valid = ls_response-isvalid.
      ex_token = ls_response-token.
      ex_time_used = ls_response-timeused.
      ex_time_remaining = ls_response-timeremaining.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Retrieve OTP for a secret key

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zget_otp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: get_otp
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_secret)         TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
        VALUE(im_token_length)   TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_current_token)  TYPE  string
        VALUE(ex_time_used)      TYPE  string
        VALUE(ex_time_remaining) TYPE  string
        VALUE(ex_previous_token) TYPE  string
        VALUE(ex_next_token)     TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zget_otp IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc          TYPE sysubrc,
          lv_mess           TYPE string,
          lv_current_token  TYPE string,
          lv_time_used      TYPE string,
          lv_time_remaining TYPE string,
          lv_previous_token TYPE string,
          lv_next_token     TYPE string.
*
    CALL METHOD get_otp
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/getOTP'
        im_api_key        = '<your API key>'
        im_secret         = '<your secret>'
        im_token_validity = '120'
        im_token_length   = '7'
      IMPORTING
        ex_current_token  = lv_current_token
        ex_time_used      = lv_time_used
        ex_time_remaining = lv_time_remaining
        ex_previous_token = lv_previous_token
        ex_next_token     = lv_next_token
        ex_subrc          = lv_subrc
        ex_mess           = lv_mess.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_current_token ).
    out->write( lv_time_used ).
    out->write( lv_time_remaining ).
    out->write( lv_previous_token ).
    out->write( lv_next_token ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD get_otp.
*
    TYPES: BEGIN OF ltyp_response,
             currenttoken  TYPE string,
             timeused      TYPE string,
             timeremaining TYPE string,
             previoustoken TYPE string,
             nexttoken     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'secret=' im_secret INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenValidity=' im_token_validity INTO lv_req_body.
    ENDIF.
    IF im_token_length IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenLength=' im_token_length INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_current_token = ls_response-currenttoken.
      ex_time_used = ls_response-timeused.
      ex_time_remaining = ls_response-timeremaining.
      ex_previous_token = ls_response-previoustoken.
      ex_next_token = ls_response-nexttoken.
*
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Send SMS&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zsend_sms DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: send_sms
      IMPORTING
        VALUE(im_url)         TYPE  string
        VALUE(im_api_key)     TYPE  string
        VALUE(im_number)      TYPE  string
        VALUE(im_message)     TYPE  string
        VALUE(im_sender_name) TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_subrc)       TYPE  sysubrc
        VALUE(ex_mess)        TYPE  string,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zsend_sms IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc TYPE sysubrc,
          lv_mess  TYPE string.
*
    CALL METHOD send_sms
      EXPORTING
        im_url         = 'https://api-eu.renda.io/communication/sendSMS'
        im_api_key     = '<your api key>'
        im_number      = '<mobile number>'
        im_message     = 'Hello world'
        im_sender_name = 'Renda.io'
      IMPORTING
        ex_mess        = lv_mess
        ex_subrc       = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD send_sms.
*
    TYPES: BEGIN OF ltyp_response,
             secretkey TYPE string,
             otpurl    TYPE string,
             qrcode    TYPE string,
             token     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'number=' im_number '&message=' im_message INTO lv_req_body.
    IF im_sender_name IS NOT INITIAL.
      CONCATENATE lv_req_body '&senderName=' im_sender_name INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}


# FAQs

Explore a wide range of frequently asked questions

## Regional Availability

### Where is the API engine hosted?

Renda microservices are currently hosted in 3 regions spread across the world to offer you the lowest latency for your API calls.

* Ireland (Europe)
* North Virginia (America)
* Mumbai (Asia Pacific)

We have plans in the pipeline to expand to other regions very soon. Please drop us a line if you need the microservice hosted closer to a location near you. We will be happy to review your request and provide assistance.

## Trial Plan

### Do you offer any free plans?

Renda offers a generous 50 rendas for absolute free of costs each month which can be used towards API calls.&#x20;

## Billing Cycle

### When will I be charged?

We will charge the card in the file once a month if your consumption is over > 50 renda units based on a simple volumetric pricing slab.

## Rate card

{% hint style="info" %}
The prices below are effective from January 1, 2026.
{% endhint %}

| Renda Units          | Per Renda Cost         | Flat Fees |
| -------------------- | ---------------------- | --------- |
| 0 - 50               | £0.00                  | £0.00     |
| 51 - 10000           | £0.025                 | £30       |
| 10,001 - 100,000     | £0.01                  | £200      |
| 100,001 - 250,000    | £0.00                  | £1500     |
| 250,001 - 500,000    | £0.00                  | £2500     |
| Greater than 500,000 | Contact us for pricing |           |

## Renda Units

<table><thead><tr><th width="300">Microservice</th><th>Renda Unit Consumption</th></tr></thead><tbody><tr><td>HTML to PDF APIs</td><td>1 unit</td></tr><tr><td>PDF Transformation APIs</td><td>1 unit</td></tr><tr><td>Time Based Authentication APIs</td><td>2 unit</td></tr><tr><td>Communication (SMS) APIs</td><td>10 unit per 160 character SMS (0 - 50 Rendas)</td></tr><tr><td></td><td>4 unit per 160 character SMS (51 - 10000 Rendas)</td></tr><tr><td></td><td>2 unit per 160 character SMS (10001+ Rendas)</td></tr></tbody></table>

## Pricing Estimator

| Usage         | Calculation                                                        | Monthly Cost |
| ------------- | ------------------------------------------------------------------ | ------------ |
| 300 units     | Falls in the “0 – 50” band → £0.00 flat                            | £0.00        |
| 701 units     | Falls in the “51 – 10,000” band → (701 × £0.025) + £30             | £47.53       |
| 10,001 units  | Falls in the “10,001 – 100,000” band → (10,001 × £0.01) + £200     | £300.01      |
| 150,000 units | Falls in the “100,001 – 250,000” band (£0 per Renda + £1,500 flat) | £1,500.00    |
| 300,000 units | Falls in the “250,001 – 500,000” band (£0 per Renda + £2,500 flat) | £2,500.00    |

## Backend Infrastructure

Renda's backend infrastructure is powered by AWS Lambda.&#x20;

## Scalability

Renda's lambda powered infrastructure provides dynamic load scaling that seamlessly grows behind the scenes to accommodate and service large volume of API calls concurrently

## Subscription

### **How do I subscribe to Renda?**

* As part of the registration process Renda microservices can be subscribed by providing payment card details. Providing card details is a mandatory. This protects the platform from being abused. With its generous free tier, Renda will not bill you for the first 500 API call each month.&#x20;
* Alternatively, Renda can also be subscribed from the developer user dashboard.&#x20;

### How do I Cancel Subscription?

Log into developer user dashboard, navigate to 'Manage Billing' section and simply cancel.&#x20;

## Rate Limits

Renda employs a number of safety guards against burst of incoming traffic to maximize the platform's stability. Users who perform multiple APIs requests in quick successions may see error responses that show up as HTTP status code 429. All requests are throttled using token bucket algorithm where a token counts for a request.

### What is the current rate limit?

100 requests per second. If you need higher concurrency support, please raise a support ticket specifying a reason for the upgrade

## Font support&#x20;

### PDF transformation

Renda supports the following fonts for HTML to PDF transformation.&#x20;

* Arial
* Arial Black
* Avant Garde
* Comic Sans
* Courier New
* Georgia
* Helvetica
* Impact
* Kunstler
* Nanum Gothic
* Segoe
* Simhei
* Tahoma
* Times New Roman
* Verdana

If you need any other custom font support please raise a support ticket.

## PDF Rendering Engine

Renda uses headless Chromium engine to convert HTML/Text documents into PDF.

### Is there a payload limit?

Yes the payload limit is currently limited to \~6MB. You will encounter processing error once this limit is breached. Please write to <support@renda.io> if you need a higher payload limit.

## Consulting Services

### Do you offer custom built microservices?

Yes we do. Please write to us, we will be glad to work with you in bringing your ideas to life.

## Data Storage

Renda only stores metadata associated with your API request for billing purposes. We do not store your any application related data on our servers. As soon as the service request is fulfilled the application data is purged.

## Payments processing & Security

We use Stripe for subscription billing who employ world class security to save guard your card and personal details. Renda does not store your card or billing details.&#x20;

## Privacy Policy

[Full documentation available here](https://www.arch-global.com/privacy-policy/)

## Support

### How do I report issues?

Simply login into our ticketing system to raise tickets. Alternatively you are welcome to email us at <support@renda.io>

[Renda Helpdesk](http://helpdesk.renda.io/support/home)

### Feedbacks/feature requests?

Please email support at <support@renda.io> or raise a ticket at our helpdesk

[Renda Helpdesk](http://helpdesk.renda.io/support/home)


# Changelog

Keep upto date with all new our features and improvements!

## Coming soon 🚀

PDF Utility

* Merge multiple PDF documents into one

## R3 2.0 - 2023-01-09

## **Added**

* PDF to PNG image transformation API
* PDF to Postscript transformation API

## Enhanced

* New font packs for HTML to PDF transformation
* Error handling

## R2 1.1 - 2022-01-28

## Enhanced

* Generate PDF service header + footer support
* Bug fixes and enhancements

## R1 1.0 - 2021-05-04

* QR Code Generation
* Authentication service - TOTP
* SMS Gateway
* Code Samples

## Beta 0.9 - 2020-10-20

### Added

* Heartbeat check feature to ping Renda Service
* Password protect PDF with 256 bit AES encryption algorithm

### Changed

Updated API signature to include encryption key.

## Alpha 1.0 - 2020-05-10

* Initial Release

### Added

* HTML to PDF transformation API

### Features

* HTML to PDF transformation
* SVG Support
* Multiple font support
* Margin Support
* Orientation Support


# Open Source Credits

Renda is powered by a number of open source software. We would like to send  a big thank you to the following great projects and thousands of fantastic contributors in this ecosystem that make it absolutely great!

[Express](https://www.npmjs.com/package/express)

[Serverless](https://www.npmjs.com/package/serverless)

[Middy](https://www.npmjs.com/package/middy)

[JWT](https://www.npmjs.com/package/jsonwebtoken)

[UUID](https://www.npmjs.com/package/uuid)

[QPDF](https://www.npmjs.com/package/qpdf)

[Puppeteer](https://pptr.dev/)

[OTP Library](https://www.npmjs.com/package/otplib)


