# 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](/get-started/onboarding.md)] 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](/appendix/demo/api-signature-demo.md)];
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;](/reference/api-reference/webhooks/webhook-for-order-events.md)
   * 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](/get-started/onboarding.md)] process;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.fatpay.org/reference/api-reference/verification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
