> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zodia-custody.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Signing the Payload

> How makers and authorisers sign instruction payloads using their ECC keys

Some API calls (for example, `v3/api/servicedesk/approve`) require an additional signing process with the maker/authoriser private key, typically when the maker confirms/authoriser approves an instruction (see section "4. Confirm instruction as maker" below).
Before submitting the instruction to the HSM, you will need to sign the request payload with **api\_user\_pri\_key** (API user private key).
The content that must be signed is the stringified value of a part of this payload.
For more details about a **stringified value**, see [json-stable-stringify](https://github.com/ljharb/json-stable-stringify)

> **The signed payload must not include optional and empty fields**

The content to sign is the stringified value of the object named `request` and the resulting signature string should substitute placeholder `$$REPLACE`.

Assume the maker is confirming instructions, retreive the instructions using the API `v3/api/servicedesk/pending`, the response is like (no field ordering)

```json theme={null}
{
  "request": {
    "key2": "value2",
    "key1": "value1",   
    "key3": "value3"
  },
  "signature": "$$REPLACE$$"
}

```

Here the request payload needs to be ordered like,

```json theme={null}
{
  "key1": "value1",   
  "key2": "value2",
  "key3": "value3"
}

```

This is the string to be used for generating the signature using **api\_user\_pri\_key**, use it as value for signature field in the request.

Below is an example of how to sign it in Python:

```python theme={null}
import os, base64, json
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec

def stringify_transaction_details():
    transaction_details = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
  }

    return json.dumps(transaction_details, sort_keys=True, separators=(',', ':'))

def sign_transaction_details(details, user):
    with open(os.path.join("keys", user + ".private.pem"), "rb") as private_key_in:
        ec_private_key = serialization.load_pem_private_key(private_key_in.read(),
                                                            password=None,
                                                            backend=default_backend())
        signed_payload = ec_private_key.sign(str.encode(details), ec.ECDSA(hashes.SHA256()))
    b64_signed_payload = base64.b64encode(signed_payload).decode('UTF-8')
    return b64_signed_payload

def create_transaction_payload(details, signature):
    payload = {
            "request": json.loads(details),
            "signature": signature  # this is signature of the json i.e. transaction_details
        }
    }
    return json.dumps(payload, sort_keys=True, separators=(',', ':'))

if __name__ == "__main__":
    stringified_details = stringify_transaction_details()
    user_signature = sign_transaction_details(stringified_details, "api-maker@zodia.io")
    transaction_payload = create_transaction_payload(stringified_details, user_signature)

    print(transaction_payload)
    

```

You will obtain the payload below (**prettified** for the documentation) to be submitted to the API:

```json theme={null}
{
  "request": {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
  },
  "signature": "MEQCIHuLPOFmbnjWnJ0l6QpYRLMh/6LTwIV6LNlGXRiChProAiBjDQCsvbsGxb6pw9Il/m8zIFmZ+Wh3QFwBmIZJCOk8kA=="
}

```

Note: Please make sure you submit the same ordered request payload in the request body as well.
