# API Signature & Webhook Validation

To ensure the authenticity and integrity of your message, all API request must be signed securely by adding `X-Fp-Signature` in request header. Similarly, the partners' backend system should validate `X-Fp-Signature` in request header of the webhook notification sent by FaTPay as well.

## Signature for API request

As Premium Partner, you will generate `APIPrivateKey` during \[[onboarding](https://dev.fatpay.org/get-started/onboarding "mention")] process, which is essential to the signature producing.

{% hint style="danger" %}
**Do not share the private key to anyone or public repositories.** Your account might be blocked once the credential leakage is detected. FaTPay reserves the right to take any other actions and pursue any other legal rights available to us.
{% endhint %}

### Procedure

Please follow this guide to generate the signature, which uses `RSA-SHA256`  algorithm.

1. **Retrieve parameters**
   * Firstly, retrieve all the common header parameters except `X-Fp-Signature`. <mark style="color:red;">**Convert all the keys to lowercase**</mark> and build a map with all key-value pairs;
   * Secondly, retrieve all query parameters and add to the map;
   * Thirdly, remove all the items with null keys or null values;
2. **Sort parameters**
   * Sort all parameter <mark style="color:red;">**keys**</mark> in ascending order(as per ASCII values of the characters);
3. **Prepare&#x20;*****`to-be-signed-payload`***&#x20;
   * Firstly convert the sorted map to a string *`request-key-value-parameters-string`* in the form of `key=value` and concatenate them with `&` character as the separator;
   * Then concatenate the final string by the following rule. Please exclude `http`/`https` in *`request-domain`*. And *`request-method`* should be all uppercase as `GET`/`POST`;

     > *`request-method`* + *`request-domain`* + *`request-URI`* + *`?`* + *`request-key-value-parameters-string`*
   * Now we get a string called *`to-be-signed-payload`*;
4. **Compute signature**
   * Next use `APIPrivateKey` to generate signature for the string *`to-be-signed-payload`* from last step via `RSA-SHA256` algorithm. Please check \[[api-signature-demo](https://dev.fatpay.org/appendix/demo/api-signature-demo "mention")];
5. **Assign signature**
   * Finally, assign the signature to `X-Fp-Signature` in the request header, and call FaTPay APIs. Once it's received by FaTPay gateway, it will be validated with `APIPublicKey`. If it is passed, the data will be responded accordingly;

### Example

Let's take a **virtual** API as `testSignature` with `GET` method to go through the whole procedure step by step. The URI of this API is `api/testsignature`.

{% code title="Request parameters" lineNumbers="true" %}

```javascript
{
  "page": 1,
  "index": null,
  "size": 10
}
```

{% endcode %}

<pre class="language-javascript" data-title="Common header parameters" data-line-numbers><code class="lang-javascript">{
  "X-Fp-Nonce": 748219,
  "X-Fp-Partner-Id": "mqMBpCIP630LJxLY",
  "X-Fp-Timestamp": 1656600459,
  "X-Fp-Version": "v1.0"
<strong>}
</strong></code></pre>

#### **Retrieve parameters**

Firstly, retrieve all the common header parameters except `X-Fp-Signature`. <mark style="color:red;">**Convert all the keys to lowercase**</mark> and build a map with all key-value pairs.

{% code lineNumbers="true" %}

```json
{
  "x-fp-partner-id": "mqMBpCIP630LJxLY",
  "x-fp-timestamp": 1656600459,
  "x-fp-nonce": 748219,
  "x-fp-version": "v1.0"
}
```

{% endcode %}

Secondly, retrieve all query parameters and add to the map.

{% code lineNumbers="true" %}

```json
{
  "x-fp-partner-id": "mqMBpCIP630LJxLY",
  "x-fp-timestamp": 1656600459,
  "x-fp-nonce": 748219,
  "x-fp-version": "v1.0"
  "page": 1,
  "index": null,
  "size": 10
}
```

{% endcode %}

Thirdly, remove all the items with null keys or null values. Now we get

{% code lineNumbers="true" %}

```json
{
  "x-fp-partner-id": "mqMBpCIP630LJxLY",
  "x-fp-timestamp": 1656600459,
  "x-fp-nonce": 748219,
  "x-fp-version": "v1.0"
  "page": 1,
  "size": 10
}
```

{% endcode %}

**Sort parameters**

Sort all parameter <mark style="color:red;">**keys**</mark> in ascending order(as per ASCII values of the characters);

{% code lineNumbers="true" %}

```javascript
{
  "page": 1,
  "size": 10,
  "x-fp-nonce": 748219,
  "x-fp-partner-id": "mqMBpCIP630LJxLY",
  "x-fp-timestamp": 1656600459,
  "x-fp-version": "v1.0"
}
```

{% endcode %}

**Prepare&#x20;*****`to-be-signed-payload`***

Firstly convert the sorted map to a string *`request-key-value-parameters-string`* in the form of `key=value` and concatenate them with `&` character as the separator. We get

{% code overflow="wrap" %}

```
page=1&size=10&x-fp-nonce=748219&x-fp-partner-id=mqMBpCIP630LJxLY&x-fp-timestamp=1656600459&x-fp-version=v1.0
```

{% endcode %}

Then concatenate the final string by the rule:

> *`request-method`* + *`request-domain`* + *`request-URI`* + *`?`* + *`request-key-value-parameters-string`*

Now *`to-be-signed-payload`* turns out to be:

{% code overflow="wrap" %}

```html
GETapi.ramp.fatpay.xyz/api/testsignature?page=1&size=10&x-fp-nonce=748219&x-fp-partner-id=mqMBpCIP630LJxLY&x-fp-timestamp=1656600459&x-fp-version=v1.0
```

{% endcode %}

**Compute signature**

Next use `APIPrivateKey` to generate signature for the string *`to-be-signed-payload`* from last step via `RSA-SHA256` algorithm. The signature:

> akZjLiZak0v07CzJoKr7/uKgsAzW2a8DXevy98xg3k6HeOtiU2OyWeEYuQtX/G5EuOs5NeagnIwsIxxiFCQoo6hh2OkgxuEphUQNg1B2HO9cYxpJWRKJfxcf20fJ/OIKFfI75PLMqSGRSmx5tVl+9vP4mBzQwpFtgYok2nrWZU4=

**Assign signature**

Finally, assign the signature to `X-Fp-Signature` in the request header, and call FaTPay APIs.

{% code overflow="wrap" %}

```shell
curl -X 'https://api.ramp.fatpay.xyz/api/testsignature?page=1&size=10' \
  -H 'Content-Type: application/json' \
  -H 'X-Fp-Nonce: 748219' \
  -H 'X-Fp-Partner-Id: mqMBpCIP630LJxLY' \
  -H 'X-Fp-Timestamp: 1656600459' \
  -H 'X-Fp-Version: v1.0' \
  -H 'X-Fp-Signature: akZjLiZak0v07CzJoKr7/uKgsAzW2a8DXevy98xg3k6HeOtiU2OyWeEYuQtX/G5EuOs5NeagnIwsIxxiFCQoo6hh2OkgxuEphUQNg1B2HO9cYxpJWRKJfxcf20fJ/OIKFfI75PLMqSGRSmx5tVl+9vP4mBzQwpFtgYok2nrWZU4='
```

{% endcode %}

## Webhook validation

{% hint style="warning" %}
For security reason, we highly recommend the backend system of our partners to validate the signature of webhook whenever receiving a notification of order status change.
{% endhint %}

FaTPay will inform the partners about the order status changing by calling the predefined webhook endpoints. The partners' backend system should validate `X-Fp-Signature` in request header to check the authenticity and integrity of such webhook message. Use `WebhookPublicKey` to verify that FaTPay generated a webhook request and that it didn’t come from a server acting like FaTPay.

FaTPay generates signatures using`RSA-SHA256` algorithm. The validation procedure is quite similar to the signature generating procedure.

1. **Retrieve parameters**
   * Firstly, extract all the parameters starting with `X-Fp` except `X-Fp-Signature` from header. <mark style="color:red;">**Convert all the keys to lowercase**</mark> and build a map with all key-value pairs. Check [header details;](https://dev.fatpay.org/reference/api-reference/webhooks/webhook-for-order-events)
   * Secondly, retrieve all query parameters and add to the map;
   * Thirdly, remove all items with null keys or null values;
2. **Sort parameters**
   * Sort all parameter <mark style="color:red;">**keys**</mark> in ascending order(as per ASCII values of the characters);
3. **Prepare&#x20;*****`to-be-verified-payload`***&#x20;
   * Firstly convert the sorted map to a string in the form of `key=value` and concatenate them with `&` character as the separator;
   * Then concatenate the final string by the rule: `request method` + `request domain` + `request URI` + `?` + `<request key-value parameters string>`. Please remember to exclude `http://` or `https://` in `request domain`;
   * Now you will get a string called *`to-be-verified-payload`*;
4. **Validate signature**
   * Finally, extract the *`to-be-verified-signature`* from `X-Fp-Signature` in the webhook header. Validate the signature(`RSA-SHA256` algorithm) with the string *`to-be-verified-payload`* from last step and `WebhookPublicKey` provided by FaTPay during \[[onboarding](https://dev.fatpay.org/get-started/onboarding "mention")] process;
