# Klasha Wire API

### Summary

Give merchants the ability to send out funds from their collection balance via API using our internal Klasha rates.

**Coverage**

See all available currencies[ here](https://developers.klasha.com/transfers/currency-coverage)

You can transfer money in four easy steps:

1. Generate a bearer token
2. Create a beneficiary
3. Generate a quote for the beneficiary
4. Initiate a payment

{% hint style="info" %}
Before you begin!

* [Link](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E) to the Postman collection
* Find your keys on the Klasha Dashboard → Settings → Generate API Keys ([here](https://dashboard.klasha.com/settings/keys))

<img src="https://257545343-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNw4nU37LIEg41plxXG5u%2Fuploads%2FvBXI8QATrncq17zlRm1P%2Fdashboad-klasha-settings.png?alt=media&#x26;token=1ebaf2b3-7e99-4490-9ede-a660c8d0035c" alt="" data-size="original">
{% endhint %}

<details>

<summary>Encryption Algorithm</summary>

You need to encrypt the entire create transfer payload that we specify on the previous point (here). In order to encrypt the body correctly, you’d need the encryptionKey (that you can obtain following this guide here). We also provided an example in Java of the encryption algorithm in order to help you.

```java
public static String encryptCBC(String stringToEncrypt, String encryptionkey) {
    try {
        SecureRandom sr = new SecureRandom();
        byte[] salt = new byte[8];
        sr.nextBytes(salt);
        final byte[][] keyAndIV =GenerateKeyAndIV(32, 16, 1, salt, password.getBytes(StandardCharsets.UTF_8),
                MessageDigest.getInstance("MD5"));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyAndIV[0], "AES"), new IvParameterSpec(keyAndIV[1]));
        byte[] encryptedData = cipher.doFinal(stringToEncrypt.getBytes(StandardCharsets.UTF_8));
        byte[] prefixAndSaltAndEncryptedData = new byte[16 + encryptedData.length];
        // Copy prefix (0-th to 7-th bytes)
        System.arraycopy("Salted__".getBytes(StandardCharsets.UTF_8), 0, prefixAndSaltAndEncryptedData, 0, 8);
        // Copy salt (8-th to 15-th bytes)
        System.arraycopy(salt, 0, prefixAndSaltAndEncryptedData, 8, 8);
        // Copy encrypted data (16-th byte and onwards)
        System.arraycopy(encryptedData, 0, prefixAndSaltAndEncryptedData, 16, encryptedData.length);
        return Base64.getEncoder().encodeToString(prefixAndSaltAndEncryptedData);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}




public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {

    int digestLength = md.getDigestLength();
    int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;
    byte[] generatedData = new byte[requiredLength];
    int generatedLength = 0;

    try {
        md.reset();

        // Repeat process until sufficient data has been generated
        while (generatedLength < keyLength + ivLength) {

            // Digest data (last digest if available, password data, salt if available)
            if (generatedLength > 0)
                md.update(generatedData, generatedLength - digestLength, digestLength);
            md.update(password);
            if (salt != null)
                md.update(salt, 0, 8);
            md.digest(generatedData, generatedLength, digestLength);

            // additional rounds
            for (int i = 1; i < iterations; i++) {
                md.update(generatedData, generatedLength, digestLength);
                md.digest(generatedData, generatedLength, digestLength);
            }

            generatedLength += digestLength;
        }

        // Copy key and IV into separate byte arrays
        byte[][] result = new byte[2][];
        result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);
        if (ivLength > 0)
            result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);

        return result;

    } catch (DigestException e) {
        throw new RuntimeException(e);

    } finally {
        // Clean out temporary data
        Arrays.fill(generatedData, (byte) 0);
    }
}


```

</details>

### Integration step

**Generate a bearer token**

Using the Token endpoint on the Postman collection, the token can be obtained from the headers under the header name: <mark style="color:red;">token</mark>

<mark style="color:green;">`POST`</mark> `{{env_url}}/auth/account/v2/login`

#### Request Body

| Name                                       | Type     | Description |
| ------------------------------------------ | -------- | ----------- |
| username<mark style="color:red;">\*</mark> | username |             |
| password<mark style="color:red;">\*</mark> | password |             |

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

```json
{
    "message": "success",
    "error": null,
    "data": {
        "token": "This is your token"
    }
}
```

{% endtab %}
{% endtabs %}

**Create a beneficiary**

## Make a POST call to the Create Merchant Beneficiary API to create your beneficiary

<mark style="color:green;">`POST`</mark> `{{env_url}}/merchant/merchantbeneficiary/create`

Make a <mark style="color:green;">POST</mark> call to the Create Merchant Beneficiary API to create your beneficiary. See an  example of the payload you need to encrypt and send in order to create a beneficiary

The encrypted JSON body for the request can be found in the Postman [link](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E).

You’d need to pass, as header the `x-auth-token`. This can be obtained from your merchant dashboard → Settings → Generate API keys → **Merchant public key.**

#### Headers

| Name                                            | Value               |
| ----------------------------------------------- | ------------------- |
| Authorization<mark style="color:red;">\*</mark> | Bearer {{token}}    |
| x-auth-token                                    | MERCHANT PUBLIC KEY |

#### Request Body

| Name                                                 | Type | Description              |
| ---------------------------------------------------- | ---- | ------------------------ |
| accountNumber<mark style="color:red;">\*</mark>      |      | 1234567890               |
| bankName<mark style="color:red;">\*</mark>           |      | Bank Name                |
| bankAddress<mark style="color:red;">\*</mark>        |      | Bank Address             |
| beneficiaryName<mark style="color:red;">\*</mark>    |      | Beneficiary Name         |
| beneficiaryAddress<mark style="color:red;">\*</mark> |      | Beneficiary Address      |
| country<mark style="color:red;">\*</mark>            |      | Country Name             |
| countryCode<mark style="color:red;">\*</mark>        |      | US                       |
| currency<mark style="color:red;">\*</mark>           |      | USD                      |
| phone<mark style="color:red;">\*</mark>              |      | phone number             |
| swiftCode<mark style="color:red;">\*</mark>          |      | SWFT1234                 |
| narration<mark style="color:red;">\*</mark>          |      | clothes                  |
| email<mark style="color:red;">\*</mark>              |      | <your.email@example.com> |
| routingNumber<mark style="color:red;">\*</mark>      |      | 12345                    |
| iban<mark style="color:red;">\*</mark>               |      | 045                      |

{% tabs %}
{% tab title="Encrypted Request " %}

```json
{
  "message": "encrypted request"
}
```

{% endtab %}

{% tab title="201: Created " %}

```json
Response
{
    "message": "success",
    "error": null,
    "data": {
        "accountNumber": "1234567890",
        "bankName": "Bank Name",
        "token": "d95a6930-233f-4699-a11f-0d1337a34cce",
        "beneficiaryName": "Beneficiary Name",
        "id": 345
    }
}
```

{% endtab %}
{% endtabs %}

**Generate a quote**

## Make a POST call to the Create Quote API to generate your quote

<mark style="color:green;">`POST`</mark> `{{env_url}}/wallet/wire/generate/quote`

Make a POST call to the Create Quote API to generate your quote. See an example of the payload you need to encrypt and send in order to generate your quote.

The encrypted JSON body for the request can be found in the Postman [link](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E) as well as other APIs.

You’d need to pass, as header the `x-auth-token`. This can be obtained from your merchant dashboard → Settings → Generate API keys → **Merchant public key.**

#### Headers

| Name          | Value               |
| ------------- | ------------------- |
| Authorization | Bearer {{token}}    |
| x-auth-token  | MERCHANT PUBLIC KEY |

#### Request Body

| Name                                                  | Type | Description                                       |
| ----------------------------------------------------- | ---- | ------------------------------------------------- |
| sourceCurrency<mark style="color:red;">\*</mark>      |      | NGN                                               |
| destinationCurrency<mark style="color:red;">\*</mark> |      | USD                                               |
| beneficiary<mark style="color:red;">\*</mark>         |      | beneficiar87954c4f-736a-4e09-b588-76ab9c13bafeyId |
| destinationAmount<mark style="color:red;">\*</mark>   |      | 1000.00                                           |

{% tabs %}
{% tab title="Encrypted Request" %}

```json
{
  "message": "encrypted request"
}
```

{% endtab %}

{% tab title="201: Created " %}

```json
Response
{
    "message": "success",
    "error": null,
    "data": {
        "id": 1,
        "sourceCurrency": "NGN",
        "sourceAmount": 575338.5,
        "destinationCurrency": "USD",
        "destinationAmount": 1000,
        "destinationFees": 27.5,
        "sourceFees": 15821.808749999998,
        "rate": 575.3385,
        "klashaWireStatus": "PENDING",
        "merchantBeneficiary": "87954c4f-736a-4e09-b588-76ab9c13bafe",
        "quoteToken": "842dcd42-8f95-4a3b-a5f3-07a3d0416119",
        "createdAt": "2023-10-09T13:11:29.478",
        "updatedAt": "2023-10-09T13:11:29.478"
    }
}
```

{% endtab %}
{% endtabs %}

**Initiate a payment**

## Make a POST call to the Initiate Payment API&#x20;

<mark style="color:green;">`POST`</mark> `{{env_url}}/wallet/wire/initiate`

Make a POST call to the Initiate Payment API to convert your quote into an initialised payment.&#x20;

See an example of the payload you need to encrypt and send in order to generate your quote.

The encrypted JSON body for the request can be found in the Postman [link](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E) as well as other APIs

You’d need to pass, as header the `x-auth-token`. This can be obtained from your merchant dashboard → Settings → Generate API keys → **Merchant public key.**

#### Headers

| Name          | Value               |
| ------------- | ------------------- |
| Authorization | Bearer {{token}}    |
| x-auth-token  | MERCHANT PUBLIC KEY |

#### Request Body

| Name                                          | Type | Description                                     |
| --------------------------------------------- | ---- | ----------------------------------------------- |
| quoteToken<mark style="color:red;">\*</mark>  |      | 842dcd42-8f95-4a3b-a5f3-07a3d0416119            |
| beneficiary<mark style="color:red;">\*</mark> |      | 87954c4f-736a-4e09-b588-76ab9c13bafe            |
| narration<mark style="color:red;">\*</mark>   |      | School fees                                     |
| invoiceUrl<mark style="color:red;">\*</mark>  |      | [www.invoiceURL.com](http://www.invoiceURL.com) |

{% tabs %}
{% tab title="Encrypted Request" %}

```json
{
  "message": "encrypted request"
}
```

{% endtab %}

{% tab title="201: Created " %}

```json
Response
{
    "message": "success",
    "error": null,
    "data": {
        "id": 5,
        "sourceCurrency": "NGN",
        "sourceAmount": 575338.5,
        "destinationCurrency": "USD",
        "destinationAmount": 1000,
        "narration": "School fees",
        "destinationFees": 27.5,
        "sourceFees": 15821.81,
        "rate": 575.3385,
        "klashaWireStatus": "PENDING",
        "transactionReference": "KWire-32f1d4c6-4560-4033-8cf6-713d405ec10d",
        "merchantBeneficiary": "7ed8d2e3-8709-4202-8842-7757946ee194",
        "quoteToken": "1c8eaf0d-3490-4774-ae86-7443e4f93557",
        "createdAt": "2023-10-26T12:44:37.355",
        "updatedAt": "2023-10-26T12:45:27.243"
    }
}
```

{% endtab %}
{% endtabs %}

**Fetch all your payments**

## Make a GET call to the Fetch All API

<mark style="color:blue;">`GET`</mark> `{{env_url}}/wallet/wire/fetch/all`

Make a GET call to the Fetch All API to retrieve all your previously initiated wire payments.

The URL can be found in the Postman [link](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E) well as other APIs

You’d need to pass, as header the `x-auth-token`. This can be obtained from your merchant dashboard → Settings → Generate API keys → **Merchant public key.**

#### Headers

| Name          | Value               |
| ------------- | ------------------- |
| Authorization | Bearer {{token}}    |
| x-auth-token  | MERCHANT PUBLIC KEY |

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

```json
Response
{
    "message": "success",
    "error": null,
    "data": [
         {
            "id": 46,
            "sourceCurrency": "NGN",
            "sourceAmount": 1628664.50,
            "destinationCurrency": "USD",
            "destinationAmount": 1000.00,
            "narration": "Test",
            "destinationFees": 27.50,
            "sourceFees": 44788.27,
            "rate": 0.000614,
            "klashaWireStatus": "PENDING",
            "transactionReference": "KWire-296aac06-f425-4d43-9e4c-611247959a88",
            "merchantBeneficiary": "e0595f0b-16b4-4b62-a317-fa00af40a7ec",
            "quoteToken": "71a6aff6-5c23-41e3-8b85-6918cf92ead6",
            "createdAt": "2024-07-09T19:00:52.218",
            "updatedAt": "2024-07-09T19:02:14.863"
        },
        {
            "id": 60,
            "sourceCurrency": "NGN",
            "sourceAmount": 1631321.37,
            "destinationCurrency": "USD",
            "destinationAmount": 1000.00,
            "narration": "Test",
            "destinationFees": 27.50,
            "sourceFees": 44861.34,
            "rate": 0.000613,
            "klashaWireStatus": "PENDING",
            "transactionReference": "KWire-bae3f6dc-aaec-4e6a-a963-cffe1a3899c5",
            "merchantBeneficiary": "633b70a6-da15-4bc5-b0ec-1eda041245e2",
            "quoteToken": "dbd4e976-ad5e-4555-aee5-d4afa59849c5",
            "createdAt": "2024-07-11T14:40:11.91",
            "updatedAt": "2024-07-11T14:41:29.237"
        }
     ...
    ]
}
```

{% endtab %}
{% endtabs %}

**Fetch a single payment by reference**

## Fetch by reference API to retrieve all your previously initiated wire payments.

<mark style="color:blue;">`GET`</mark> `{{env_url}}/wallet/wire/fetch/by/reference/<ref>`

Make a GET call to the Fetch by reference API to retrieve all your previously initiated wire payments.

The URL can be found in the Postman [link ](https://api.postman.com/collections/25963887-51087ebf-1aa8-4573-9259-9965bf043717?access_key=PMAT-01HF4CJMVK7BG3QSRHYH1CKE6E)well as other APIs

You’d need to pass the `transactionReference` you obtained when you initiated the payment, as a path variable.

You’d need to pass, as header the `x-auth-token`. This can be obtained from your merchant dashboard → Settings → Generate API keys → **Merchant public key.**

#### Headers

| Name          | Value               |
| ------------- | ------------------- |
| Authorization | Bearer {{token}}    |
| x-auth-token  | MERCHANT PUBLIC KEY |

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

```json
Response
{
    "message": "success",
    "error": null,
    "data": {
            "id": 46,
            "sourceCurrency": "NGN",
            "sourceAmount": 1628664.50,
            "destinationCurrency": "USD",
            "destinationAmount": 1000.00,
            "narration": "Test",
            "destinationFees": 27.50,
            "sourceFees": 44788.27,
            "rate": 0.000614,
            "klashaWireStatus": "PENDING",
            "transactionReference": "KWire-296aac06-f425-4d43-9e4c-611247959a88",
            "merchantBeneficiary": "e0595f0b-16b4-4b62-a317-fa00af40a7ec",
            "quoteToken": "71a6aff6-5c23-41e3-8b85-6918cf92ead6",
            "createdAt": "2024-07-09T19:00:52.218",
            "updatedAt": "2024-07-09T19:02:14.863"
    }
}
```

{% endtab %}
{% endtabs %}

&#x20;

{% hint style="info" %}
Notes

Klasha Wire Statuses

When you generate a quote and initiate a payment, one of the field in the response body is <mark style="color:red;">`klashaWireStatus`</mark>, here you can find all the possible cases and explanation:

* <mark style="color:orange;">PENDING</mark>: this is the status when a payment just get initialised through the API. This is not a final status.
* <mark style="color:yellow;">PROCESSING</mark>: this is when Klasha is actually processing the payment itself. This is not a final status.
* <mark style="color:green;">SUCCESSFUL</mark>: the klasha wire payment was executed successfully. Final status.
* <mark style="color:red;">CANCELLED</mark>: The payment has been cancelled from the Klasha finance/operation team, in result of previous communication with the merchant. Final status.
* <mark style="color:red;">FAILED</mark>: the initiated wire payments failed to be executed. Final status.
  {% endhint %}

**Quote expiry logic**

After you proceeded generating your quote, you can now convert that quote into an initiated payment.

The initiation would be successful if the quote is NOT expired.

A quote does not expire because of time but just if the rate in our system changed.

{% hint style="info" %}
**Example**

&#x20;If you generate a quote on 1st Oct at 11am and at 3pm the rate changes, you can convert your quote into a initiated payment until 2:59:59pm. Right after, then the rate get updated at 3pm, you won’t be able to initiate a payment with that quote and you’d have to generate a new quote.
{% endhint %}

In case you try to initiate a payment with an expired quote, you’d have a Bad Request response with the the following body:

```json
{
    "message": "Quote has expired or does not exist!",
    "error": "QuoteNotFoundException",
    "data": null
}
```
