> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-api/api-reference/transfer.md).

# Transfer

## Transfer tokens between shielded balances

> Relays a shielded-to-shielded transfer to a recipient. \`recipientAddress\` accepts either\
> the recipient's \`recipientInfo\` (from \`GET /recipient-info\`) or a plain public address\
> (Ethereum address on EVM/Tron chains, Solana address on Solana).\
> \
> \*\*EVM / Tron\*\*: \`feeToken\` is required in the request body.\
> \
> \*\*Solana\*\*: \`feeToken\` is not used — the server always uses \`tokenAddresses\[0]\` as the\
> fee token regardless of what is passed.\
> \
> The relay fee is computed automatically. \`feeAmount\` is only needed to lock in an exact\
> amount already returned by \`GET /get-fee\`.\
> \
> Authorized by a normal mode session (secp256k1 request signature, bound to\
> \`"POST /transfer"\`) or an EIP-712 mode session with a per-transaction EIP-712 typed-data\
> signature (primary type \`Transfer\`) on EVM/Tron, or an ed25519 plain-text signature on\
> Solana.<br>

```json
{"openapi":"3.0.3","info":{"title":"Hinkal API","version":"1.0.0"},"tags":[{"name":"Transfer"}],"servers":[{"url":"https://api.hinkal.io","description":"Production"}],"paths":{"/transfer":{"post":{"operationId":"transfer","summary":"Transfer tokens between shielded balances","description":"Relays a shielded-to-shielded transfer to a recipient. `recipientAddress` accepts either\nthe recipient's `recipientInfo` (from `GET /recipient-info`) or a plain public address\n(Ethereum address on EVM/Tron chains, Solana address on Solana).\n\n**EVM / Tron**: `feeToken` is required in the request body.\n\n**Solana**: `feeToken` is not used — the server always uses `tokenAddresses[0]` as the\nfee token regardless of what is passed.\n\nThe relay fee is computed automatically. `feeAmount` is only needed to lock in an exact\namount already returned by `GET /get-fee`.\n\nAuthorized by a normal mode session (secp256k1 request signature, bound to\n`\"POST /transfer\"`) or an EIP-712 mode session with a per-transaction EIP-712 typed-data\nsignature (primary type `Transfer`) on EVM/Tron, or an ed25519 plain-text signature on\nSolana.\n","tags":["Transfer"],"parameters":[{"$ref":"#/components/parameters/XHinkalRequestSignatureNormalMode"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid"},"nonce":{"type":"string","format":"uuid"},"signature":{"type":"string","description":"EIP-712 or ed25519 signature (EIP-712 mode only)"},"chainId":{"type":"integer"},"tokenAddresses":{"type":"array","items":{"type":"string"}},"amounts":{"type":"array","items":{"type":"string"}},"recipientAddress":{"type":"string","description":"Recipient's recipientInfo from GET /recipient-info, or a plain public\naddress (Ethereum on EVM/Tron, Solana on Solana).\n"},"feeToken":{"type":"string","description":"Token used to pay the relay fee. Required for EVM/Tron.\nOn Solana, always set to tokenAddresses[0] by the server — any value passed is ignored.\n"},"feeAmount":{"type":"string","description":"Optional — omit it and the server computes the fee automatically. Pass it\nonly to lock in a fee amount already quoted from GET /get-fee.\n"}},"required":["sessionId","nonce","chainId","tokenAddresses","amounts","recipientAddress"]}}}},"responses":{"200":{"description":"Relayed transaction hash","headers":{},"content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"txHash":{"type":"string"},"nonce":{"type":"string","description":"Echoed per-request `nonce` from the request, added before signing."}},"required":["success","txHash","nonce"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/NonceConflict"},"500":{"$ref":"#/components/responses/ServerError"}}}}},"components":{"parameters":{"XHinkalRequestSignatureNormalMode":{"name":"x-hinkal-request-signature","in":"header","required":false,"schema":{"type":"string"},"description":"Required for **normal mode** sessions: hex-encoded compact secp256k1 signature `secp256k1_sign(SHA256(binding + \"\\n\" + JSON.stringify(body)))`, where `binding` is `\"POST <routePath>\"` for this endpoint. Omit for **EIP-712 mode** sessions — include `signature` in the request body instead. See [Authentication](/enclave-api/authentication) for the full signing scheme."}},"responses":{"BadRequest":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"Unauthorized":{"description":"Invalid signature or reused nonce","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"NonceConflict":{"description":"Request `nonce` already consumed. Each `nonce` is single-use; generate a fresh UUID for every request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"ServerError":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}}},"schemas":{"FailedResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"string"}},"required":["success","error"]}}}}
```
