> For the complete documentation index, see [llms.txt](https://docs.afx.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.afx.xyz/api-reference/exchange/builder-code.md).

# Builder Code

Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.

**Integration flow:**

1. The Builder master wallet calls `registerBuilder` once.
2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.
3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.
4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.

**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).

Use the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.

## Register Builder

> Register the Builder master wallet once. Submit \`action.type=registerBuilder\` to \`POST /api/v1/exchange\`.\
> \
> \*\*Signer:\*\* Builder master wallet · \*\*EIP-712 primary type:\*\* \`RegisterBuilder\`\
> \
> \*\*Runnable examples:\*\* \[Python register Builder]\(<https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/register\\_builder.py>) · \[JavaScript register Builder]\(<https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/register-builder.ts)\\>
> \
> \*\*Raw signing.\*\* EIP-712 is a wallet typed-data signature, not a signature of the JSON request string. Sign this exact typed-data payload with the Builder master wallet. Use \`chainId\` \`421614\` for Testnet or \`42161\` for Mainnet; when \`expiryAfter\` is omitted in the request, sign it as \`0\`.\
> \
> \`\`\`json\
> {\
> &#x20; "types": {\
> &#x20;   "EIP712Domain": \[\
> &#x20;     { "name": "name", "type": "string" },\
> &#x20;     { "name": "version", "type": "string" },\
> &#x20;     { "name": "chainId", "type": "uint256" },\
> &#x20;     { "name": "verifyingContract", "type": "address" }\
> &#x20;   ],\
> &#x20;   "RegisterBuilder": \[\
> &#x20;     { "name": "dexChain", "type": "string" },\
> &#x20;     { "name": "name", "type": "string" },\
> &#x20;     { "name": "nonce", "type": "uint64" },\
> &#x20;     { "name": "expiryAfter", "type": "uint64" }\
> &#x20;   ]\
> &#x20; },\
> &#x20; "primaryType": "RegisterBuilder",\
> &#x20; "domain": {\
> &#x20;   "name": "SignTransaction",\
> &#x20;   "version": "1",\
> &#x20;   "chainId": 421614,\
> &#x20;   "verifyingContract": "0x0100000000000000000000000000000000000001"\
> &#x20; },\
> &#x20; "message": {\
> &#x20;   "dexChain": "Testnet",\
> &#x20;   "name": "example-builder",\
> &#x20;   "nonce": 1763023626904,\
> &#x20;   "expiryAfter": 1763023926904\
> &#x20; }\
> }\
> \`\`\`<br>

````json
{"openapi":"3.0.3","info":{"title":"AFX DEX Exchange API","version":"1.0.0"},"tags":[{"name":"Builder Code","description":"Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.\n\n**Integration flow:**\n1. The Builder master wallet calls `registerBuilder` once.\n2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.\n3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.\n4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.\n\n**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).\n\nUse the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.\n"}],"servers":[{"url":"https://api.afx.xyz","description":"Mainnet"},{"url":"https://api-testnet.afx.xyz","description":"Testnet"}],"paths":{"/exchange/registerBuilder":{"post":{"operationId":"registerBuilder","summary":"Register Builder","tags":["Builder Code"],"description":"Register the Builder master wallet once. Submit `action.type=registerBuilder` to `POST /api/v1/exchange`.\n\n**Signer:** Builder master wallet · **EIP-712 primary type:** `RegisterBuilder`\n\n**Runnable examples:** [Python register Builder](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/register_builder.py) · [JavaScript register Builder](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/register-builder.ts)\n\n**Raw signing.** EIP-712 is a wallet typed-data signature, not a signature of the JSON request string. Sign this exact typed-data payload with the Builder master wallet. Use `chainId` `421614` for Testnet or `42161` for Mainnet; when `expiryAfter` is omitted in the request, sign it as `0`.\n\n```json\n{\n  \"types\": {\n    \"EIP712Domain\": [\n      { \"name\": \"name\", \"type\": \"string\" },\n      { \"name\": \"version\", \"type\": \"string\" },\n      { \"name\": \"chainId\", \"type\": \"uint256\" },\n      { \"name\": \"verifyingContract\", \"type\": \"address\" }\n    ],\n    \"RegisterBuilder\": [\n      { \"name\": \"dexChain\", \"type\": \"string\" },\n      { \"name\": \"name\", \"type\": \"string\" },\n      { \"name\": \"nonce\", \"type\": \"uint64\" },\n      { \"name\": \"expiryAfter\", \"type\": \"uint64\" }\n    ]\n  },\n  \"primaryType\": \"RegisterBuilder\",\n  \"domain\": {\n    \"name\": \"SignTransaction\",\n    \"version\": \"1\",\n    \"chainId\": 421614,\n    \"verifyingContract\": \"0x0100000000000000000000000000000000000001\"\n  },\n  \"message\": {\n    \"dexChain\": \"Testnet\",\n    \"name\": \"example-builder\",\n    \"nonce\": 1763023626904,\n    \"expiryAfter\": 1763023926904\n  }\n}\n```\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterBuilderRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ExchangeOk"}}}}},"components":{"schemas":{"RegisterBuilderRequest":{"type":"object","required":["action","signature","nonce"],"properties":{"action":{"type":"object","required":["type","name","dexChain"],"properties":{"type":{"type":"string","enum":["registerBuilder"]},"name":{"type":"string","minLength":1},"dexChain":{"type":"string","enum":["Mainnet","Testnet"]}}},"signature":{"$ref":"#/components/schemas/Signature"},"nonce":{"type":"integer","format":"int64"},"expiryAfter":{"type":"integer","format":"int64","nullable":true,"description":"Sign `0` when omitted or null."}}},"Signature":{"type":"object","required":["r","s","v"],"properties":{"r":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"s":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"v":{"type":"integer","description":"27 or 28"}}},"ExchangeResponse":{"type":"object","properties":{"code":{"type":"integer","description":"`0` = success. See Error Codes section for non-zero values."},"message":{"type":"string"},"data":{"type":"object","nullable":true,"properties":{"txHash":{"type":"string"},"txCode":{"type":"integer"},"txMsg":{"type":"string"}}}}}},"responses":{"ExchangeOk":{"description":"Transaction submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeResponse"}}}}}}}
````

## Authorize Builder Agent

> Submit \`action.type=approveAgentToBuilder\` to \`POST /api/v1/exchange\`. The Trader master wallet authorizes the \*\*Builder agent address\*\*, not the Trader's own agent. \`maxFeeRate\` is a positive decimal string and must not exceed the environment-configured Builder fee cap.\
> \
> \*\*Signer:\*\* Trader master wallet · \*\*EIP-712 primary type:\*\* \`ApproveAgentToBuilder\`\
> \
> \*\*Runnable examples:\*\* \[Python full lifecycle]\(<https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder\\_lifecycle.py>) · \[JavaScript approve Builder agent]\(<https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/approve-agent-to-builder.ts)\\>
> \
> \*\*Raw signing.\*\* Sign the following EIP-712 typed-data payload with the Trader master wallet. \`agentAddress\` is the Builder's agent address, \`builderAddress\` is the Builder's master address, and \`expiryAfter\` must be signed as \`0\` when omitted.\
> \
> \`\`\`json\
> {\
> &#x20; "types": {\
> &#x20;   "ApproveAgentToBuilder": \[\
> &#x20;     { "name": "dexChain", "type": "string" },\
> &#x20;     { "name": "agentAddress", "type": "address" },\
> &#x20;     { "name": "builderAddress", "type": "address" },\
> &#x20;     { "name": "maxFeeRate", "type": "string" },\
> &#x20;     { "name": "validitySeconds", "type": "uint64" },\
> &#x20;     { "name": "nonce", "type": "uint64" },\
> &#x20;     { "name": "expiryAfter", "type": "uint64" }\
> &#x20;   ]\
> &#x20; },\
> &#x20; "primaryType": "ApproveAgentToBuilder",\
> &#x20; "domain": { "name": "SignTransaction", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },\
> &#x20; "message": {\
> &#x20;   "dexChain": "Testnet",\
> &#x20;   "agentAddress": "0x\<builder-agent-address>",\
> &#x20;   "builderAddress": "0x\<builder-master-address>",\
> &#x20;   "maxFeeRate": "0.0002",\
> &#x20;   "validitySeconds": 3600,\
> &#x20;   "nonce": 1763023626904,\
> &#x20;   "expiryAfter": 1763023926904\
> &#x20; }\
> }\
> \`\`\`<br>

````json
{"openapi":"3.0.3","info":{"title":"AFX DEX Exchange API","version":"1.0.0"},"tags":[{"name":"Builder Code","description":"Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.\n\n**Integration flow:**\n1. The Builder master wallet calls `registerBuilder` once.\n2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.\n3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.\n4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.\n\n**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).\n\nUse the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.\n"}],"servers":[{"url":"https://api.afx.xyz","description":"Mainnet"},{"url":"https://api-testnet.afx.xyz","description":"Testnet"}],"paths":{"/exchange/approveAgentToBuilder":{"post":{"operationId":"approveAgentToBuilder","summary":"Authorize Builder Agent","tags":["Builder Code"],"description":"Submit `action.type=approveAgentToBuilder` to `POST /api/v1/exchange`. The Trader master wallet authorizes the **Builder agent address**, not the Trader's own agent. `maxFeeRate` is a positive decimal string and must not exceed the environment-configured Builder fee cap.\n\n**Signer:** Trader master wallet · **EIP-712 primary type:** `ApproveAgentToBuilder`\n\n**Runnable examples:** [Python full lifecycle](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript approve Builder agent](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/approve-agent-to-builder.ts)\n\n**Raw signing.** Sign the following EIP-712 typed-data payload with the Trader master wallet. `agentAddress` is the Builder's agent address, `builderAddress` is the Builder's master address, and `expiryAfter` must be signed as `0` when omitted.\n\n```json\n{\n  \"types\": {\n    \"ApproveAgentToBuilder\": [\n      { \"name\": \"dexChain\", \"type\": \"string\" },\n      { \"name\": \"agentAddress\", \"type\": \"address\" },\n      { \"name\": \"builderAddress\", \"type\": \"address\" },\n      { \"name\": \"maxFeeRate\", \"type\": \"string\" },\n      { \"name\": \"validitySeconds\", \"type\": \"uint64\" },\n      { \"name\": \"nonce\", \"type\": \"uint64\" },\n      { \"name\": \"expiryAfter\", \"type\": \"uint64\" }\n    ]\n  },\n  \"primaryType\": \"ApproveAgentToBuilder\",\n  \"domain\": { \"name\": \"SignTransaction\", \"version\": \"1\", \"chainId\": 421614, \"verifyingContract\": \"0x0100000000000000000000000000000000000001\" },\n  \"message\": {\n    \"dexChain\": \"Testnet\",\n    \"agentAddress\": \"0x<builder-agent-address>\",\n    \"builderAddress\": \"0x<builder-master-address>\",\n    \"maxFeeRate\": \"0.0002\",\n    \"validitySeconds\": 3600,\n    \"nonce\": 1763023626904,\n    \"expiryAfter\": 1763023926904\n  }\n}\n```\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveAgentToBuilderRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ExchangeOk"}}}}},"components":{"schemas":{"ApproveAgentToBuilderRequest":{"type":"object","required":["action","signature","nonce"],"properties":{"action":{"type":"object","required":["type","agentAddress","builderAddress","maxFeeRate","validitySeconds","dexChain"],"properties":{"type":{"type":"string","enum":["approveAgentToBuilder"]},"agentAddress":{"type":"string","description":"Builder agent address"},"builderAddress":{"type":"string","description":"Builder master wallet address"},"maxFeeRate":{"type":"string","description":"Positive decimal string; subject to the configured fee cap"},"validitySeconds":{"type":"integer","format":"int64","minimum":0},"dexChain":{"type":"string","enum":["Mainnet","Testnet"]}}},"signature":{"$ref":"#/components/schemas/Signature"},"nonce":{"type":"integer","format":"int64"},"expiryAfter":{"type":"integer","format":"int64","nullable":true,"description":"Sign `0` when omitted or null."}}},"Signature":{"type":"object","required":["r","s","v"],"properties":{"r":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"s":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"v":{"type":"integer","description":"27 or 28"}}},"ExchangeResponse":{"type":"object","properties":{"code":{"type":"integer","description":"`0` = success. See Error Codes section for non-zero values."},"message":{"type":"string"},"data":{"type":"object","nullable":true,"properties":{"txHash":{"type":"string"},"txCode":{"type":"integer"},"txMsg":{"type":"string"}}}}}},"responses":{"ExchangeOk":{"description":"Transaction submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeResponse"}}}}}}}
````

## Revoke Builder Agent Authorization

> Submit \`action.type=revokeAgentToBuilder\` to \`POST /api/v1/exchange\`. The authorization is resolved from the Trader master signature; no Builder or agent address is included in the action.\
> \
> \*\*Signer:\*\* Trader master wallet · \*\*EIP-712 primary type:\*\* \`RevokeAgentToBuilder\`\
> \
> \*\*Runnable examples:\*\* \[Python revoke Builder authorization]\(<https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/revoke\\_agent\\_to\\_builder.py>) · \[JavaScript revoke Builder authorization]\(<https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/revoke-agent-to-builder.ts)\\>
> \
> \*\*Raw signing.\*\* Sign this EIP-712 typed-data payload with the Trader master wallet. The server resolves the Builder and agent from the Trader's active authorization; do not add those addresses to the action.\
> \
> \`\`\`json\
> {\
> &#x20; "types": {\
> &#x20;   "RevokeAgentToBuilder": \[\
> &#x20;     { "name": "dexChain", "type": "string" },\
> &#x20;     { "name": "nonce", "type": "uint64" },\
> &#x20;     { "name": "expiryAfter", "type": "uint64" }\
> &#x20;   ]\
> &#x20; },\
> &#x20; "primaryType": "RevokeAgentToBuilder",\
> &#x20; "domain": { "name": "SignTransaction", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },\
> &#x20; "message": {\
> &#x20;   "dexChain": "Testnet",\
> &#x20;   "nonce": 1763023626904,\
> &#x20;   "expiryAfter": 1763023926904\
> &#x20; }\
> }\
> \`\`\`<br>

````json
{"openapi":"3.0.3","info":{"title":"AFX DEX Exchange API","version":"1.0.0"},"tags":[{"name":"Builder Code","description":"Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.\n\n**Integration flow:**\n1. The Builder master wallet calls `registerBuilder` once.\n2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.\n3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.\n4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.\n\n**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).\n\nUse the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.\n"}],"servers":[{"url":"https://api.afx.xyz","description":"Mainnet"},{"url":"https://api-testnet.afx.xyz","description":"Testnet"}],"paths":{"/exchange/revokeAgentToBuilder":{"post":{"operationId":"revokeAgentToBuilder","summary":"Revoke Builder Agent Authorization","tags":["Builder Code"],"description":"Submit `action.type=revokeAgentToBuilder` to `POST /api/v1/exchange`. The authorization is resolved from the Trader master signature; no Builder or agent address is included in the action.\n\n**Signer:** Trader master wallet · **EIP-712 primary type:** `RevokeAgentToBuilder`\n\n**Runnable examples:** [Python revoke Builder authorization](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/revoke_agent_to_builder.py) · [JavaScript revoke Builder authorization](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/revoke-agent-to-builder.ts)\n\n**Raw signing.** Sign this EIP-712 typed-data payload with the Trader master wallet. The server resolves the Builder and agent from the Trader's active authorization; do not add those addresses to the action.\n\n```json\n{\n  \"types\": {\n    \"RevokeAgentToBuilder\": [\n      { \"name\": \"dexChain\", \"type\": \"string\" },\n      { \"name\": \"nonce\", \"type\": \"uint64\" },\n      { \"name\": \"expiryAfter\", \"type\": \"uint64\" }\n    ]\n  },\n  \"primaryType\": \"RevokeAgentToBuilder\",\n  \"domain\": { \"name\": \"SignTransaction\", \"version\": \"1\", \"chainId\": 421614, \"verifyingContract\": \"0x0100000000000000000000000000000000000001\" },\n  \"message\": {\n    \"dexChain\": \"Testnet\",\n    \"nonce\": 1763023626904,\n    \"expiryAfter\": 1763023926904\n  }\n}\n```\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeAgentToBuilderRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ExchangeOk"}}}}},"components":{"schemas":{"RevokeAgentToBuilderRequest":{"type":"object","required":["action","signature","nonce"],"properties":{"action":{"type":"object","required":["type","dexChain"],"properties":{"type":{"type":"string","enum":["revokeAgentToBuilder"]},"dexChain":{"type":"string","enum":["Mainnet","Testnet"]}}},"signature":{"$ref":"#/components/schemas/Signature"},"nonce":{"type":"integer","format":"int64"},"expiryAfter":{"type":"integer","format":"int64","nullable":true,"description":"Sign `0` when omitted or null."}}},"Signature":{"type":"object","required":["r","s","v"],"properties":{"r":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"s":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"v":{"type":"integer","description":"27 or 28"}}},"ExchangeResponse":{"type":"object","properties":{"code":{"type":"integer","description":"`0` = success. See Error Codes section for non-zero values."},"message":{"type":"string"},"data":{"type":"object","nullable":true,"properties":{"txHash":{"type":"string"},"txCode":{"type":"integer"},"txMsg":{"type":"string"}}}}}},"responses":{"ExchangeOk":{"description":"Transaction submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeResponse"}}}}}}}
````

## Place Builder Order

> Submit \`action.type=placeBuilderOrder\` to \`POST /api/v1/exchange\` after the Trader authorizes the Builder agent. \`builderFeeRate\` must be a non-negative decimal string and must not exceed the Trader authorization's \`maxFeeRate\`.\
> \
> \*\*Signer:\*\* Builder agent · \*\*Protobuf:\*\* \`MsgPlaceBuilderOrder\`\
> \
> \*\*Runnable examples:\*\* \[Python full lifecycle]\(<https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder\\_lifecycle.py>) · \[JavaScript place Builder order]\(<https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/place-builder-order.ts)\\>
> \
> \*\*Raw signing.\*\* Serialize this message using proto3, then calculate \`connectionId = keccak256(proto\_bytes + bytes(vaultAddress) + little\_endian\_uint64(nonce) + little\_endian\_uint64(expiryAfter))\`. Use empty bytes for an omitted \`vaultAddress\` and \`0\` for an omitted \`expiryAfter\`. The Builder agent then signs this EIP-712 typed-data payload. Use \`source\` \`"b"\` on Testnet or \`"a"\` on Mainnet.\
> \
> \`\`\`json\
> {\
> &#x20; "types": {\
> &#x20;   "Agent": \[\
> &#x20;     { "name": "source", "type": "string" },\
> &#x20;     { "name": "connectionId", "type": "bytes32" }\
> &#x20;   ]\
> &#x20; },\
> &#x20; "primaryType": "Agent",\
> &#x20; "domain": { "name": "Exchange", "version": "1", "chainId": 421614, "verifyingContract": "0x0100000000000000000000000000000000000001" },\
> &#x20; "message": { "source": "b", "connectionId": "0x\<keccak256-result>" }\
> }\
> \`\`\`\
> \
> \`\`\`protobuf\
> message MsgPlaceBuilderOrder {\
> &#x20; int64 cl\_ord\_id = 1;\
> &#x20; int64 symbol\_code = 2;\
> &#x20; string ord\_px = 3;\
> &#x20; string ord\_qty = 4;\
> &#x20; string trigger\_px = 5;\
> &#x20; OrdType ord\_type = 6;\
> &#x20; OrdSide ord\_side = 7;\
> &#x20; OrdTIF time\_in\_force = 8;\
> &#x20; ReduceOnlyOption reduce\_only\_option = 9;\
> &#x20; int64 parent\_ord\_id = 10;\
> &#x20; ConditionalOrdTriggerType tpsl\_trigger\_type = 11;\
> &#x20; string slippage\_pct = 12;\
> &#x20; string builder\_addr = 13;\
> &#x20; string builder\_fee\_rate = 14;\
> }\
> \`\`\`<br>

````json
{"openapi":"3.0.3","info":{"title":"AFX DEX Exchange API","version":"1.0.0"},"tags":[{"name":"Builder Code","description":"Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.\n\n**Integration flow:**\n1. The Builder master wallet calls `registerBuilder` once.\n2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.\n3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.\n4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.\n\n**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).\n\nUse the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.\n"}],"servers":[{"url":"https://api.afx.xyz","description":"Mainnet"},{"url":"https://api-testnet.afx.xyz","description":"Testnet"}],"paths":{"/exchange/placeBuilderOrder":{"post":{"operationId":"placeBuilderOrder","summary":"Place Builder Order","tags":["Builder Code"],"description":"Submit `action.type=placeBuilderOrder` to `POST /api/v1/exchange` after the Trader authorizes the Builder agent. `builderFeeRate` must be a non-negative decimal string and must not exceed the Trader authorization's `maxFeeRate`.\n\n**Signer:** Builder agent · **Protobuf:** `MsgPlaceBuilderOrder`\n\n**Runnable examples:** [Python full lifecycle](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript place Builder order](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/place-builder-order.ts)\n\n**Raw signing.** Serialize this message using proto3, then calculate `connectionId = keccak256(proto_bytes + bytes(vaultAddress) + little_endian_uint64(nonce) + little_endian_uint64(expiryAfter))`. Use empty bytes for an omitted `vaultAddress` and `0` for an omitted `expiryAfter`. The Builder agent then signs this EIP-712 typed-data payload. Use `source` `\"b\"` on Testnet or `\"a\"` on Mainnet.\n\n```json\n{\n  \"types\": {\n    \"Agent\": [\n      { \"name\": \"source\", \"type\": \"string\" },\n      { \"name\": \"connectionId\", \"type\": \"bytes32\" }\n    ]\n  },\n  \"primaryType\": \"Agent\",\n  \"domain\": { \"name\": \"Exchange\", \"version\": \"1\", \"chainId\": 421614, \"verifyingContract\": \"0x0100000000000000000000000000000000000001\" },\n  \"message\": { \"source\": \"b\", \"connectionId\": \"0x<keccak256-result>\" }\n}\n```\n\n```protobuf\nmessage MsgPlaceBuilderOrder {\n  int64 cl_ord_id = 1;\n  int64 symbol_code = 2;\n  string ord_px = 3;\n  string ord_qty = 4;\n  string trigger_px = 5;\n  OrdType ord_type = 6;\n  OrdSide ord_side = 7;\n  OrdTIF time_in_force = 8;\n  ReduceOnlyOption reduce_only_option = 9;\n  int64 parent_ord_id = 10;\n  ConditionalOrdTriggerType tpsl_trigger_type = 11;\n  string slippage_pct = 12;\n  string builder_addr = 13;\n  string builder_fee_rate = 14;\n}\n```\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceBuilderOrderRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ExchangeOk"}}}}},"components":{"schemas":{"PlaceBuilderOrderRequest":{"type":"object","required":["action","signature","nonce"],"properties":{"action":{"type":"object","required":["type","order","builder","builderFeeRate"],"properties":{"type":{"type":"string","enum":["placeBuilderOrder"]},"order":{"$ref":"#/components/schemas/BuilderOrder"},"builder":{"type":"string","description":"Builder master wallet address"},"builderFeeRate":{"type":"string","description":"Non-negative decimal string; must not exceed the Trader authorization"}}},"signature":{"$ref":"#/components/schemas/Signature"},"nonce":{"type":"integer","format":"int64"},"expiryAfter":{"type":"integer","format":"int64","nullable":true,"description":"Use `0` in the L1 connection ID when omitted or null."},"vaultAddress":{"type":"string","nullable":true}}},"BuilderOrder":{"type":"object","required":["symbolCode","ordPx","ordQty","ordType","ordSide","timeInForce"],"properties":{"symbolCode":{"type":"integer","format":"int64"},"ordPx":{"type":"string","description":"Limit price; use `0` for a market order"},"ordQty":{"type":"string"},"ordType":{"type":"string","enum":["LIMIT","MARKET","STOP_LIMIT","STOP_MARKET","TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"]},"ordSide":{"type":"string","enum":["BUY","SELL","BUY_CLOSE_HEDGE","SELL_CLOSE_HEDGE"]},"timeInForce":{"type":"string","enum":["GTC","IOC","FOK","POST_ONLY"]},"clOrdId":{"type":"integer","format":"int64"},"parentOrdId":{"type":"integer","format":"int64"},"reduceOnly":{"type":"string","enum":["REDUCE_ONLY","TP_FROM_POSITION","SL_FROM_POSITION"],"description":"`reduceOnlyOption` is accepted as a compatibility alias."},"triggerPx":{"type":"string"},"tpslTriggerType":{"type":"string","enum":["LAST_PRICE","MARK_PRICE","INDEX_PRICE"]},"slippagePct":{"type":"string"}}},"Signature":{"type":"object","required":["r","s","v"],"properties":{"r":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"s":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"v":{"type":"integer","description":"27 or 28"}}},"ExchangeResponse":{"type":"object","properties":{"code":{"type":"integer","description":"`0` = success. See Error Codes section for non-zero values."},"message":{"type":"string"},"data":{"type":"object","nullable":true,"properties":{"txHash":{"type":"string"},"txCode":{"type":"integer"},"txMsg":{"type":"string"}}}}}},"responses":{"ExchangeOk":{"description":"Transaction submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeResponse"}}}}}}}
````

## Place Builder Bracket Order

> Submit 2 or 3 orders with \`action.type=placeBuilderBracketOrder\` to \`POST /api/v1/exchange\`. The first order is the main order; remaining orders must be TP (\`TP\_FROM\_POSITION\`) or SL (\`SL\_FROM\_POSITION\`).\
> \
> \*\*Signer:\*\* Builder agent · \*\*Protobuf:\*\* \`MsgPlaceBuilderBracketOrder\`\
> \
> \*\*Runnable examples:\*\* \[Python full lifecycle]\(<https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder\\_lifecycle.py>) · \[JavaScript full lifecycle]\(<https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts)\\>
> \
> \*\*Raw signing.\*\* Each child order is a \`MsgPlaceBuilderOrder\` with the \`builder\_addr = 13\` and \`builder\_fee\_rate = 14\` fields shown above. Serialize the wrapper below and use the same Builder-agent \`Agent\` EIP-712 signing process as \`placeBuilderOrder\`.\
> \
> \`\`\`protobuf\
> message MsgPlaceBuilderBracketOrder {\
> &#x20; MsgPlaceBuilderOrder main\_order = 1;\
> &#x20; MsgPlaceBuilderOrder take\_profit\_order = 2;\
> &#x20; MsgPlaceBuilderOrder stop\_loss\_order = 3;\
> }\
> \`\`\`<br>

````json
{"openapi":"3.0.3","info":{"title":"AFX DEX Exchange API","version":"1.0.0"},"tags":[{"name":"Builder Code","description":"Builder Code lets a registered Builder place orders for a Trader after the Trader explicitly authorizes that Builder's agent wallet. The Builder never receives the Trader's private key.\n\n**Integration flow:**\n1. The Builder master wallet calls `registerBuilder` once.\n2. Each Trader master wallet calls `approveAgentToBuilder` with the Builder agent address and fee cap.\n3. The Builder agent calls `placeBuilderOrder` or `placeBuilderBracketOrder` for that Trader.\n4. The Trader master wallet calls `revokeAgentToBuilder` to end the authorization.\n\n**Start here:** [Python full lifecycle example](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle example](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts).\n\nUse the SDKs unless you need a raw REST integration. The SDKs create protobuf bytes and EIP-712 signatures for you.\n"}],"servers":[{"url":"https://api.afx.xyz","description":"Mainnet"},{"url":"https://api-testnet.afx.xyz","description":"Testnet"}],"paths":{"/exchange/placeBuilderBracketOrder":{"post":{"operationId":"placeBuilderBracketOrder","summary":"Place Builder Bracket Order","tags":["Builder Code"],"description":"Submit 2 or 3 orders with `action.type=placeBuilderBracketOrder` to `POST /api/v1/exchange`. The first order is the main order; remaining orders must be TP (`TP_FROM_POSITION`) or SL (`SL_FROM_POSITION`).\n\n**Signer:** Builder agent · **Protobuf:** `MsgPlaceBuilderBracketOrder`\n\n**Runnable examples:** [Python full lifecycle](https://github.com/afx-dex/afx-python-sdk/blob/main/examples/exchange/builder_lifecycle.py) · [JavaScript full lifecycle](https://github.com/afx-dex/afx-js-sdk/blob/main/examples/exchange/builder-lifecycle.ts)\n\n**Raw signing.** Each child order is a `MsgPlaceBuilderOrder` with the `builder_addr = 13` and `builder_fee_rate = 14` fields shown above. Serialize the wrapper below and use the same Builder-agent `Agent` EIP-712 signing process as `placeBuilderOrder`.\n\n```protobuf\nmessage MsgPlaceBuilderBracketOrder {\n  MsgPlaceBuilderOrder main_order = 1;\n  MsgPlaceBuilderOrder take_profit_order = 2;\n  MsgPlaceBuilderOrder stop_loss_order = 3;\n}\n```\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceBuilderBracketOrderRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ExchangeOk"}}}}},"components":{"schemas":{"PlaceBuilderBracketOrderRequest":{"type":"object","required":["action","signature","nonce"],"properties":{"action":{"type":"object","required":["type","orders","builder","builderFeeRate"],"properties":{"type":{"type":"string","enum":["placeBuilderBracketOrder"]},"orders":{"type":"array","minItems":2,"maxItems":3,"description":"First item is the main order; later items are TP and/or SL orders.","items":{"$ref":"#/components/schemas/BuilderOrder"}},"builder":{"type":"string","description":"Builder master wallet address"},"builderFeeRate":{"type":"string","description":"Non-negative decimal string; must not exceed the Trader authorization"}}},"signature":{"$ref":"#/components/schemas/Signature"},"nonce":{"type":"integer","format":"int64"},"expiryAfter":{"type":"integer","format":"int64","nullable":true,"description":"Use `0` in the L1 connection ID when omitted or null."},"vaultAddress":{"type":"string","nullable":true}}},"BuilderOrder":{"type":"object","required":["symbolCode","ordPx","ordQty","ordType","ordSide","timeInForce"],"properties":{"symbolCode":{"type":"integer","format":"int64"},"ordPx":{"type":"string","description":"Limit price; use `0` for a market order"},"ordQty":{"type":"string"},"ordType":{"type":"string","enum":["LIMIT","MARKET","STOP_LIMIT","STOP_MARKET","TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"]},"ordSide":{"type":"string","enum":["BUY","SELL","BUY_CLOSE_HEDGE","SELL_CLOSE_HEDGE"]},"timeInForce":{"type":"string","enum":["GTC","IOC","FOK","POST_ONLY"]},"clOrdId":{"type":"integer","format":"int64"},"parentOrdId":{"type":"integer","format":"int64"},"reduceOnly":{"type":"string","enum":["REDUCE_ONLY","TP_FROM_POSITION","SL_FROM_POSITION"],"description":"`reduceOnlyOption` is accepted as a compatibility alias."},"triggerPx":{"type":"string"},"tpslTriggerType":{"type":"string","enum":["LAST_PRICE","MARK_PRICE","INDEX_PRICE"]},"slippagePct":{"type":"string"}}},"Signature":{"type":"object","required":["r","s","v"],"properties":{"r":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"s":{"type":"string","description":"32-byte hex, zero-padded to 64 chars"},"v":{"type":"integer","description":"27 or 28"}}},"ExchangeResponse":{"type":"object","properties":{"code":{"type":"integer","description":"`0` = success. See Error Codes section for non-zero values."},"message":{"type":"string"},"data":{"type":"object","nullable":true,"properties":{"txHash":{"type":"string"},"txCode":{"type":"integer"},"txMsg":{"type":"string"}}}}}},"responses":{"ExchangeOk":{"description":"Transaction submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeResponse"}}}}}}}
````


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.afx.xyz/api-reference/exchange/builder-code.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
