# Fetch Images

Valify offers an API to retrieve transaction images, any time after the service has been called. This API receives a reference to the Transaction ID of the transaction being inquired, and returned its relevant images.

The Fetch Images API is a very sensitive API, as it allows access to images for all your transactions. Therefore, to secure your data, it is a requirement that the Fetch Images response is encrypted in transit, and decrypted on the recipient's side.

To gain access to this API, you need to contact Valify to avail this service. You also need to generate an RSA 4096 key pair. The private key is stored on the recipient side, and the public key is provided to Valify to be stored. This way, the API response payload can be encrypted for you to decrypt it on your side. Please contact **techsupport@valify.me** for more information.

The RSA 4096 key pair can be generated using the following commands:

With Passphrase:

`openssl genrsa -des3 -out private.pem 4096`\
`openssl rsa -in private.pem -outform PEM -pubout -out public.pem`

Without Passphrase:

`openssl genrsa -out private.pem 4096`\
`openssl rsa -in private.pem -outform PEM -pubout -out public.pem`

The encryption process works as follows:

1. Each time this API is called, a new AES 256 key is generated.
2. The response data (JSON string) is encrypted with the AES key.
3. The AES key is then encrypted with the public key provided to Valify.
4. The encrypted key and encrypted data are encoded into base64 format is sent in the API response.
5. The response recipient should then decode the base64-encoded key and data, decrypt the AES key using their RSA private key, and use the decrypted AES key to decrypt the transaction data, producing a JSON string.

## Transaction Fetch images

<mark style="color:green;">`POST`</mark> `https://<base-url>/api/v1/transaction/fetch-images/`

#### Headers

| Name          | Type   | Description            |
| ------------- | ------ | ---------------------- |
| Content-Type  | string | application/json       |
| Authorization | string | Bearer \<access-token> |

#### Request Body

| Name            | Type    | Description                                                       |
| --------------- | ------- | ----------------------------------------------------------------- |
| bundle\_key     | string  | A bundle key provided to you by Valify.                           |
| transaction\_id | string  | Transaction reference ID, returned in the service API's response. |
| is\_cropped     | boolean | A boolean to get the original or the cropped image.               |

{% tabs %}
{% tab title="200 " %}
```python
{
    'key': '<string>',
    'data': '<string>'
}
```
{% endtab %}

{% tab title="400 " %}
```python
{
    "message": "Bad Request – invalid request received (e.g. missing Bundle key, required parameters or invalid json) | Make sure all the required parameters are included"
}
```
{% endtab %}

{% tab title="401 " %}
```python
{
    "message": "Unauthorized – your Bundle key is invalid"
}
```
{% endtab %}

{% tab title="403 " %}
```python
{
    "message": "Forbidden – specified access_token could not be found"
}
```
{% endtab %}

{% tab title="404 " %}
```python
{
    "message": "Not Found"
}
```
{% endtab %}

{% tab title="415 " %}
```python
{
    "message": "Unsupported Media Type"
}
```
{% endtab %}

{% tab title="422 " %}
```python
{
    "message": "<error-description>",
    "error_code": <valify-error-code>
}
```
{% endtab %}

{% tab title="500 " %}
```python
{
    "message": "Internal Server Error"
}
```
{% endtab %}
{% endtabs %}



{% tabs %}
{% tab title="Python 3" %}
```python
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import base64
import json
import requests

private_key_str = "<rsa 4096 private key>"
private_key_bytes = str.encode(private_key_str)
private_key = serialization.load_pem_private_key(
        private_key_bytes,
        password=None,
        backend=default_backend()
    )
    
def unpad(s): return s[0:-s[-1]]

def decrypt_aes_key(encrypted_aes_key):
    aes_key = private_key.decrypt(
        encrypted_aes_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return aes_key

def decrypt_data(enc_data, key, iv):
    backend = default_backend()
    sha256 = algorithms.AES(key)
    cipher = Cipher(sha256, modes.CBC(iv), backend=backend)
    decryptor = cipher.decryptor()

    dec_data = decryptor.update(enc_data)
    return unpad(dec_data)

def request_data():
    token = "<token>"
    data = {
        "bundle_key": "<bundle key>",
        "transaction_id": "<str>"
        "is_cropped": "<bool>"
    }

    r = requests.post("https://<base-url>/api/v1/transaction/fetch-images/",
            json=data,
            headers={'Authorization' :'Bearer %s' % token}
        )
    return r.json()


response = request_data()
encrypted_data = base64.b64decode(response['data'])
encrypted_aes_key = base64.b64decode(response['key'])
iv = base64.b64decode(response['iv'])

aes_key = decrypt_aes_key(encrypted_aes_key)
decrypted_data = decrypt_data(encrypted_data, aes_key, iv)
data = json.loads(decrypted_data)

```
{% endtab %}
{% endtabs %}
