# Build a Custom Co-Signer

Use an API User and webhooks to build a custom Co-Signer to perform automated
validations on Fordefi transactions.

In Fordefi, an API User's function is not limited to initiating transactions,
like human users. They can also be part of a transaction rule approval quorum in
your policies and act as a custom Co-Signer — performing automated verification
tasks such as making sure that the recipient of a swap is not a malicious
address.

## Before you start

To run this setup you will need to:

- Create an API User with `Trader` role and save its access tokens.
[Learn more](https://docs.fordefi.com/developers/getting-started/create-an-api-user).
The example uses an API User named `Validator Bot`, which will serve as our
custom Co-Signer.
- Set up a modified webhook server that will receive events from Fordefi.
[Learn more](https://docs.fordefi.com/developers/webhooks).
  - This guide uses a
[modified server](https://github.com/FordefiHQ/api-examples/tree/main/python/tx-validation-via-api)
that is designed to analyze EVM transaction data from your Fordefi
organization and parse call data/EIP-712 messages to make sure the recipient
of a swap is always `msg.sender`.
  - When providing your server callback URL to Fordefi, make sure you select
`Transactions V2`:


## Secure your Co-Signer server

Since the Co-Signer has the authority to approve or abort transactions, it's
critical to lock down the webhook endpoint that it exposes.

**Verify webhook signatures.** Every webhook that Fordefi sends includes a
signature header. You should verify this signature against Fordefi's public key
to confirm that the payload genuinely originated from Fordefi and that it hasn't
been tampered with. See the
[webhook validation documentation](https://docs.fordefi.com/developers/webhooks#validate-a-webhook)
for the public key and implementation details.

**Whitelist Fordefi's IP.** Restrict inbound traffic to your Co-Signer server by
whitelisting Fordefi's NAT address:


```
54.243.103.88
```

This ensures that only Fordefi's infrastructure can reach your webhook endpoint.
Any requests originating from other IPs can be dropped at the firewall or load
balancer level before they ever hit your application.

Combining both measures — signature verification at the application layer and IP
whitelisting at the network layer — gives you defense in depth against spoofed
or unauthorized webhook calls.

## Workflow

1. Create a policy with a single-set approval quorum including `Validator Bot`
as your custom Co-Signer:

This quorum implements the following logic: The Co-Signer **only** approves
EVM transactions that pass your custom validation checks. If validation
fails, it automatically aborts the transaction using the
`/transactions/{tx_id}/abort` endpoint documented
[here](https://docs.fordefi.com/api/latest/openapi/transactions/abort_transaction_api_v1_transactions__id__abort_post).
**Note**: More approver sets could be added, potentially adding human
approvers to the quorum, but in the example here, the Co-Signer is designed
to keep things as automated as possible.
2. Now, build the rest of the policy:

The Co-Signer must be able to scan every EVM transaction that is broadcast,
so build the policy rule using `Transaction type=Any`, `Recipient=Any` and
`Origin` to be a Vault group containing all your EVM vaults.
([Learn more](https://docs.fordefi.com/user-guide/vaults/handle-vault-groups)
about setting up Vault groups.) The policy must also be ranked at the top of
your policy rules, to ensure all EVM transactions will be evaluated.
*Fordefi's backend assumes that the initiator of the transaction always
provides tacit approval, so it's very important that the Co-Signer API User
is never used to initiate transactions. This is why the example does not use
`Any` initiator in the policy.*
3. Create EVM transactions and monitor your server and policy matching. If all
works well, any transaction that passes validation will be co-signed
automatically. Transactions that fail validation, however, will be
automatically aborted by the Co-Signer before they can be signed by the API
Signer or its human initiator.