# Agentic API
Source: https://docs.brickken.com/api-reference/endpoint/agentic-methods-x402
x402-paid Agentic API for ERC-8004 workflows on Base and ERC-8226 RAMS mandates on Ethereum Sepolia.
## Overview
The Agentic API is the x402-paid surface for Brickken agentic methods. It covers ERC-8004 identity, reputation, and agent-owned ERC-20 operations on **Base**, plus ERC-8226 RAMS mandates on **Ethereum Sepolia**.
Every agentic operation is a two-step flow:
1. **Prepare** the unsigned transaction. Half of the operation charge is collected here.
2. **Send** the operation. The remaining x402 USDC charge is collected here.
You always sign the blockchain transaction yourself. There are two execution modes for the send step:
* **`client-signed` (default).** You sign the prepared transaction with your own private key and submit the signed payload; Brickken broadcasts it.
* **`client-broadcast`.** You sign and broadcast the transaction yourself, then confirm it with `txHash`.
Never send a private key to the Brickken API. Blockchain signing belongs in your client, the [Brickken CLI](/cli/introduction), or an MCP session you control.
## Base URLs
| Environment | Base URL |
| ----------- | ---------------------------------- |
| Sandbox | `https://api.sandbox.brickken.com` |
| Production | `https://api.brickken.com` |
## Networks
The Agentic API runs on Base, with Base Sepolia for tests. The x402 payment rail is **operation-aligned**: you pay on the same chain the operation runs on.
| Network | `chainId` (decimal) | Hex | Use |
| ---------------- | ------------------- | ---------- | --------------------------------------------- |
| Base mainnet | `8453` | `0x2105` | Production |
| Base Sepolia | `84532` | `0x14a34` | Testing |
| Ethereum Sepolia | `11155111` | `0xaa36a7` | RAMS mandates only; not ERC-8004 agent routes |
## Authentication Flow
For x402, omit `x-api-key`.
1. **Prepare.** Call a semantic facade such as `POST /x402/agent/register`, or `POST /prepare-transactions` with an eligible `method`. The response returns `txId`, `transactions`, and an `x402Requirements` quote, and may return a payment challenge for its half of the operation price.
2. **Send.** Call `POST /send-transactions`. The API responds `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the exact chain, asset, transfer method, amount, recipient, and timeout.
3. **Sign the x402 payment locally** with the payer's private key, and retry the send with `X-PAYMENT`.
4. Brickken verifies the payment and processes the operation. The settlement is returned in the `PAYMENT-RESPONSE` header.
For an agent facade, a `400` before a `txId` is request validation, not an insufficient x402 balance. x402 payment begins only when `send-transactions` returns `402 Payment Required`.
```http theme={null}
X-PAYMENT: BASE64_ENCODED_X402_PAYMENT_PAYLOAD
```
Always read the chain, asset, transfer method, amount, recipient, and timeout from `PAYMENT-REQUIRED`; do not hardcode them client-side. On Base Sepolia the payment rail uses **EIP-3009**, whose signed authorization carries the transfer, so no separate ERC-20 `approve` transaction is required. On Base mainnet, follow the advertised token's transfer method.
The payment is reserved when you pay and only **settled after the operation confirms on-chain**. If the operation reverts or its authorization expires before confirmation, the reservation is released.
## Base Sepolia Testing
Use `chainId: "84532"` (`eip155:84532`). The Base Sepolia x402 payment asset is **Circle USDC**:
```text theme={null}
0x036CbD53842c5426634e7929541eC2318f3dCF7e
```
It has 6 decimals and uses the **EIP-3009** transfer method (EIP-712 name `USDC`, version `2`, authorization window 300s). Fund the payer with the exact asset advertised by `PAYMENT-REQUIRED` before signing. The Base Sepolia ERC-8004 registries are:
* Identity: `0x8004A818BFB912233c491871b3d84c89A494BD9e`
* Reputation: `0x8004B663056A597Dffe9eCcC1965A193B7388713`
## Discovery
```http theme={null}
GET /.well-known/x402
GET /openapi.json
```
Production (`https://api.brickken.com`) is the public x402scan target. Sandbox exposes the same discovery routes for QA.
## Prepare and Send
The semantic `/x402/...` routes prepare unsigned transactions and do not submit transactions on-chain by themselves. Preparing is a paid call: it collects half of the operation price, unless you send a valid `x-api-key` instead.
### Preparing an operation
Pass `signerAddress` as the wallet that will sign the prepared transaction.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/x402/agent/register' \
--header 'Content-Type: application/json' \
--data '{
"chainId": "84532",
"signerAddress": "0x1111111111111111111111111111111111111111",
"name": "Research Agent",
"description": "Autonomous research agent",
"image": "https://example.com/agent.png",
"services": [
{
"name": "A2A",
"endpoint": "https://agent.example/.well-known/agent-card.json",
"version": "0.3.0"
}
],
"aiModelName": "Research Model",
"aiModelProvider": "OpenAI",
"x402Support": true,
"active": true
}'
```
`image` is required for `agentRegister` and must be a publicly reachable HTTPS logo URL. Do not use local paths or omit the field.
The prepare response returns a single `txId`, exactly one transaction `{ to, data, value }`, and `x402Requirements`. Submit those to `send-transactions` and complete the x402 payment; Brickken signs and broadcasts:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--header 'X-PAYMENT: BASE64_ENCODED_X402_PAYMENT_PAYLOAD' \
--data '{
"txId": "0xPreparedTransactionId",
"transactions": [
{ "to": "0xRegistry", "data": "0x...", "value": "0x0" }
]
}'
```
### Client-signed
Prepare with your own `signerAddress`, sign the returned transaction locally, then send the signed payload:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--header 'X-PAYMENT: BASE64_ENCODED_X402_PAYMENT_PAYLOAD' \
--data '{
"txId": "0xPreparedTransactionId",
"signedTransactions": ["0xSignedRawTransaction"]
}'
```
`send-transactions` x402 batches must contain only x402-eligible prepared transactions, and all transactions in the batch must be on the same chain.
### Polling
Poll status with `GET /get-transaction-status` by `txId` or operation hash. A response of `status: "pending"` means the operation was broadcast but not yet confirmed; do not pay or resubmit the same `txId` again. Brickken's reconciliation settles after confirmation or releases the payment on revert or authorization expiry.
## Endpoint Groups
Facade requests use the same body fields as the matching backend `method`, except `method` is optional and ignored because the path fixes it.
Register, maintain, and transfer ownership of ERC-8004 agent identities.
Give, revoke, and respond to ERC-8004 feedback.
Create and operate agent-owned ERC-20 tokens.
Delegate compliance-gated, scoped, capped authority to AI-agent wallets with ERC-8226.
Review execution-mode-aware prepare and send prices.
Advanced clients can also call `POST /prepare-transactions` directly and pass `method` explicitly. `newTokenizedAgent` remains a legacy alias for agent registration, but it is not published in x402scan discovery.
The ten RAMS methods (`ramsGrantMandate`, `ramsRevokeMandate`, `ramsExtendMandate`, `ramsSetOperator`, `ramsExecute`, `ramsSetExecutorAction`, `ramsFreezeAgent`, `ramsUnfreezeAgent`, `ramsGrantPrincipal`, and `ramsRevokePrincipal`) are also eligible through `/prepare-transactions`. Their semantic facades live under `/x402/rams/*`.
RAMS facades are client-signed; see [RAMS Mandates](/api-reference/endpoint/rams-overview).
## Common Fields
| Field | Type | Required | Description |
| --------------- | ---------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chainId` | string | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `method` | string | Yes for `/prepare-transactions`; no for `/x402/...` facades | One of the eligible method names. Facades derive it from the path. |
| `executionMode` | string | No | `client-signed` (default: you sign, Brickken broadcasts) or `client-broadcast` (you sign and broadcast, then confirm with `txHash`). Either way the operation price is split evenly between prepare and send. See [Pricing](/api-reference/endpoint/agentic-pricing). |
| `signerAddress` | string | Yes | Wallet that signs the prepared transaction. |
| `gasLimit` | string or number | No | Optional explicit gas limit (client-signed). |
| `nonce` | number | No | Optional explicit nonce when managing nonces manually (client-signed). |
## Response Shape
The prepare response includes `txId`, `transactions`, and optional `info`. For `agentRegister`, save `info.agentUuid` for later `set-uri`, `set-metadata`, and `transfer-ownership` calls.
x402 payments and on-chain transactions are non-refundable. Confirm chain, signer/recipient, token address, and expected USDC price before paying. See [Pricing](/api-reference/endpoint/agentic-pricing) for the published mainnet table.
# Pricing
Source: https://docs.brickken.com/api-reference/endpoint/agentic-pricing
x402 pricing for Agentic API prepare and send operations.
**Every operation is priced once and charged twice.** Half is collected when you prepare it, half when you send it, in both `client-signed` and `client-broadcast` mode. Calling `POST /prepare-transactions` directly is therefore **a paid call**.
A valid `x-api-key` is accepted instead of paying, on both steps.
Prices are in USDC on **Base mainnet**, and the figures below are the **total** for the operation.
| Method | Total |
| ----------------------------------------------- | -----: |
| `agentRegister` | `0.98` |
| `agentSetURI` | `0.48` |
| `agentSetMetadata` | `0.48` |
| `agentSetWallet` | `0.98` |
| `agentTransferOwnership` | `0.98` |
| `agentGiveFeedback` | `0.24` |
| `agentRevokeFeedback` | `0.24` |
| `agentAppendFeedbackResponse` | `0.48` |
| `agentCreateToken` | `9.98` |
| `agentMintToken` | `0.10` |
| `agentBurnToken` | `0.04` |
| `agentTransferToken` | `0.04` |
| `agentTransferFromToken` | `0.04` |
| `agentApproveToken` | `0.02` |
| `newTokenizedAgent` (legacy registration alias) | `2.98` |
| `ramsGrantMandate` | `0.98` |
| `ramsRevokeMandate` | `0.48` |
| `ramsExtendMandate` | `0.48` |
| `ramsSetOperator` | `0.48` |
| `ramsExecute` | `0.24` |
| `ramsSetExecutorAction` | `0.48` |
| `ramsFreezeAgent` | `0.48` |
| `ramsUnfreezeAgent` | `0.48` |
| `ramsGrantPrincipal` | `0.98` |
| `ramsRevokePrincipal` | `0.48` |
## Agent getter pricing
`GET /get-agents`, `GET /get-agent-info`, and `GET /get-agent-transactions` cost `0.000001 USDC` per x402 call. They are free of x402 payment when called with a valid API key.
## How RAMS is priced
**RAMS runs on Ethereum Sepolia (`11155111`) at launch**, on both sandbox and production. All `/x402/rams/*` prepare facades default to `chainId: "11155111"`.
RAMS writes are priced the same way as the rest: the total splits evenly across prepare and send, so `ramsGrantMandate` costs `0.49` at prepare and `0.49` at send.
Four of the ten writes — `grant-mandate`, `revoke-mandate`, `extend-mandate`, and `set-operator` — are authorized by a principal EIP-712 signature, so the wallet that sends the transaction does not have to be the principal. The other six check `msg.sender` against an on-chain role, so `signerAddress` must be the role holder itself.
The nine RAMS read and typed-data endpoints (`GET /rams/*`) are priced at the cheaper `GETTER` tier, not the transaction tier. They are also callable with an `x-api-key` instead of paying.
Prices are resolved from a database table at request time and environment defaults are only a fallback, so the `GETTER` amount is not fixed here. Read it from the `PAYMENT-REQUIRED` header of the `402` response.
Sandbox, Base Sepolia, and other non-production environments use a flat reference price of `0.01` USDC per write. Agent getters keep their separate `0.000001 USDC` price.
The exact amount, asset, and chain are always quoted in the `PAYMENT-REQUIRED` header of the `402` response (and previewed in the prepare response's `x402Requirements`). Read them from there rather than hardcoding the table above.
x402 payments and on-chain transactions are non-refundable. Confirm chain, signer/recipient, token address, and expected USDC price before paying.
# Request BKN from the Faucet
Source: https://docs.brickken.com/api-reference/endpoint/bkn-faucet
api-reference/openapi.json POST /faucet/bkn
Request 100 BKN on Ethereum Sepolia with an API key or a 0.01 USDC x402 payment.
`POST /faucet/bkn` is available in Sandbox and Forge. It mints **100 BKN on Ethereum Sepolia** to `recipientAddress`.
Use exactly one authentication mode:
* `x-api-key`: consumes one of the key's **10 dedicated lifetime faucet credits**.
* `X-PAYMENT`: settles the live **0.01 USDC** x402 challenge and consumes no API-key credit.
Every request needs `Idempotency-Key`, and its value must be a UUID v4.
Create a new UUID v4 for every new logical claim. If a request times out or its response is lost, retry the same claim with the same UUID. Reusing that UUID with a different recipient returns `409 Conflict`.
The recipient address has a separate 24-hour cooldown. An idempotent retry does not spend another faucet credit, and a request rejected by validation or cooldown does not spend one either.
## Client examples
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/faucet/bkn' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--header 'Idempotency-Key: 4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1' \
--data '{"recipientAddress":"0x1111111111111111111111111111111111111111"}'
```
```ts theme={null}
const result = await bkn.faucet.requestBkn({
recipientAddress: '0x1111111111111111111111111111111111111111',
// Optional: generated as UUID v4 when omitted.
idempotencyKey: '4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1',
})
console.log(result.idempotencyKey)
console.log(result.payment) // present only when the SDK paid through x402
```
```bash theme={null}
brickken faucet bkn \
--recipient-address 0x1111111111111111111111111111111111111111 \
--idempotency-key 4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1 \
--json
```
```json theme={null}
{
"name": "request_bkn_faucet",
"arguments": {
"recipientAddress": "0x1111111111111111111111111111111111111111",
"idempotencyKey": "4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1"
}
}
```
SDK, CLI, and MCP generate a UUID v4 when you omit it and return the actual value used. If crash recovery matters, generate and persist the UUID before the first call so it remains available even if the client never receives a response.
## Response
The API returns `200` when confirmation completed within the request and `202` when the mint was submitted and can finish asynchronously.
```json theme={null}
{
"claimId": "1d0f91d8-453d-4fb5-a8e1-c722bc7b75a2",
"status": "submitted",
"chainId": "11155111",
"recipientAddress": "0x1111111111111111111111111111111111111111",
"amount": "100",
"amountRaw": "100000000000000000000",
"token": {
"address": "0x2458fB1620ff84019d73216fF20aA1F82Bc8E4CC",
"symbol": "BKN",
"decimals": 18
},
"transactionHash": "0x...",
"explorerUrl": "https://sepolia.etherscan.io/tx/0x...",
"cooldownEndsAt": "2026-08-26T12:00:00.000Z"
}
```
`429` means the recipient is still in cooldown and includes `Retry-After`. `Out of credits for faucet` means the API key has spent all 10 lifetime claims; use x402 for a paid request or contact Brickken.
# Prepare Transactions
Source: https://docs.brickken.com/api-reference/endpoint/create
api-reference/openapi.json POST /prepare-transactions
**Description:** This endpoint prepares unsigned transactions for the method selected in the `method` field. For the exact required and optional body fields of a single method, open the matching page under Prepare Transactions.
For a payment-token `approve` used before `dividendDistribution`, call `GET /get-tokenizer-info` for the tokenized asset and set `spenderAddress` to its returned `tokenAddress`. Do not use `escrowAddress`; the approval must be confirmed on-chain before preparing the distribution.
**Headers:**
- `x-api-key`: `YOUR_API_KEY` for API-key auth, or `X-Payment` for x402 retries on eligible agentic methods
- `Content-Type`: `application/json`
**Common Request Body Parameters:**
- `method` (string, required): Operation to prepare.
- `chainId` (string, required): Blockchain network identifier. Hex format is recommended, for example `aa36a7` for Sepolia.
- `signerAddress` (string, conditionally required): Wallet address that signs the prepared transaction. Most methods require it; `newInvest` and `claimTokens` can use `investorAddress` as the signer.
Prepares unsigned transactions for various blockchain operations. This endpoint supports multiple transaction methods for tokenization, STO management, token operations, and more.
## Common Parameters
| Parameter | Type | Required | Description |
| --------------- | ------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `chainId` | string | Yes | Blockchain network identifier (hex format) |
| `method` | string | Yes | Transaction method type |
| `signerAddress` | string | Conditional | Address that will sign the transaction. Most methods require it; `newInvest` and `claimTokens` can use `investorAddress` as the signer. |
## Supported Methods
| Method | Description |
| ---------------------- | ----------------------------------------------- |
| `newTokenization` | Create a new tokenized asset. |
| `mintToken` | Mint tokens to one or more investors. |
| `whitelist` | Whitelist or blacklist investor wallets. |
| `burnToken` | Burn tokens from the signer balance. |
| `transferFrom` | Transfer tokens from an approved owner address. |
| `transferTo` | Transfer tokens from the signer address. |
| `approve` | Approve token spending. |
| `dividendDistribution` | Distribute payment-token dividends. |
| `newSto` | Create a Security Token Offering. |
| `newInvest` | Prepare an STO investment. |
| `claimTokens` | Claim tokens from a successful STO. |
| `closeOffer` | Close an active STO. |
## Response Format
The response includes the transaction details, metadata, and a unique transaction ID that must be saved for use with the `/send-transactions` endpoint.
**Important:** The `txId` is NOT a blockchain transaction hash - it's an internal identifier used to link the prepared transactions with the send operation.
### Response Fields
| Field | Type | Description |
| -------------- | ------ | -------------------------------------------------------------------------------- |
| `transactions` | array | Array of unsigned transaction objects ready for signing |
| `info` | object | Metadata about the operation including emails and token symbol |
| `txId` | string | Unique identifier for this transaction batch (required for `/send-transactions`) |
**Next Steps:**
1. Sign each transaction in the `transactions` array
2. Submit the signed transactions along with the `txId` to `/send-transactions`
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# Create KYC Link
Source: https://docs.brickken.com/api-reference/endpoint/create-kyc-link
POST /create-kyc-link
Create or reuse an investor and return a Sumsub verification link.
This endpoint always requires `x-api-key`. The email is normalized before lookup, and `needKyc` defaults to `true`.
**Testing in Sandbox?** Pass `needKyc: false` and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.
Rehearse the real KYC flow once before you go live, since `needKyc: false` is rejected in
production with `needKyc=false is only available in the sandbox environment`.
This operation can create an investor account and send an invitation email. The returned Sumsub URL grants access to a verification flow; do not log it, commit it, or expose it to another user.
When `needKyc` is `false`, the investor is created without a KYC requirement and `url` is `null`.
## Fields
| Field | Required | Notes |
| --------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `email` | yes | Normalized to lowercase before lookup |
| `needKyc` | no | Defaults to `true`. `false` creates the investor with no KYC requirement, and is accepted in Sandbox only |
| `walletAddress` | no | The investor's wallet, as a valid EVM address |
| `tokenSymbol` | no | Scopes the investor to a tokenized asset |
### Attach the wallet address
An investor record with no wallet address cannot invest. Pass `walletAddress` here so the record is
complete from the start:
```json theme={null}
{
"email": "investor@example.com",
"needKyc": false,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
```
A wallet address is set once. If the investor already has a different address on file, the call is
rejected with `Investor is already associated with a different wallet address` rather than
overwriting it. Preparing a [`whitelist`](/api-reference/endpoint/prepare-whitelist) transaction
also attaches the address when the record does not yet have one.
Confirm the result with `GET /get-investor-info`, which returns `walletAddress` and
`complianceStatus`. A `complianceStatus` of `NOT_REQUIRED` together with a non-null `walletAddress`
is a ready-to-invest test investor.
`needKyc` is only applied when the investor record is created. For an email that already has an
account, the stored value wins and cannot be downgraded — use a fresh address, such as a `+` alias.
## Client examples
`walletAddress` and `tokenSymbol` are currently available through the API only; the CLI, MCP and SDK
clients still accept `email` and `needKyc`.
```bash theme={null}
brickken kyc create-link \
--email investor@example.com \
--need-kyc true \
--json
```
```json theme={null}
{
"name": "create_kyc_link",
"arguments": {
"email": "investor@example.com",
"needKyc": true
}
}
```
```ts theme={null}
const result = await bkn.kyc.createLink({
email: 'investor@example.com',
needKyc: true,
})
```
## Response
```json theme={null}
{
"email": "investor@example.com",
"needKyc": true,
"userCreated": true,
"invitationSent": true,
"tokenSymbol": null,
"walletAddress": "0x1111111111111111111111111111111111111111",
"url": "https://in.sumsub.com/..."
}
```
# Get Agent Information
Source: https://docs.brickken.com/api-reference/endpoint/get-agent-info
GET /get-agent-info
Get a complete ERC-8004 agent profile by stored UUID or on-chain ID.
Provide one of these references:
* `agentUuid`; or
* `agentId` together with `chainId`.
The endpoint accepts an API key or x402 and costs `0.000001 USDC` in x402 mode. API-key access is checked against the API client's agent scope. For x402, the payer must match the agent's stored owner wallet.
## Client examples
```bash theme={null}
brickken agent info --agent-uuid "$AGENT_UUID" --json
```
```json theme={null}
{
"name": "get_agent_info",
"arguments": { "agentUuid": "YOUR_AGENT_UUID" }
}
```
```ts theme={null}
const agent = await bkn.agent.get({ agentUuid })
// Equivalent on-chain reference:
const sameAgent = await bkn.agent.get({ agentId: '8896', chainId: '84532' })
```
The detail response extends the list summary with `registrationFile`, `onchainMetadata`, and `prepareTxId`.
# Get Agent Transactions
Source: https://docs.brickken.com/api-reference/endpoint/get-agent-transactions
GET /get-agent-transactions
List ERC-8004, agent-token, and RAMS transactions for one agent.
Reference the agent with `agentUuid`, or with `agentId` and `chainId`. The endpoint accepts an API key or x402 and costs `0.000001 USDC` in x402 mode. API-key access is scope-checked; the x402 payer must match the agent owner wallet.
`limit` defaults to `50` and accepts `1`–`100`. `offset` defaults to `0` and cannot be negative.
## Client examples
```bash theme={null}
brickken agent transactions \
--agent-uuid "$AGENT_UUID" \
--limit 20 \
--offset 0 \
--json
```
```json theme={null}
{
"name": "get_agent_transactions",
"arguments": {
"agentUuid": "YOUR_AGENT_UUID",
"limit": 20,
"offset": 0
}
}
```
```ts theme={null}
const history = await bkn.agent.transactions({
agentUuid,
limit: 20,
offset: 0,
})
```
Each transaction includes a `category` of `erc8004`, `agentToken`, or `rams`, plus a sanitized `details` object with operation-specific fields.
# List Agents
Source: https://docs.brickken.com/api-reference/endpoint/get-agents
GET /get-agents
List API-key-scoped agents or x402 owner-scoped agents.
With an API key, the result is scoped to agents associated with that API client; `chainId` and `ownerWalletAddress` are optional filters.
Without an API key, the endpoint returns an x402 challenge priced at `0.000001 USDC`. Both `chainId` and `ownerWalletAddress` are required, and the x402 payer must match the owner wallet.
`limit` defaults to `50` and accepts `1`–`100`. `offset` defaults to `0` and cannot be negative.
## Client examples
```bash theme={null}
brickken agent list --chain 84532 --limit 20 --offset 0 --json
```
```json theme={null}
{
"name": "get_agents",
"arguments": {
"chainId": "84532",
"limit": 20,
"offset": 0
}
}
```
```ts theme={null}
const result = await bkn.agent.list({
chainId: '84532',
limit: 20,
offset: 0,
})
```
For x402, also pass `ownerWalletAddress` to the CLI, MCP tool, or SDK call. The CLI and SDK use the configured payment signer.
# Get Allowance
Source: https://docs.brickken.com/api-reference/endpoint/get-allowance
GET /get-allowance
**Description:** Reads the payment-token allowance between two addresses for a tokenized asset. The value is returned as a decimal string in whole units, not in the smallest unit.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
- `ownerAddress` (string): Token owner address.
- `spenderAddress` (string): Spender address.
Retrieves the allowance amount for a spender.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `ownerAddress` (required): Token owner address
* `spenderAddress` (required): Spender address
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-allowance?tokenSymbol=EXMPL&ownerAddress=0x123...&spenderAddress=0x456...' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"allowance": "1000000000000000000"
}
```
# Get Balance and Whitelist Status
Source: https://docs.brickken.com/api-reference/endpoint/get-balance-whitelist
GET /get-balance-whitelist
**Description:** Reads the on-chain token balance and whitelist flag of the wallet associated with an investor or owner email.
`bknFees` and `senderBalance` are deprecated legacy fields and are always returned as `"0"`. Read `tokenBalance` or `tokenBalanceRaw` instead.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
- `investorEmail` (string): Email of the investor or owner.
Reads the on-chain token balance and whitelist flag of the wallet associated with an investor or owner email.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `investorEmail` (required): Email of the investor or owner
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-balance-whitelist?tokenSymbol=EXMPL&investorEmail=investor@example.com' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"walletAddress": "0x1111111111111111111111111111111111111111",
"tokenAddress": "0x2222222222222222222222222222222222222222",
"tokenDecimals": 18,
"tokenBalanceRaw": "500000000000000000000",
"tokenBalance": "500.0",
"isWhitelisted": true,
"balanceSource": "blockchain",
"bknFees": "0",
"senderBalance": "0"
}
```
`bknFees` and `senderBalance` are deprecated. They are kept in the response for backward compatibility and are
always `"0"`, whatever the real balance is. Read `tokenBalance` (formatted with `tokenDecimals`) or
`tokenBalanceRaw` (smallest unit) instead.
Both the balance and the whitelist flag are read from the token contract, so `balanceSource` is always
`blockchain`. If you already know the wallet address and only need the whitelist flag, use
[`GET /get-whitelist-status`](/api-reference/endpoint/get-whitelist-status) — it does not require the address to
be registered as an investor under an email.
# Get Dividend Distribution Info
Source: https://docs.brickken.com/api-reference/endpoint/get-dividend-distribution
GET /get-dividend-distribution
**Description:** Retrieves information about dividend distributions for a token.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
Lists the dividend distributions executed for a token, newest first.
## Query Parameters
* `tokenSymbol` (required): Token symbol
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-dividend-distribution?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"tokenSymbol": "EXMPL",
"companyName": "Example Corp",
"tokenizerEmail": "tokenizer@example.com",
"distributions": [
{
"uuid": "b8341970-b99d-4c75-929c-854ab746723e",
"tokenizerEmail": "tokenizer@example.com",
"amountInPaymentToken": "1000.0",
"paymentTokenSymbol": "USDC",
"paymentTokenAddress": "0x2222222222222222222222222222222222222222",
"txHash": "0xae08674018f81ce617aa8b6c4d582a681b278542cf30921536b91b2162fe19fb",
"status": "success",
"date": "2026-08-10T12:00:00.000Z"
}
],
"total": 1
}
```
Amounts are denominated in the payment token, not in the security token. To prepare a new distribution, see
[`dividendDistribution`](/api-reference/endpoint/prepare-dividendDistribution) and the
[`approve`](/api-reference/endpoint/prepare-approve) allowance it requires.
# Get Investments by STO
Source: https://docs.brickken.com/api-reference/endpoint/get-investments-by-sto
GET /get-investments-by-sto-id
**Description:** This endpoint retrieves a list of investment transactions associated with a specific Security Token Offering (STO), identified by its UUID.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
- `id` (string, format: uuid): The unique identifier of the STO for which to retrieve investments.
Lists the investment transactions recorded for one offering.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `id` (required): Offering `uuid`, as returned by [`GET /get-stos`](/api-reference/endpoint/get-stos)
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-investments-by-sto-id?tokenSymbol=EXMPL&id=a5232594-3f97-47d0-b362-491caac9388f' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"offeringTransactionsList": [
{
"id": "b8341970-b99d-4c75-929c-854ab746723e",
"date": "2026-08-10T12:00:00.000Z",
"txHash": "0xae08674018f81ce617aa8b6c4d582a681b278542cf30921536b91b2162fe19fb",
"user": "investor@example.com",
"currency": "USDC",
"amountInUSD": "100.0",
"status": "invest"
}
],
"total": 1
}
```
An unknown or unmatched offering `id` returns an empty list with `total: 0` rather than an error. `status` is the
claimant operation when one exists, and `invest` otherwise.
# Get Investor Information
Source: https://docs.brickken.com/api-reference/endpoint/get-investors-info
GET /get-investor-info
Returns detailed information about an individual investor, including personal details, KYC verification link, wallet address, investor type, and a list of all past investments. Each investment entry includes transaction details such as amount, currency, status, associated token, and offering metadata
Retrieves an investor profile, KYC/compliance state, and investments for one token. The response is not a whitelist lookup; use [Get Whitelist Status](/api-reference/endpoint/get-whitelist-status) for the on-chain whitelist.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `email` (required): Investor email
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-investor-info?tokenSymbol=EXMPL&email=investor@example.com' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"email": "investor@example.com",
"firstName": "Jane",
"lastName": "Doe",
"kycUrl": "https://kyc.example.com/user/123",
"profilePicture": null,
"walletAddress": "0x1111111111111111111111111111111111111111",
"type": "INVESTOR",
"needKyc": true,
"kycStatus": "completed",
"kycResult": "GREEN",
"complianceStatus": "APPROVED",
"investments": [
{
"id": "b8341970-b99d-4c75-929c-854ab746723e",
"date": "2026-08-10T12:00:00.000Z",
"txHash": "0x...",
"currency": "USDC",
"amountInUSDT": "100.0",
"status": "success",
"tokenSymbol": "EXMPL",
"offeringId": "a5232594-3f97-47d0-b362-491caac9388f",
"offeringName": "Round A"
}
]
}
```
`complianceStatus` is one of `NOT_REQUIRED`, `NOT_STARTED`, `PENDING`, `APPROVED`, `REJECTED`, or `ON_HOLD` and is derived from `needKyc`, `kycStatus`, and `kycResult`.
# Get Network Information
Source: https://docs.brickken.com/api-reference/endpoint/get-network-info
GET /get-network-info
**Description:** Retrieves network information for a specified chain ID.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `chainId` (string): The blockchain's chain ID (e.g., "aa36a7").
Reads the chain metadata and the Brickken contract addresses deployed on a network. This endpoint does not
require a token symbol, so it works before you have created any asset.
## Query Parameters
* `chainId` (required): Blockchain network ID. Decimal (`11155111`) and hexadecimal (`0xaa36a7`) forms are both accepted.
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-network-info?chainId=11155111' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"currencyName": "ETH",
"blockExplorerUrl": "https://sepolia.etherscan.io",
"factoryAddress": "0x1111111111111111111111111111111111111111",
"BKNAddress": "0x2222222222222222222222222222222222222222",
"USDTAddress": "0x3333333333333333333333333333333333333333",
"USDCAddress": "0x4444444444444444444444444444444444444444"
}
```
`factoryAddress`, `BKNAddress`, `USDTAddress`, and `USDCAddress` are `null` when the corresponding contract is
not configured on that network.
# Get STO Balance
Source: https://docs.brickken.com/api-reference/endpoint/get-sto-balance
GET /get-sto-balance
**Description:** This endpoint retrieves balance details and current status for a Security Token Offering (STO).
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
- `id` (string, format: uuid): The unique identifier of the STO.
Reads one offering together with how much it has raised and how much is still available.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `id` (required): Offering `uuid`, as returned by [`GET /get-stos`](/api-reference/endpoint/get-stos)
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-sto-balance?tokenSymbol=EXMPL&id=a5232594-3f97-47d0-b362-491caac9388f' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"uuid": "a5232594-3f97-47d0-b362-491caac9388f",
"name": "Round A",
"companyName": "Example Corp",
"status": "active",
"tokenAmount": "100000",
"hardCap": "500000",
"softCap": "50000",
"minInvestment": "100",
"maxInvestment": "10000",
"startDate": "2026-01-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"tokenPrice": "5.0",
"tokenSymbol": "EXMPL",
"currentAmountRaised": "25000",
"availableAmount": "75000"
}
```
# Get STO by ID
Source: https://docs.brickken.com/api-reference/endpoint/get-sto-by-id
GET /get-sto-by-id
Read one Security Token Offering by its identifier.
Requires `x-api-key`. Returns the full record for a single offering — supply, price, dates, status, the escrow
contract address, and the associated token.
Your key must be the tokenizer of the token behind the offering, or the call returns `Unauthorized token symbol`. See [Authentication](/get-started/authentication).
Use [`GET /get-stos`](/api-reference/endpoint/get-stos) to list every offering for a token and discover the IDs.
# Get STOs
Source: https://docs.brickken.com/api-reference/endpoint/get-stos
GET /get-stos
**Description:** Lists every offering of a tokenized asset. The response is a JSON array, not an object.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
Lists every Security Token Offering of a tokenized asset. The response is a JSON array, not an object.
## Query Parameters
* `tokenSymbol` (required): Token symbol
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-stos?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
[
{
"uuid": "a5232594-3f97-47d0-b362-491caac9388f",
"name": "Round A",
"status": "active",
"tokenAmount": "100000",
"hardCap": "500000",
"softCap": "50000",
"maxInvestment": "10000",
"minInvestment": "100",
"tokenSymbol": "EXMPL",
"startDate": "2026-01-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"tokenPrice": "5.0",
"acceptedCoin": "USDC",
"escrow": "0x3333333333333333333333333333333333333333"
}
]
```
Use `uuid` as the `id` parameter of [`GET /get-sto-by-id`](/api-reference/endpoint/get-sto-by-id),
[`GET /get-sto-balance`](/api-reference/endpoint/get-sto-balance), and
[`GET /get-investments-by-sto-id`](/api-reference/endpoint/get-investments-by-sto).
# Get Token Information
Source: https://docs.brickken.com/api-reference/endpoint/get-token-info
GET /get-token-info
**Description:** Reads token information. The endpoint has two modes.
- With `tokenSymbol`: returns the stored record of that tokenized asset.
- Without `tokenSymbol`: returns the token symbols and tokenizer emails available to the API key.
This endpoint does **not** return the deployed token contract address and does not return wallet balances. Use `GET /get-tokenizer-info` for the contract address (`tokenAddress`) and `GET /get-balance-whitelist` for balances.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string, optional): The symbol of the token.
Reads token information. This endpoint has two modes, selected by whether you send `tokenSymbol`.
This endpoint does **not** return the deployed token contract address. After a `newTokenization` succeeds, read
the address from [`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) as `tokenAddress`.
It also does not return wallet balances — use
[`GET /get-balance-whitelist`](/api-reference/endpoint/get-balance-whitelist) for those.
## Query Parameters
* `tokenSymbol` (optional): Token symbol. Omit it to list what the API key can see.
## Mode 1 — list what the API key can see
Omit `tokenSymbol`. Useful right after a tokenization, to confirm the new symbol is registered.
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-token-info' \
--header 'x-api-key: YOUR_API_KEY'
```
```json theme={null}
{
"tokenSymbols": [
"EXMPL"
],
"tokenizerEmails": [
"tokenizer@example.com"
]
}
```
## Mode 2 — read one asset record
Send `tokenSymbol`. Your key must be the tokenizer of that token, or the call returns `Unauthorized token symbol`.
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-token-info?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
```json theme={null}
{
"uuid": "a5232594-3f97-47d0-b362-491caac9388f",
"name": "Example Corp",
"tokenName": "Example Token",
"tokenSymbol": "EXMPL",
"tokenType": "equity",
"tokenizerEmail": "tokenizer@example.com",
"companyWalletAddress": "0x1111111111111111111111111111111111111111",
"tokenLogotype": "https://cdn.example.com/logo.png",
"subscriptionAgreement": "ipfs://...",
"legalDocs": "ipfs://...",
"allowedTokenDecimals": 18,
"initialTokenSupply": "1000000",
"maxTokenSupply": "10000000",
"paymentToken": {
"symbol": "USDC",
"address": "0x2222222222222222222222222222222222222222",
"decimals": 6,
"blockchain": {
"chainId": "aa36a7",
"chainName": "Ethereum Sepolia",
"blockExplorerUrl": "https://sepolia.etherscan.io"
}
}
}
```
## Where to find each address
| You need | Endpoint | Field |
| ------------------------- | ----------------------------------------------------------------------------- | ------------------------------ |
| Token contract address | [`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) | `tokenAddress` |
| Payment token address | [`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) | `paymentTokenAddress` |
| Escrow address | [`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) | `escrowAddress` |
| Factory and BKN addresses | [`GET /get-network-info`](/api-reference/endpoint/get-network-info) | `factoryAddress`, `BKNAddress` |
| Holder balance | [`GET /get-balance-whitelist`](/api-reference/endpoint/get-balance-whitelist) | `tokenBalance` |
# Get Tokenizer Information
Source: https://docs.brickken.com/api-reference/endpoint/get-tokenizer-info
GET /get-tokenizer-info
**Description:** Reads the tokenizer and contract addresses of a specific token. This is the endpoint that returns the deployed token contract address (`tokenAddress`) after a `newTokenization` succeeds.
For a payment-token approval before `dividendDistribution`, use the returned `tokenAddress` as `spenderAddress`. `paymentTokenAddress` identifies the ERC-20 being approved; `escrowAddress` is not the spender for this allowance.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
Retrieves the tokenizer and contract addresses of a specific token.
This is where you read the deployed token contract address after a `newTokenization` succeeds. The address is
returned as `tokenAddress`; neither the transaction status response nor
[`GET /get-token-info`](/api-reference/endpoint/get-token-info) contains it.
## Query Parameters
* `tokenSymbol` (required): Token symbol
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-tokenizer-info?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"companyWalletAddress": "0x0000000000000000000000000000000000000001",
"tokenAddress": "0x0000000000000000000000000000000000000002",
"paymentTokenAddress": "0x0000000000000000000000000000000000000003",
"escrowAddress": "0x0000000000000000000000000000000000000004",
"chainId": "aa36a7",
"email": "tokenizer@example.com"
}
```
## Address roles for dividend distributions
When preparing the payment-token allowance required by `dividendDistribution`:
* Use `tokenAddress` as the `spenderAddress` of the `approve` request. This is the STO token contract that consumes the allowance.
* `paymentTokenAddress` is the ERC-20 payment token contract on which the approval transaction is executed.
* `companyWalletAddress` identifies the tokenizer and can be passed as `tokenizerAddress` for a shared payment token such as USDT.
* Do not use `escrowAddress` as the spender for the dividend allowance.
See [`approve`](/api-reference/endpoint/prepare-approve) for a complete request example.
# Get Transaction Status
Source: https://docs.brickken.com/api-reference/endpoint/get-transaction-status
GET /get-transaction-status
**Description:** This endpoint retrieves the status of a transaction submitted through `/send-transactions`.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `hash` (string, optional): On-chain transaction hash returned after the transaction is sent. Use the exact hash value starting with `0x`.
- `txId` (string, optional): Internal transaction ID returned by `/prepare-transactions`. Use this when the on-chain transaction hash is not available yet.
At least one of `hash` or `txId` is required. Do not send a request body, because this endpoint only accepts `GET`.
Retrieves the status of a transaction submitted through `/send-transactions`.
## Query Parameters
* `hash` (optional): On-chain transaction hash returned after the transaction is sent. Use the exact hash value starting with `0x`.
* `txId` (optional): Internal transaction ID returned by `/prepare-transactions`. Use this when the on-chain transaction hash is not available yet.
At least one of `hash` or `txId` is required. Do not include `--data` in the request, because this endpoint only accepts `GET`.
## Example
```bash theme={null}
curl --location --request GET 'https://api.sandbox.brickken.com/get-transaction-status?hash=0x46f7114878c49ad5af0f1e6f0a2ce9c700c1fdf36455fd956b20f492ee813e80' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"status": "success",
"transactionHash": "0x46f7114878c49ad5af0f1e6f0a2ce9c700c1fdf36455fd956b20f492ee813e80"
}
```
`status` is `pending`, `success`, or `rejected`. `transactionHash` appears as soon as Brickken has resolved the
on-chain hash, so a `pending` response may not include it yet.
If the transaction failed, the response includes the stored error:
```json theme={null}
{
"status": "rejected",
"error": "Transaction failed"
}
```
A confirmed `newTokenization` does not carry the new token contract address. Read it from
[`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) as `tokenAddress` once the status is
`success`.
## x402 transactions
When the transaction was paid through x402, the response also carries the payment outcome:
```json theme={null}
{
"status": "success",
"transactionHash": "0x46f7114878c49ad5af0f1e6f0a2ce9c700c1fdf36455fd956b20f492ee813e80",
"paymentStatus": "settled",
"settlementTransaction": "0xae08674018f81ce617aa8b6c4d582a681b278542cf30921536b91b2162fe19fb"
}
```
`paymentStatus` is one of `received`, `verified`, `settle_submitted`, `settled`, `released`, `failed`, or
`replayed`. `settlementTransaction` appears once a settlement transaction exists, and `paymentError` appears when
the payment recorded a failure reason; either, both, or neither may be present. All three fields are omitted for
API-key transactions.
# Get Whitelist Status
Source: https://docs.brickken.com/api-reference/endpoint/get-whitelist-status
GET /get-whitelist-status
**Description:** Reads the whitelist flag of an address directly from the token contract.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Query Parameters:**
- `tokenSymbol` (string): The symbol of the token.
- `address` (string): Wallet address to check. `investorAddress` is accepted as a legacy alias.
Checks the token contract directly to determine whether an address is whitelisted.
## Query Parameters
* `tokenSymbol` (required): Token symbol
* `address` (required): Wallet address to check. `investorAddress` is accepted as a legacy alias — send either one.
## Example
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-whitelist-status?tokenSymbol=EXMPL&address=0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8b' \
--header 'x-api-key: YOUR_API_KEY'
```
## Response
```json theme={null}
{
"isWhitelisted": true,
"address": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8b",
"tokenSymbol": "EXMPL",
"source": "blockchain"
}
```
`address` is returned in checksummed form, and `source` is always `blockchain` because the flag is read from the
token contract rather than from Brickken's database.
# approve
Source: https://docs.brickken.com/api-reference/endpoint/prepare-approve
api-reference/prepare/approve.json POST /prepare-transactions
Grant an ERC-20 allowance before an investment or a dividend distribution.
Prepares unsigned transactions for approving a spender to use tokens on behalf of the signer. Use `POST /prepare-transactions` with `method=approve`.
## Fields
* `tokenSymbol` selects the **token being approved**, not the asset it relates to.
* `spenderAddress` is the address allowed to spend it. It is never derived — you must pass it.
* `tokenizerAddress` is additionally required when `tokenSymbol` is a shared payment token
(`USDT`, `USDC`, `BKN`, `HAI`). Use `companyWalletAddress` from `GET /get-tokenizer-info`.
* `amount` is in **whole tokens**. Send `"100"` for 100 USDT; the API applies the token's decimals
for you. Do not pre-multiply.
`spenderAddress` is validated as an EVM address, and a malformed value is rejected with a
validation error naming that field. Two things trip it most often: an invalid EIP-55 checksum, and
leading or trailing whitespace picked up from a copied value or an environment variable. Trim the
value, or send the address in all lowercase, which always passes the checksum rule.
Sending the field as `spender` instead of `spenderAddress` returns
`Missing spender address parameter`.
## Choosing the spender
Allowances are **per spender**. An allowance granted to one contract gives nothing to another, so an
investor who has invested in one offering still has to approve the next offering's escrow separately.
| Purpose | `tokenSymbol` | `spenderAddress` |
| ------------------------ | ---------------------------- | --------------------------------------- |
| Investing in an offering | the offering's payment token | `escrowAddress` |
| Distributing dividends | the asset's payment token | `tokenAddress` (the STO token contract) |
Both addresses come from the same call:
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-tokenizer-info?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
## Approving payment tokens for dividend distributions
Before calling `dividendDistribution`, approve the tokenized asset's configured payment token and set `spenderAddress` to the **STO token contract address**.
Use the response fields as follows:
* `tokenAddress` → `spenderAddress` in the `approve` request
* `paymentTokenAddress` → the ERC-20 contract being approved; use its configured symbol, such as `USDT`, as `tokenSymbol`
* `companyWalletAddress` → `tokenizerAddress` when approving a shared payment token
* `escrowAddress` → **do not use this as the spender for `dividendDistribution`**
Approving the payment token to `escrowAddress` does not satisfy the dividend allowance check. The allowance must be from `signerAddress` to the STO `tokenAddress`.
For example, if `get-tokenizer-info` returns the STO address `0x2222222222222222222222222222222222222222` and the configured payment token is USDT:
```json theme={null}
{
"method": "approve",
"signerAddress": "0x1111111111111111111111111111111111111111",
"chainId": "aa36a7",
"tokenSymbol": "USDT",
"spenderAddress": "0x2222222222222222222222222222222222222222",
"amount": "100",
"tokenizerAddress": "0x1111111111111111111111111111111111111111"
}
```
Sign and submit the prepared approval, then wait for its on-chain confirmation before preparing `dividendDistribution`.
## Replacing an existing allowance
Some payment tokens refuse to change a non-zero allowance directly. When the signer already has a
non-zero allowance for that spender, the response therefore contains **two** transactions — a reset
to `0` followed by the new amount — and `txId` is an array rather than a single value.
```json theme={null}
{
"transactions": [ { "…reset to 0…" }, { "…new amount…" } ],
"txId": ["0xaaa…", "0xbbb…"]
}
```
Iterate the array rather than assuming a single entry, and broadcast the transactions **in order**,
waiting for the reset to confirm before sending the second.
Both transactions are gas-estimated at prepare time, while the reset is still unmined. On a token
that strictly forbids a non-zero to non-zero change, that estimate can fail and the whole prepare
call returns a revert with empty data (`"data": "0x"`).
If it does: check the current allowance with `GET /get-allowance`. If it already covers the amount
you need, skip the approval entirely. Otherwise prepare and send `amount: "0"` on its own first,
wait for it to confirm, then prepare the new amount.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# burnToken
Source: https://docs.brickken.com/api-reference/endpoint/prepare-burnToken
api-reference/prepare/burnToken.json POST /prepare-transactions
Burn tokens held by the signing wallet.
Prepares unsigned transactions for burning tokens from the signer's balance. Use `POST /prepare-transactions` with `method=burnToken`.
Burning reduces the token's current `totalSupply`. It does not reduce the configured maximum supply.
## The signer's balance is what burns
The prepared transaction calls `burn(amount)`, which burns the caller's own tokens. The API checks
the balance of `signerAddress` and returns `Insufficient token balance` when it is short.
`investorEmail` is required, but it only attributes the burn in Brickken's records. It does **not**
select whose tokens are burned, and there is no `investorAddress` selector on this method.
A tokenizer wallet that holds none of the token therefore gets `Insufficient token balance` even
when the investor named in the request holds plenty.
## Burning tokens an investor holds
The API does not expose a delegated burn. Two supported routes:
* **The investor signs.** Use the investor's wallet as `signerAddress`, so the burn comes out of the balance that actually holds the tokens.
* **Recover, then burn.** Have the investor `approve` the company wallet, use [`transferFrom`](/api-reference/endpoint/prepare-transferFrom) to move the tokens to it, then burn from the company wallet.
If your application only ever acts for the issuer and can never obtain an investor signature, only the second route is available.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# claimTokens
Source: https://docs.brickken.com/api-reference/endpoint/prepare-claimTokens
api-reference/prepare/claimTokens.json POST /prepare-transactions
Collect tokens from a successful offering, or a refund from a rolled-back one.
Prepares unsigned transactions for claiming from a Security Token Offering (STO) investment. Use `POST /prepare-transactions` with `method=claimTokens`.
The prepared transaction is signed and sent by the investor.
## The offering must be finalized first
`claimTokens` reverts with `0x04c7a3b1` `IssuanceNotInRollback(uint256)` while the issuance has not
been finalized. The argument is the issuance index, not an address.
Run [`closeOffer`](/api-reference/endpoint/prepare-closeOffer) first — and `closeOffer` itself only
works once the offering's `endDate` has passed.
## What you get back
The same call does one of two things, decided at finalization:
* **Successful offering** — the purchased tokens are released to the investor.
* **Rolled-back offering** — the payment token is refunded instead, because the soft cap was not reached.
## Testing a successful claim end to end
Because there is no minimum offering duration, a short offering is the reliable way to exercise the
full lifecycle:
Set `minRaiseUSD` low enough that your test investment alone can meet it, and set `endDate` a few
minutes out. Remember the `Z` suffix on both dates.
Invest at least the soft cap, so finalization resolves to success rather than rollback.
There is no way to close early.
Run `closeOffer` and wait for it to confirm.
`claimTokens` now releases the tokens.
## Notes
* The investor must have participated in the offering.
* Each investor can only claim once.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# closeOffer
Source: https://docs.brickken.com/api-reference/endpoint/prepare-closeOffer
api-reference/prepare/closeOffer.json POST /prepare-transactions
Finalize an offering after its end date, releasing the raise or entering rollback.
Prepares unsigned transactions for finalizing a Security Token Offering (STO). Use `POST /prepare-transactions` with `method=closeOffer`.
Finalizing is what unlocks [`claimTokens`](/api-reference/endpoint/prepare-claimTokens): until it runs, investors can neither receive their tokens nor be refunded.
## The end date has to have passed
An offering cannot be closed early. The escrow refuses to finalize an offering that has not
started, and refuses to finalize one whose `endDate` has not yet passed — returning
`0xffac9d14` `IssuanceNotEnded(address,uint256)`. There is no administrative or time override,
in Sandbox or in production.
An offering therefore runs for its full configured window. Since there is no minimum duration, give
test offerings a short `endDate` so you can exercise close and claim quickly.
## Success or rollback
What finalization does depends on whether the raise reached `minRaiseUSD`, the offering's soft cap:
| Outcome | Condition | Effect |
| ---------- | ---------------------------------------- | -------------------------------------------------------------------------- |
| Successful | Amount raised reached the soft cap | The raise is withdrawn to the issuer, and investors can claim their tokens |
| Rollback | Amount raised fell short of the soft cap | Investors are refunded their payment token instead of receiving tokens |
Waiting for the end date does not by itself produce a successful offering. An offering that ends
under its soft cap finalizes into rollback, and `claimTokens` then refunds. To demonstrate a
successful claim, size the soft cap so the offering can actually reach it.
## Notes
* Only the issuer of the offering can close it.
* Existing investments remain valid throughout; nothing is lost by waiting for the window to end.
* Finalization is irreversible once the transaction is confirmed.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# dividendDistribution
Source: https://docs.brickken.com/api-reference/endpoint/prepare-dividendDistribution
api-reference/prepare/dividendDistribution.json POST /prepare-transactions
Distribute payment-token dividends to the holders of a tokenized asset.
Prepares unsigned transactions for distributing payment token dividends to holders of a specific token. Use `POST /prepare-transactions` with `method=dividendDistribution`.
## Notes
* Amounts are specified in whole units (e.g., 10 for 10 USDT)
* The signer must have sufficient balance of the payment token
* The signer must first approve the configured payment token to the STO contract. Retrieve the STO address from `GET /get-tokenizer-info?tokenSymbol=...` and use its `tokenAddress` as `spenderAddress` in the `approve` request.
* Do not use `escrowAddress` as the approval spender for this operation. Wait for the payment-token approval to be confirmed on-chain before preparing the distribution.
* Only the tokenizer can distribute dividends for their tokens
## Which token, and which spender
The allowance is read as `paymentToken.allowance(signerAddress, tokenAddress)`, where the payment
token is resolved from the asset on-chain. Getting either half wrong produces the same error:
| Approve this | With this spender |
| --------------------------------------------------------------------------- | ----------------------------------------------- |
| The asset's **payment token** (for example `USDT`) — not the security token | The **security token contract**, `tokenAddress` |
`GET /get-token-info` returns the asset's configured payment token, not the security token's own
address. The address you need as `spenderAddress` is `tokenAddress` from
`GET /get-tokenizer-info`. Approving the security token itself, or approving to `escrowAddress`,
both leave the dividend allowance at zero.
## Preflight errors
| Message | Meaning |
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
| `Insufficient allowance to distribute dividends` | The allowance from `signerAddress` to `tokenAddress`, on the payment token, is below the requested amount |
| `Insufficient balance to distribute dividends` | The signer does not hold enough payment token |
Both are returned as `400` before anything is prepared, so **nothing was broadcast** and no funds
moved. Fix the allowance or the balance and prepare again.
There is no additional platform fee folded into this check: the allowance only has to cover the
dividend amount you requested.
Once distributed, it can take a little while for a storefront's claim action to become available to
holders.
See [`approve`](/api-reference/endpoint/prepare-approve) for the complete allowance workflow and field mapping.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# mintToken
Source: https://docs.brickken.com/api-reference/endpoint/prepare-mintToken
api-reference/prepare/mintToken.json POST /prepare-transactions
Issue tokens directly to investors, optionally whitelisting them in the same call.
Prepares unsigned transactions for minting tokens to specified users. Use `POST /prepare-transactions` with `method=mintToken`.
Minting increases the token's current `totalSupply` and the recipient's balance. It does not change the configured maximum supply.
## Recipient Requirements
* Every entry in `userToMint` needs a valid `investorEmail` and a positive whole-token `amount`.
* `investorEmail` must be different from the token's `tokenizerEmail`. Issuer and investor are separate email identities, even when they use the same wallet for sandbox testing. A collision returns `investorEmail cannot be the tokenizer email (index N)`, where `N` is the position in `userToMint`.
* Use the exact symbol from a successfully confirmed `newTokenization`. A symbol that does not resolve on the supplied chain returns `No company found with this token symbol`.
* `needWhitelist` only determines whether the recipient is whitelisted with the mint. It does not change the identity requirement. It defaults to `true` unless explicitly set to `false`.
* `needKyc` on a `userToMint` entry works the same way it does on [`whitelist`](/api-reference/endpoint/prepare-whitelist), and `false` is accepted in Sandbox only.
**Testing in Sandbox?** Pass `needKyc: false` and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.
Rehearse the real KYC flow once before you go live, since `needKyc: false` is rejected in
production with `needKyc=false is only available in the sandbox environment`.
This method is an issuance-to-investors flow. It cannot mint to the tokenizer's own identity, so
there is no supported payload for minting into a company treasury.
## Response shape
`transactions` is an array, as it is for every other prepare method. Iterate it rather than assuming
a single entry: when a recipient still needs whitelisting, the response carries **two** transactions.
When no recipient needs whitelisting:
```json theme={null}
{
"transactions": [ { "…unsigned mint transaction…" } ],
"info": { "…" },
"txId": "0x…"
}
```
When at least one recipient still needs whitelisting, the whitelist transaction comes first and
`txId` carries the matching identifiers in the same order:
```json theme={null}
{
"transactions": [
{ "…unsigned whitelist transaction…" },
{ "…unsigned mint transaction…" }
],
"info": { "…" },
"txId": ["0x…", "0x…"]
}
```
Sign and send **all of them, in order**, and wait for each to succeed before the next. The
transactions carry sequential nonces, so broadcasting only the mint leaves it on a nonce that will
never be used: it never mines, and the tokens never exist. A later `burnToken` or balance read then
correctly reports no balance, which looks like an indexing lag but is not one.
## Credits
Two independent counters can block a mint:
* **API-key mint credits**, consumed once per mint operation at send time. Exhausting them returns `Out of credits for minting`.
* **License mint-recipient credits**, counted per distinct recipient. Exhausting them returns `Mint credit limit exceeded`.
A recipient email that has never been invited also consumes an **invitation credit**; exhausting those returns `Invitation credit limit exceeded`. When more than one counter is exhausted the message lists them, for example `Insufficient license credits: mint, invitation`.
None of these have a public reset endpoint. Contact [support@brickken.com](mailto:support@brickken.com) to review an account's balances.
The first mint to a new recipient sends both a new-shareholder invitation and a token-received
notification. Later mints to the same recipient send only the token-received notification.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# newInvest
Source: https://docs.brickken.com/api-reference/endpoint/prepare-newInvest
api-reference/prepare/newInvest.json POST /prepare-transactions
Invest in an open Security Token Offering on behalf of a registered investor.
Prepares unsigned transactions for making an investment in a Security Token Offering (STO). Use `POST /prepare-transactions` with `method=newInvest`.
The prepared transaction is signed and sent by `investorAddress`, not by the tokenizer.
## Prerequisites
`newInvest` prepares a single `buyToken` transaction and nothing else. It does **not** whitelist the
investor and it does **not** return an `approve` transaction. Everything below must already be true
before you call it.
Create the investor with [`whitelist`](/api-reference/endpoint/prepare-whitelist) or
[`create-kyc-link`](/api-reference/endpoint/create-kyc-link), passing the wallet address. Verify
with `GET /get-investor-info`: a null `walletAddress` fails the call.
The investor's email must be different from the tokenizer account's email, or no investor record
is created and lookups return `Investor not found`.
Confirm with `GET /get-whitelist-status?tokenSymbol=…&address=…`. Whitelisting is per token, and
the whitelist transaction must be signed, sent, and confirmed — preparing it is not enough.
`GET /get-investor-info` → `complianceStatus` must be `APPROVED` or `NOT_REQUIRED`. In Sandbox,
create the investor with `needKyc: false` and it reads `NOT_REQUIRED` from the start.
Use [`approve`](/api-reference/endpoint/prepare-approve) with the offering's `escrowAddress` as
`spenderAddress`. Allowances are per spender: approving one offering's escrow grants nothing to
another's.
An allowance is a permission, not a balance. Both must cover the investment amount.
`startDate` must have passed and `endDate` must not have. Check with `GET /get-sto-by-id`.
The amount must also sit within the offering's `minInvestment` and `maxInvestment`.
**Testing in Sandbox?** Pass `needKyc: false` and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.
Rehearse the real KYC flow once before you go live, since `needKyc: false` is rejected in
production with `needKyc=false is only available in the sandbox environment`.
## How failures surface
The whitelist, the allowance, and the balance are enforced by the contract, not by an API
precondition check — they are caught when the API simulates the transaction. So they come back as
**contract reverts**, not as friendly messages:
| Revert | Meaning |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `0x3ecda1e8` `IssuanceNotStarted(address)` | The offering has not opened yet. Check the `Z` suffix on the `startDate` you used at `newSto`. |
| `0xaafefe9b` `UserIsNotWhitelisted(address)` | The wallet in the argument is not whitelisted for this token. |
| Panic `0x11` | Arithmetic underflow — a zero or insufficient allowance to this escrow, or not enough payment token in the wallet. |
Compliance is checked before the chain is simulated, so a KYC-ineligible investor always gets a
plain `400` naming the compliance problem. A revert therefore always means chain state — a
timestamp, a whitelist entry, an allowance, or a balance — never a compliance verdict.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
See [Troubleshooting](/api-reference/guides/troubleshooting) for full revert decoding.
# newSto
Source: https://docs.brickken.com/api-reference/endpoint/prepare-newSto
api-reference/prepare/newSto.json POST /prepare-transactions
Launch a Security Token Offering for an existing tokenized asset.
Prepares unsigned transactions for creating a new Security Token Offering (STO). Use `POST /prepare-transactions` with `method=newSto`.
Wait for the tokenization to succeed before preparing the STO, and use the exact token symbol available to the API key on the selected chain.
## Fields
All of the following are required: `method`, `chainId`, `signerAddress`, `tokenizerEmail`, `tokenSymbol`, `offeringName`, `tokenAmount`, `acceptedCoin`, `startDate`, `endDate`, `minRaiseUSD`, `maxRaiseUSD`, `minInvestment`, `maxInvestment`.
Three field names are commonly guessed and are **not** accepted:
| Not accepted | Use instead |
| -------------------- | --------------------------------------------------------- |
| `totalTokensOffered` | `tokenAmount` — the number of tokens offered |
| `paymentTokenSymbol` | `acceptedCoin` — the payment token symbol, such as `USDT` |
| `tokenPrice` | Nothing. The price is derived, see below. |
A rejected field name currently surfaces as a message about `txId` and transaction values not
matching, rather than naming the field. If you see that message, check your field names against
the list above before anything else.
### There is no token price input
Price is derived as `maxRaiseUSD / tokenAmount`. To offer 50,000 tokens at 1 USD each, send
`tokenAmount: "50000"` and `maxRaiseUSD: "50000"`.
`minRaiseUSD` is the offering's **soft cap**. It decides what happens at the end: an offering that
reaches it can deliver tokens, and one that does not enters rollback and refunds investors instead.
## Timing
Send `startDate` and `endDate` as explicit UTC, with a `Z` suffix — `2026-09-01T00:00:00Z` — or as
a unix timestamp. A timestamp with no offset is read as UTC by the server, so a local-time value
such as `2026-09-01T14:00:00` schedules the offering at a different moment than you intended. Every
`newInvest` in that gap reverts with `IssuanceNotStarted`.
`startDate` is validated against the timestamp of the block that mines the STO transaction. Set it at least 10 minutes after the time you expect to send the transaction, rather than from the prepare time. This buffer covers signing, broadcast, and block inclusion; an elapsed `startDate` makes the transaction revert on-chain.
There is **no minimum offering duration**. A short window is a legitimate way to exercise close and
claim in testing.
## One ongoing offering per token
A token can have only one offering in the `ONGOING` state. Preparing a second returns
`Tokenizer already has an ongoing STO`.
An offering cannot be cancelled, and it cannot be closed before its `endDate` has passed. A
mistake in `newSto` therefore blocks that token until the window elapses. Use a short `endDate`
on test offerings so you can close and recreate quickly.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
Once the offering is live, see [`newInvest`](/api-reference/endpoint/prepare-newInvest), then
[`closeOffer`](/api-reference/endpoint/prepare-closeOffer) and
[`claimTokens`](/api-reference/endpoint/prepare-claimTokens) for the rest of the lifecycle.
# newTokenization
Source: https://docs.brickken.com/api-reference/endpoint/prepare-newTokenization
api-reference/prepare/newTokenization.json POST /prepare-transactions
Prepares the unsigned transactions that deploy a new tokenized asset.
Prepares unsigned transactions for creating a new tokenized asset. Use `POST /prepare-transactions` with `method=newTokenization`.
## Prerequisites
* The required asset-name field is `name`. `tokenName` is not accepted.
* After sending, wait until the tokenization succeeds before using its symbol in `newSto`, `mintToken`, or `whitelist`.
* Use [`GET /get-token-info`](/api-reference/endpoint/get-token-info) to inspect the exact symbols available to the API key.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# transferFrom
Source: https://docs.brickken.com/api-reference/endpoint/prepare-transferFrom
api-reference/prepare/transferFrom.json POST /prepare-transactions
Prepares the unsigned transaction that transfers tokens from an address that approved the signer.
Prepares unsigned transactions for transferring tokens from one address to another (requires prior approval). Use `POST /prepare-transactions` with `method=transferFrom`.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# transferTo
Source: https://docs.brickken.com/api-reference/endpoint/prepare-transferTo
api-reference/prepare/transferTo.json POST /prepare-transactions
Prepares the unsigned transaction that transfers tokens from the signer balance to another address.
Prepares unsigned transactions for transferring tokens from the signer's address to another address. Use `POST /prepare-transactions` with `method=transferTo`.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# whitelist
Source: https://docs.brickken.com/api-reference/endpoint/prepare-whitelist
api-reference/prepare/whitelist.json POST /prepare-transactions
Authorize a wallet to hold a token, creating the investor record if it does not exist.
Prepares unsigned transactions for whitelisting or blacklisting users. Use `POST /prepare-transactions` with `method=whitelist`.
Whitelisting is an on-chain, per-token permission. A wallet must be whitelisted before it can hold or receive that token, which makes this the standalone step to run before a transfer, a resale, or an investment — no minting required.
## Fields
`tokenSymbol`, `signerAddress` (the tokenizer wallet), and `userToWhitelist` are required. Each entry
in `userToWhitelist` needs:
| Field | Required | Notes |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `investorAddress` | yes | The wallet being authorized |
| `investorEmail` | yes | The identity the wallet is attached to |
| `whitelistStatus` | yes | `true` to whitelist, `false` to blacklist |
| `needKyc` | no | Defaults to `true`. `false` creates the investor with no KYC requirement, and is accepted in Sandbox only |
**Testing in Sandbox?** Pass `needKyc: false` and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.
Rehearse the real KYC flow once before you go live, since `needKyc: false` is rejected in
production with `needKyc=false is only available in the sandbox environment`.
An optional `newInvestor` object supplies profile defaults used when a record has to be created:
`name`, `surname`, `middleName`, `secondSurname`, and `type` (defaults to `INVESTOR_PERSON`).
```json theme={null}
{
"method": "whitelist",
"chainId": "aa36a7",
"signerAddress": "0x",
"tokenSymbol": "EXMPL",
"userToWhitelist": [
{
"investorAddress": "0x",
"investorEmail": "investor@example.com",
"whitelistStatus": true,
"needKyc": false
}
],
"newInvestor": { "name": "Jane", "surname": "Doe", "type": "INVESTOR_PERSON" }
}
```
## The investor record
The investor record is created during the **prepare** call, not when the transaction is mined. Two
consequences matter:
The investor's email must not already belong to a tokenizer account. When the email is already
registered, the call still succeeds and whitelists the address on-chain, but no investor record is
added — so `GET /get-balance-whitelist` and `newInvest` both go on reporting `Investor not found`.
Give every test investor its own email, separate from the account you issue with. In a real flow
the issuer and the investor are different parties anyway.
When the investor already exists but has no wallet address on file, whitelisting attaches the
`investorAddress` you pass to that record. An investor whose stored wallet differs from the one you
send is rejected with `Investor is already associated with a different wallet address` — a
wallet address is set once and is not silently replaced.
## Preparing is not sending
Preparing a whitelist only returns an unsigned transaction. The signed transaction must also be
submitted, confirmed on-chain, and processed by the backend before the wallet counts as whitelisted.
Verify the on-chain result before relying on it:
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-whitelist-status?tokenSymbol=EXMPL&address=0x' \
--header 'x-api-key: YOUR_API_KEY'
```
Whitelisting is not KYC. Whitelisting authorizes a **wallet** for one token on-chain; KYC is an
off-chain compliance record for an **investor email**, shared across every asset that investor
touches. Whitelisting a wallet does not approve KYC, and an approved KYC does not whitelist a
wallet.
## Next step
Preparing does not touch the chain. The response gives you `txId` and an array of unsigned `transactions` — you still have to sign and submit them.
Sign each entry locally with the wallet that sends the transaction — `signerAddress`, or `investorAddress` for `newInvest` and `claimTokens`. It must be whitelisted by Brickken, and it needs native gas on the target chain.
`POST` them to [`/send-transactions`](/api-reference/endpoint/send) as `{ txId, signedTransactions }` and Brickken broadcasts for you.
If you would rather broadcast yourself, prepare with `executionMode: "client-broadcast"` and confirm afterwards with `{ txId, txHash }` instead.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. A `pending` status means it is broadcast but not yet mined — do not resubmit.
Full walkthrough: [Tokenize an asset and run an STO](/api-reference/guides/tokenize-and-run-an-sto).
# Check RAMS Execution
Source: https://docs.brickken.com/api-reference/endpoint/rams-can-execute
GET /rams/can-execute
Check whether a mandate currently permits an action and value.
Send `x-api-key`. These reads are also x402-payable: call without a key and, where x402 is enabled for the chain, the API answers `402 Payment Required` with the amount in the `PAYMENT-REQUIRED` header. Reads are priced at the cheaper `GETTER` tier than writes — take the amount from the response rather than from a table.
Provide `chainId`, `agent`, `principal`, `asset`, optional raw `amount`, and either a bytes32 `action` or 4-byte `selector`.
The response combines the authoritative on-chain `canExecute` result with diagnostic checks for lifecycle, freeze, asset, action, transaction cap, cumulative cap, and compliance. Treat the top-level on-chain result as authoritative.
# Check RAMS Compliance
Source: https://docs.brickken.com/api-reference/endpoint/rams-compliance-status
GET /rams/compliance-status
Read a principal eligibility record from a ComplianceProvider.
Send `x-api-key`. These reads are also x402-payable: call without a key and, where x402 is enabled for the chain, the API answers `402 Payment Required` with the amount in the `PAYMENT-REQUIRED` header. Reads are priced at the cheaper `GETTER` tier than writes — take the amount from the response rather than from a table.
Provide `chainId`, `principal`, and the bytes32 `identityRef`; optionally override `complianceProviderAddress`.
The response reports eligibility, expiry, and revocation reason details. A mandate can exist while compliance is ineligible, but `canExecute` will reject it.
# Get RAMS Executor Action
Source: https://docs.brickken.com/api-reference/endpoint/rams-executor-action
GET /rams/executor-action
Return the ActionSpec for a function selector from an AgentExecutor.
Send `x-api-key`. These reads are also x402-payable: call without a key and, where x402 is enabled for the chain, the API answers `402 Payment Required` with the amount in the `PAYMENT-REQUIRED` header. Reads are priced at the cheaper `GETTER` tier than writes — take the amount from the response rather than from a table.
Provide `chainId` and either a 4-byte `selector` or left-aligned bytes32 `action`; optionally override `executorAddress`.
The returned `ActionSpec` contains `supported`, `hasAmount`, and `amountIndex`. The response also includes the executor's principal, owner, and AgentMandate binding. Verify value-bearing selectors have amount extraction enabled before relying on RAMS caps.
# Get RAMS Mandate
Source: https://docs.brickken.com/api-reference/endpoint/rams-get-mandate
GET /rams/mandate
Read an ERC-8226 mandate and its derived lifecycle status.
Send `x-api-key`. These reads are also x402-payable: call without a key and, where x402 is enabled for the chain, the API answers `402 Payment Required` with the amount in the `PAYMENT-REQUIRED` header. Reads are priced at the cheaper `GETTER` tier than writes — take the amount from the response rather than from a table.
Query by `chainId`, `agent`, and `principal`; `agentMandateAddress` is an optional contract override.
The response includes the raw mandate, derived `status` (`none`, `pending`, `active`, `expired`, or `revoked`), agent freeze state, and the principal's current EIP-712 nonce. On-chain read failures are returned as errors and never replaced with defaults.
# RAMS Mandates (ERC-8226)
Source: https://docs.brickken.com/api-reference/endpoint/rams-overview
Compliance-gated, value-capped on-chain mandates that let principals delegate execution authority to AI agents.
## Overview
RAMS (ERC-8226) is Brickken's on-chain **mandate** system: a principal grants an AI agent a delegated, compliance-gated, value-capped authority to act on a specific asset. The mandate lives on the **AgentMandate** registry, eligibility is attested by a **ComplianceProvider**, and executions run through a per-principal **AgentExecutor** that enforces the caps and records usage.
**RAMS runs on Ethereum Sepolia (`11155111`) at launch**, on both sandbox and production. All `/x402/rams/*` prepare facades default to `chainId: "11155111"`.
Every write follows the standard two-step flow: **prepare** (unsigned transaction) → **send** (`POST /send-transactions`), with the x402 charge split evenly between the two. Most RAMS operations require `msg.sender` to hold a specific role, so `signerAddress` must be the role holder itself. The four signed lifecycle operations are the exception: a principal EIP-712 signature authorizes them, so any wallet can send the transaction.
## Actors
| Actor | Who | What they can do |
| ----------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------- |
| **Principal** | Wallet delegating authority | Grant, revoke, extend mandates; approve operators; sign the EIP-712 payloads |
| **Agent** | Wallet acting under the mandate | Send `execute` transactions through the AgentExecutor (`msg.sender` must be the agent) |
| **Operator** | Wallet approved by the principal | Revoke and extend the principal's mandates directly (signatures still come from the principal) |
| **Enforcer** | Holder of `ENFORCER_ROLE` on AgentMandate | Freeze and unfreeze agents |
| **Compliance provider owner** | Owner of the ComplianceProvider contract | Grant and revoke principal eligibility records |
| **Executor owner** | Owner of the AgentExecutor | Register function selectors via `setAction` |
## Mandate lifecycle
```text theme={null}
grantPrincipal (compliance) grantMandate extendMandate
│ │ │
▼ ▼ ▼
eligible ──────────────────► active mandate ──────────► extended validUntil
│ │
freezeAgent ◄─────┼─────► unfreezeAgent │
│ │
▼ ▼
revokeMandate / expiry ──────────► inactive
```
A mandate's derived status is `none → revoked → pending (now < validFrom) → expired (now > validUntil) → active`. Extending preserves `cumulativeUsed` — spent value is **not** reset. Freezing is an enforcement overlay: a frozen agent fails `canExecute` regardless of mandate state.
## Two signing flows
The four lifecycle operations — `grant-mandate`, `revoke-mandate`, `extend-mandate`, `set-operator` — support two modes:
1. **Direct.** The transaction sender authorizes on-chain: the principal (or, for revoke/extend, an approved operator) is `signerAddress`, and `signature` is omitted (encoded as `0x`).
2. **EIP-712 signature.** The principal signs a typed-data payload off-chain (domain `{ name: "RAMS", version: "1" }`, verifying contract = AgentMandate); any wallet can then send the transaction. Fetch the payload from [`GET /rams/typed-data/{operation}`](/api-reference/endpoint/rams-typed-data) and submit the **same parameters and the same `deadline`** with the signature at prepare time.
The per-principal EIP-712 **nonce is shared by all four signed operations** and increments only on signature-verified calls — direct calls do not consume it. Signatures always come from the principal, never the operator.
All other operations (`execute`, `set-executor-action`, `freeze-agent`, `unfreeze-agent`, `grant-principal`, `revoke-principal`) require `signerAddress` to be the role holder itself.
## Actions and caps
* **Actions** are `bytes32` values holding a **left-aligned 4-byte function selector** (Solidity `bytes32(selector)`: the selector in bytes 0–3, zeros after). Everywhere an action is accepted you may pass either the full bytes32 or the bare selector (e.g. `0x23b872dd` for `transferFrom`); the server right-pads selectors to 32 bytes.
* **Caps** (`maxTransactionValue`, `maxCumulativeValue`) are denominated in the asset's **raw base units** — no decimals scaling is applied, because the backend cannot know arbitrary-asset decimals. This intentionally differs from the agent-token operations' human-readable amounts.
* The alias `"max"` / `"unlimited"` (case-insensitive) sets a cap to `2^256-1`, the contract's "no cap" value.
## Executor setup checklist
Before an agent's `execute` can succeed, the operational chain must be set up in this order:
1. Deploy or choose the per-principal **AgentExecutor** (Brickken's Sepolia default is bound to the platform principal).
2. Grant the executor **`RECORDER_ROLE`** on the AgentMandate registry so it can record usage.
3. Register each selector with **`setAction`** ([Set Executor Action](/api-reference/endpoint/x402-rams-set-executor-action)). Registering a value-bearing selector with `hasAmount: false` makes its transfers **bypass the mandate caps**. Always set `hasAmount: true` and the correct `amountIndex` for selectors that move value.
4. The principal calls **`token.approve(executor, …)`** on the asset — the executor moves funds via `transferFrom`, and the token-level allowance is not checked by the mandate.
5. Grant a wallet **`ENFORCER_ROLE`** for freeze/unfreeze. The AgentMandate admin **cannot** be its own enforcer (`AdminEnforcerOverlap`).
6. The compliance provider owner runs [`grant-principal`](/api-reference/endpoint/x402-rams-grant-principal) **before** any `grant-mandate` — an ineligible principal fails the grant pre-check.
The **AgentExecutor is a contract, not a wallet**. It has no private key, and nobody signs "as" the
executor. Calls are signed by the principal, which is the executor's owner, and the executor then
calls the registry on its own behalf. Requesting a private key for an executor address means the
model has been misread.
On the shared Sandbox deployment, Brickken owns the ComplianceProvider and administers the
AgentMandate registry, so steps 2 and 6 cannot be self-served. Send your principal address to
[tech@brickken.com](mailto:tech@brickken.com) and you will be given a dedicated executor bound to
that principal, already holding `RECORDER_ROLE`, together with the `identityRef` registered for you.
Use that exact `identityRef` when granting the mandate. The AgentMandate checks it against the
ComplianceProvider record, and any mismatch makes the principal ineligible.
## Sepolia contracts
| Contract | Address |
| ----------------------------------------- | -------------------------------------------- |
| AgentMandate (registry, EIP-712 verifier) | `0xD68E1bb972cA4EF7F5764FBf6d685a6DfC26778e` |
| ComplianceProvider (Brickken default) | `0xa90D2503D5D9b80ECC27856Ff76F892B8C02f278` |
| AgentExecutor (platform default) | `0xc81949Cf5b52BDc7890Fd5040A9Cd0cdb4B59952` |
Each endpoint accepts an optional override (`agentMandateAddress`, `complianceProviderAddress`, `executorAddress`) when you run your own contracts.
## Endpoint groups
Grant, revoke, extend mandates and manage operators — direct, or authorized with an EIP-712 signature.
Run agent executions through the AgentExecutor, raw calldata or the transferFrom helper.
Inspect mandates, dry-run executions, and fetch EIP-712 payloads to sign.
The x402 fee is split evenly between prepare and send.
# Get RAMS Status
Source: https://docs.brickken.com/api-reference/endpoint/rams-status
GET /rams/status
Read agent freeze state, principal nonce, and operator approval.
Send `x-api-key`. These reads are also x402-payable: call without a key and, where x402 is enabled for the chain, the API answers `402 Payment Required` with the amount in the `PAYMENT-REQUIRED` header. Reads are priced at the cheaper `GETTER` tier than writes — take the amount from the response rather than from a table.
Provide `chainId`, `agent`, and `principal`; optionally pass `operator` to read its approval.
Use the returned nonce only as an observation. Fetch a fresh [typed-data envelope](/api-reference/endpoint/rams-typed-data) immediately before signing because all four signature-based lifecycle operations share and consume the same per-principal nonce.
# RAMS EIP-712 Typed Data
Source: https://docs.brickken.com/api-reference/endpoint/rams-typed-data
GET /rams/typed-data/grant-mandate
Fetch complete typed-data envelopes for signature-authorized RAMS lifecycle operations.
All four API-key authenticated routes return the same envelope shape:
| Operation | Endpoint |
| ------------ | ------------------------------------- |
| Grant | `GET /rams/typed-data/grant-mandate` |
| Revoke | `GET /rams/typed-data/revoke-mandate` |
| Extend | `GET /rams/typed-data/extend-mandate` |
| Set operator | `GET /rams/typed-data/set-operator` |
## Client flow
1. Fetch typed data with the exact operation parameters.
2. Sign the returned `typedData.domain`, `types`, and `message` locally with the principal wallet (`ethers._signTypedData` / `signTypedData`). The API's `types` intentionally omit `EIP712Domain`.
3. Prepare the matching RAMS write using the same parameters, the returned `deadline`, and the signature.
4. Client-sign the returned transaction, then send and settle x402.
The domain is `RAMS` version `1`, and the verifying contract is the selected AgentMandate. The default deadline is one hour; caller-supplied deadlines cannot exceed 30 days.
The nonce is read on-chain and is shared per principal across all four signed operations. Never default it to zero. Direct lifecycle calls do not consume it, but any successful signature-authorized call invalidates other envelopes using the old nonce.
# Send Transactions
Source: https://docs.brickken.com/api-reference/endpoint/send
POST /send-transactions
**Description:** This endpoint submits signed transactions to the blockchain. This endpoint works uniformly for all transaction types prepared using the `/prepare-transactions` endpoint.
**Headers:**
- `x-api-key`: `YOUR_API_KEY` for API-key auth, or `X-Payment` for x402 retries when sending x402-eligible agentic prepared transactions
- `Content-Type`: `application/json`
**Workflow:**
1. **Prepare Transactions**: First, call `/prepare-transactions` with your desired method and parameters
2. **Sign Transactions**: Sign each transaction in the returned `transactions` array using your preferred wallet or signing method
3. **Send Transactions**: Submit the signed transactions along with the `txId` to this endpoint
**Supported Transaction Types:**
This endpoint accepts signed transactions for all methods supported by `/prepare-transactions`:
- `newTokenization` - Create new tokenized assets
- `newSto` - Create Security Token Offerings
- `newInvest` - Make investments in STOs
- `claimTokens` - Claim tokens from completed STOs
- `closeOffer` - Close active STOs
- `mintToken` - Mint additional tokens
- `whitelist` - Manage address whitelist status
- `approve` - Approve token spending
- `burnToken` - Burn tokens
- `transferFrom` - Transfer tokens (with approval)
- `transferTo` - Transfer tokens from signer
- `dividendDistribution` - Distribute dividends
- `newTokenizedAgent` / `agentRegister` - Register ERC-8004 agents
- `agentSetURI`, `agentSetMetadata`, `agentSetWallet` - Maintain ERC-8004 agent profiles
- `agentGiveFeedback`, `agentRevokeFeedback`, `agentAppendFeedbackResponse` - Manage reputation entries
- `agentCreateToken`, `agentMintToken`, `agentBurnToken`, `agentTransferToken`, `agentTransferFromToken`, `agentApproveToken` - Manage agent ERC-20 tokens
x402 can be used only for x402-eligible agentic prepared transactions. Do not mix x402-eligible and API-key-only transactions in the same send batch.
Confirms or broadcasts a prepared transaction. It works uniformly for every transaction type produced by `/prepare-transactions`.
For x402-eligible agentic methods, authenticate with either `x-api-key` or an x402 payment. To pay, omit `x-api-key`, read the `PAYMENT-REQUIRED` header from the `402` response, then retry with `X-PAYMENT`.
## The three execution modes
Which shape you send is decided at **prepare** time by `executionMode`, and the send must match — a mismatch is rejected with `Prepared transaction was not created for … execution`.
| `executionMode` | Who signs | Who broadcasts | You send | Cost split |
| --------------------------- | ------------------ | -------------- | ----------------------------- | -------------------------------- |
| `client-signed` *(default)* | You | Brickken | `txId` + `signedTransactions` | half at prepare, half at send |
| `client-broadcast` | You | **You** | `txId` + `txHash` | half at prepare, half at send |
| `brickken-relayed` | Brickken's relayer | Brickken | `txId` + `transactions` | free prepare, full price at send |
**`client-broadcast`** is for teams that already own their broadcasting: you sign *and* submit the transaction to the chain yourself, then tell Brickken the resulting hash so it can reconcile its record. It works for Dapp API methods as well as agentic ones. `brickken-relayed` is the only mode restricted to x402-eligible agentic methods.
## Parameters
| Parameter | Type | Required | Description |
| -------------------- | ------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `txId` | string \| string\[] | Yes | Transaction ID(s) from the prepare response. An array only in client-signed mode; a single string otherwise. |
| `signedTransactions` | string \| string\[] | client-signed | Signed transaction hex string(s) starting with `0x`. A single string (legacy) or an array matching the format of `txId`. |
| `txHash` | string | client-broadcast | Hash of the transaction you already broadcast. Exactly one, paired with exactly one `txId`. |
| `transactions` | object\[] | brickken-relayed | Exactly one prepared call `{ to, data, value }` returned by prepare. |
> \[!IMPORTANT]
> Send exactly one of `signedTransactions`, `txHash`, or `transactions` — never two. A `brickken-relayed` send requires x402 payment; API keys are not accepted on that path.
## Request Body
### Brickken-relayed (recommended for agentic methods)
```json theme={null}
{
"txId": "0x11769b5c2028a8ed0a3bdc7599e244aee68e2cae80261d8954e44c3b5cb621a4",
"transactions": [
{ "to": "0xRegistry", "data": "0x...", "value": "0x0" }
]
}
```
Pay with the `X-PAYMENT` header. Brickken verifies the payment, signs with its relayer, and broadcasts. The payment is settled only after the operation confirms on-chain.
### Legacy Format (Single Transaction)
```json theme={null}
{
"signedTransactions": "0x02f8b1018203e8843b9aca00850ba43b740082520894742d35cc6634c0532925a3b8d4c9db96c4b4d8b80b844a9059cbb000000000000000000000000456789abcdef...",
"txId": "0x11769b5c2028a8ed0a3bdc7599e244aee68e2cae80261d8954e44c3b5cb621a4"
}
```
### Array Format (Multiple Transactions)
```json theme={null}
{
"signedTransactions": [
"0x02f8b1018203e8843b9aca00850ba43b740082520894742d35cc6634c0532925a3b8d4c9db96c4b4d8b80b844a9059cbb000000000000000000000000456789abcdef..."
],
"txId": [
"0x11769b5c2028a8ed0a3bdc7599e244aee68e2cae80261d8954e44c3b5cb621a4"
]
}
```
### Client-broadcast (you already sent it)
Prepare with `executionMode: "client-broadcast"`, sign and broadcast the transaction with your own infrastructure, then report the hash:
```json theme={null}
{
"txId": "0x11769b5c2028a8ed0a3bdc7599e244aee68e2cae80261d8954e44c3b5cb621a4",
"txHash": "0x9f2c1f4b6e8a3d5c7b0e1a2d4f6c8b0a3e5d7c9f1b3a5c7e9d1f3b5a7c9e1d3f"
}
```
Exactly one `txId` and one `txHash` — arrays are rejected. Brickken reconciles the hash against the prepared record and updates its own state, so the transaction shows up in `get-transaction-status` and in the dApp like any other. Resubmitting the same pair is idempotent.
## Response
### Success Response
```json theme={null}
{
"txHash": "0x1234567890abcdef...",
"status": "pending"
}
```
### Error Response
```json theme={null}
{
"error": {
"code": "INVALID_SIGNATURE",
"message": "Transaction signature is invalid",
"details": {
"transactionIndex": 0,
"expectedSigner": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8b",
"actualSigner": "0x..."
}
}
}
```
## Workflow
**Client-signed**
1. **Prepare**: call `/prepare-transactions` with your method, parameters, and `signerAddress`.
2. **Sign**: sign each transaction in the returned `transactions` array with your wallet.
3. **Send**: submit `signedTransactions` + `txId` to this endpoint (with `X-PAYMENT` for x402 methods).
**Brickken-relayed**
1. **Prepare** (free): call `/prepare-transactions` (or an `/x402/...` facade) with `executionMode: "brickken-relayed"` and omit `signerAddress`.
2. **Send + pay**: submit `transactions` + `txId`, retry with `X-PAYMENT`. Brickken signs and broadcasts; the payment settles only after on-chain confirmation.
A relayed send returns `200` with `status: "confirmed"` once the receipt is in, or `202` with `status: "pending"` if the operation was broadcast but not yet confirmed — in which case poll `/get-transaction-status` rather than resubmitting.
## Supported Transaction Types
This endpoint accepts transactions for all methods supported by `/prepare-transactions`.
**Dapp (API key):** `newTokenization`, `newSto`, `newInvest`, `claimTokens`, `closeOffer`, `mintToken`, `whitelist`, `approve`, `burnToken`, `transferFrom`, `transferTo`, `dividendDistribution`.
**Agentic (x402-eligible):** `agentRegister`, `agentSetURI`, `agentSetMetadata`, `agentSetWallet`, `agentTransferOwnership`, `agentGiveFeedback`, `agentRevokeFeedback`, `agentAppendFeedbackResponse`, `agentCreateToken`, `agentMintToken`, `agentBurnToken`, `agentTransferToken`, `agentTransferFromToken`, `agentApproveToken` (and the legacy `newTokenizedAgent` alias).
## Transaction Status
After submitting transactions, check their status using the `/get-transaction-status` endpoint with the returned transaction hash (`hash`) or the original transaction ID (`txId`) from `/prepare-transactions`. For `brickken-relayed` transactions, no API key is required to poll status.
For x402 sends, the batch must contain only x402-eligible agentic prepared transactions and all transactions must be on the same chain.
## Security Notes
* Always verify transaction details (chain, recipient, token, amount, and the quoted USDC price) before paying or signing.
* Ensure the `txId` matches the one received from `/prepare-transactions`.
* In `client-signed` mode, use secure signing methods and never share or expose private keys in client-side code.
* In `brickken-relayed` mode you sign only the x402 payment authorization; never resubmit or re-pay a `txId` once an operation hash exists — poll status instead.
# Update Token Documentation
Source: https://docs.brickken.com/api-reference/endpoint/update-docs
PATCH /patch-token-docs
**Description:** This endpoint allows you to update token-related documentation and branding materials. It is fully off-chain and does not prepare or require a blockchain transaction.
**Headers:**
- `x-api-key`: `YOUR_API_KEY`
**Request Format:**
This endpoint accepts `multipart/form-data` input, which should include:
- `tokenSymbol` (text)
- `tokenLogotype` (image file) - optional
- `subscriptionAgreement` (PDF file) - optional
- `legalDocs` (PDF file) - optional
**What the endpoint does:**
- The `tokenLogotype` is uploaded to S3.
- The `subscriptionAgreement` and `legalDocs` are uploaded to IPFS.
- The token record (identified by `tokenSymbol`) is then updated with references to the uploaded files.
- No `txId`, transaction payload, or signed transaction is produced.
**Security:**
- You must provide a valid `x-api-key`.
- API key requests do not require `signerAddress`.
## Overview
The `PATCH /patch-token-docs` endpoint allows you to update token-related documentation and branding materials for existing tokens. This endpoint handles file uploads for token logos, subscription agreements, and legal documents.
## Key Features
* **Token Logo Upload**: Upload token logotype images to S3 storage
* **Legal Document Management**: Upload subscription agreements and legal documents to IPFS
* **Multipart Form Data**: Supports file uploads through multipart/form-data format
* **Selective Updates**: All file fields are optional - update only what you need
* **Off-chain Update**: This endpoint does not prepare or require any blockchain transaction
## Request Format
This endpoint accepts `multipart/form-data` with the following fields:
### Required Fields
* **`tokenSymbol`** (string): The symbol of the token being updated
### Optional File Fields
* **`tokenLogotype`** (image file): Logo image for the token (uploaded to S3)
* **`subscriptionAgreement`** (PDF file): Subscription agreement document (uploaded to IPFS)
* **`legalDocs`** (PDF file): Legal documentation (uploaded to IPFS)
## Example Request
```bash theme={null}
curl -X PATCH "https://api.sandbox.brickken.com/patch-token-docs" \
-H "x-api-key: YOUR_API_KEY" \
-F "tokenSymbol=MYTOKEN" \
-F "tokenLogotype=@logo.png" \
-F "subscriptionAgreement=@agreement.pdf" \
-F "legalDocs=@legal.pdf"
```
## Response Format
### Success Response (200)
```json theme={null}
{
"success": true,
"tokenSymbol": "MYTOKEN",
"tokenLogotypeRef": "s3://bucket/path/to/logo.png",
"subscriptionAgreementIpfs": "QmXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
"legalDocsIpfs": "QmYyYyYyYyYyYyYyYyYyYyYyYyYyYyYyYyYyYyYy"
}
```
### Response Fields
| Field | Type | Description |
| --------------------------- | ------- | ----------------------------------------------------- |
| `success` | boolean | Indicates if the operation was successful |
| `tokenSymbol` | string | The token symbol that was updated |
| `tokenLogotypeRef` | string | S3 path reference to the uploaded logo (if provided) |
| `subscriptionAgreementIpfs` | string | IPFS CID for the subscription agreement (if provided) |
| `legalDocsIpfs` | string | IPFS CID for the legal documents (if provided) |
## File Storage Details
### Token Logotype
* **Storage**: Amazon S3
* **Supported Formats**: Image files (PNG, JPG, etc.)
* **Access**: Direct S3 URL reference
* **Use Case**: Token branding and display
### Legal Documents
* **Storage**: IPFS (InterPlanetary File System)
* **Supported Formats**: PDF files
* **Access**: IPFS CID (Content Identifier)
* **Use Case**: Immutable legal document storage
## Security & Authorization
* **API Key Required**: Include your API key in the `x-api-key` header
* **Token Ownership**: You can only update documentation for tokens associated with your account
* **File Validation**: Files are validated for type and size before upload
* **No Transaction Signature**: API key requests do not require `signerAddress`, `txId`, or signed transactions
## Error Handling
### Common Error Responses
**400 Bad Request**
```json theme={null}
{
"message": "tokenSymbol is required"
}
```
**401 Unauthorized**
```json theme={null}
{
"message": "No email found in token. Unauthorized."
}
```
## Use Cases
1. **Brand Updates**: Update token logos for better visual representation
2. **Legal Compliance**: Upload updated subscription agreements and legal documents
3. **Documentation Management**: Maintain current legal and compliance documentation
4. **Token Maintenance**: Keep token information up-to-date post-creation
## Important Notes
* Only the `tokenSymbol` field is required - all file uploads are optional
* Files are processed and uploaded to different storage systems based on their purpose
* IPFS storage ensures immutable document storage for legal compliance
* S3 storage provides fast access for branding materials
* This endpoint is fully off-chain: token logos are uploaded to S3, documents are uploaded to IPFS, and the token database record is updated without preparing a blockchain transaction
* The endpoint validates file types and user permissions before processing uploads
# Give Feedback
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-feedback-give
POST /x402/agent/feedback/give
Prepare ERC-8004 reputation feedback through x402.
Prepares unsigned transactions for submitting ERC-8004 reputation feedback. This facade maps to `agentGiveFeedback`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ----------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `value` | Yes | Feedback value. |
| `valueDecimals` | Yes | Decimal precision used for `value`. |
| `agentUuid` or `agentId` | Usually | Agent identifier receiving feedback. |
| `tag1`, `tag2` | No | Optional feedback tags. |
| `endpoint`, `feedbackURI`, `feedbackHash` | No | Optional context and off-chain feedback references. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Respond to Feedback
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-feedback-respond
POST /x402/agent/feedback/respond
Prepare an ERC-8004 feedback response through x402.
Prepares unsigned transactions for appending a response to an ERC-8004 feedback thread. This facade maps to `agentAppendFeedbackResponse`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `agentId` | Yes | On-chain agent ID. |
| `clientAddress` | Yes | Client wallet associated with the feedback. |
| `feedbackIndex` | Yes | Feedback entry index. |
| `responseURI` | Yes | Off-chain response URI. |
| `responseHash` | No | Optional hash for the response content. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Revoke Feedback
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-feedback-revoke
POST /x402/agent/feedback/revoke
Prepare ERC-8004 feedback revocation through x402.
Prepares unsigned transactions for revoking an ERC-8004 feedback entry. This facade maps to `agentRevokeFeedback`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `agentId` | Yes | On-chain agent ID. |
| `feedbackIndex` | Yes | Feedback entry index to revoke. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Register Agent
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-register
POST /x402/agent/register
Prepare an ERC-8004 agent registration through x402.
Prepares unsigned transactions for registering an ERC-8004 agent identity. This facade maps to `agentRegister`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| -------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia tests. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `name` | Yes | Human-readable agent name. |
| `description` | Yes | Agent description. |
| `image` | Yes | Publicly reachable HTTPS URL for the agent logo. Local paths and omitted values are rejected. |
| `services` | Yes | Non-empty service descriptors such as A2A endpoints. Every entry needs a non-empty `name` and `endpoint`. |
| `aiModelName`, `aiModelProvider` | No | AI model metadata published with the agent profile. |
| `x402Support`, `active` | No | Agent capability and status flags. |
`image` is mandatory. Provide the final public logo URL, or an explicitly authorized test fixture; requests without it fail with `image is required`.
A `400` before the prepare response is a request-validation failure, not an x402-payment failure. Confirm the Base chain ID and all required fields (`name`, `description`, `image`, and valid `services`) before attempting payment.
## Response
Returns prepared unsigned transactions and `txId`. Save `info.agentUuid` from the response for future URI, metadata, wallet, and ownership-transfer updates.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Set Agent Metadata
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-set-metadata
POST /x402/agent/set-metadata
Prepare an ERC-8004 agent metadata update through x402.
Prepares unsigned transactions for writing an ERC-8004 agent metadata key/value pair. This facade maps to `agentSetMetadata`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `agentUuid` or `agentId` | Usually | Agent identifier from registration or the on-chain agent ID. |
| `metadataKey` | No | Metadata key to write. |
| `metadataValue` | No | Metadata value to write. |
| `metadataEncoding` | No | Optional encoding descriptor for the metadata value. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Set Agent URI
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-set-uri
POST /x402/agent/set-uri
Prepare an ERC-8004 agent URI/profile update through x402.
Prepares unsigned transactions for updating an ERC-8004 agent profile URI. This facade maps to `agentSetURI`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ---------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `agentUuid` or `agentId` | Usually | Agent identifier from registration or the on-chain agent ID. |
| `name`, `description`, `image` | No | Profile fields used to build the updated URI metadata. |
| `services`, `metadata`, `tags` | No | Additional agent profile metadata. |
| `documentation`, `sourceCode`, `license` | No | Public agent documentation and source metadata. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Set Agent Wallet
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-set-wallet
POST /x402/agent/set-wallet
Prepare an ERC-8004 operational wallet update through x402.
Prepares unsigned transactions for updating an agent operational wallet. This facade maps to `agentSetWallet`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `newWallet` | Yes | New operational wallet address. |
| `deadline` | Yes | Signature deadline. |
| `signature` | Yes | Authorization signature for the wallet update. |
| `agentUuid` or `agentId` | Usually | Agent identifier from registration or the on-chain agent ID. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Transfer Agent Ownership
Source: https://docs.brickken.com/api-reference/endpoint/x402-agent-transfer-ownership
POST /x402/agent/transfer-ownership
Prepare an ERC-8004 identity ownership transfer through x402.
Prepares an unsigned ERC-721 `safeTransferFrom` that moves an ERC-8004 agent identity from Brickken custody to a wallet you control. This facade maps to `agentTransferOwnership`.
Call this method when you want to move custody of the identity NFT to another owner.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `newOwner` | Yes | Wallet that will receive the ERC-8004 identity NFT. Must differ from the current owner. |
| `agentUuid` or `agentId` | Usually | Agent identifier from registration or the on-chain agent ID. The agent must already be registered on-chain. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. It must be the current owner. |
## Response
Returns a prepared unsigned transaction and `txId`. Submit it to `POST /send-transactions` and complete the x402 payment.
* **`client-signed`:** sign the transaction locally as the current owner, then send `{ txId, signedTransactions }`.
Ownership transfer is **irreversible** and is different from [`agentSetWallet`](/api-reference/endpoint/x402-agent-set-wallet), which only changes the operational wallet. After the transfer, only the new owner can perform owner-only operations for that agent.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Execute RAMS Action
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-execute
POST /x402/rams/execute
Prepare an agent action through the principal-bound AgentExecutor.
Maps to `ramsExecute`. `signerAddress` must be the mandate's **agent**.
This operation is always client-signed: the AgentExecutor checks `msg.sender` against the mandated agent.
## Input modes
| Mode | Fields |
| ------------- | --------------------------------------------------------------------------------- |
| Raw | `target` and full inner `data` calldata |
| ERC-20 helper | `asset`, `from`, `to`, and raw base-unit `amount`; the API encodes `transferFrom` |
Exactly one mode is accepted. The API reads the selector registration, derives any cap-gated amount, and simulates mandate authorization before returning the unsigned executor transaction.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Extend RAMS Mandate
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-extend-mandate
POST /x402/rams/extend-mandate
Prepare a later expiry for an active ERC-8226 mandate.
Maps to `ramsExtendMandate`. `newValidUntil` must exceed the current expiry; extending does not reset `cumulativeUsed`.
## Authorization modes
| Mode | Authorization |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Direct | `signerAddress` is the principal or an approved operator |
| Principal signature | Any sender supplies `signature` and the same `deadline` returned by [Typed Data](/api-reference/endpoint/rams-typed-data) |
Preparing charges half of the operation price; the rest is collected when the prepared transaction is sent.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Freeze RAMS Agent
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-freeze-agent
POST /x402/rams/freeze-agent
Prepare an enforcement freeze for an ERC-8226 agent.
Maps to `ramsFreezeAgent`. `signerAddress` must hold `ENFORCER_ROLE` on AgentMandate. It is always client-signed and freezes the agent across all mandates in that registry.
The AgentMandate admin cannot also be its enforcer (`AdminEnforcerOverlap`). Use a distinct operational wallet.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Grant RAMS Mandate
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-grant-mandate
POST /x402/rams/grant-mandate
Prepare a compliance-gated ERC-8226 mandate, directly or with a principal EIP-712 signature.
Maps to `ramsGrantMandate`. The principal must already be eligible with the selected ComplianceProvider.
## Authorization modes
| Mode | `signerAddress` | Signature fields |
| ------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| Direct | Principal | Omit `signature`; the transaction encodes `0x` |
| Principal signature | Any transaction sender/relayer | `signature` and the same `deadline` returned by [Typed Data](/api-reference/endpoint/rams-typed-data) |
## Key fields
`agent`, `principal`, `validUntil`, `identityRef`, `asset`, both value caps, and at least one `actions` entry are required. `validFrom` defaults to immediate. Values are raw base units; caps accept `max`/`unlimited`. Actions accept bytes32 values or 4-byte selectors.
## Response
Returns `txId`, unsigned `transactions`, and `info` with the contract, authorization `mode`, and EIP-712 nonce when applicable. The x402 charge is split evenly between prepare and send.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Grant RAMS Principal Eligibility
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-grant-principal
POST /x402/rams/grant-principal
Prepare a compliance eligibility record for a principal.
Maps to `ramsGrantPrincipal`. `signerAddress` must be the ComplianceProvider owner; this admin operation is always client-signed.
Provide the `principal`, a non-zero bytes32 `identityRef`, and optional `expiresAt` (`0` means no expiry). This must be completed before granting a mandate that references the same provider and identity.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Revoke RAMS Mandate
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-revoke-mandate
POST /x402/rams/revoke-mandate
Prepare revocation of an ERC-8226 mandate.
Maps to `ramsRevokeMandate` for an `agent` / `principal` pair.
## Authorization modes
| Mode | Authorization |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Direct | `signerAddress` is the principal or an approved operator |
| Principal signature | Any sender supplies `signature` and the matching `deadline` from [Typed Data](/api-reference/endpoint/rams-typed-data) |
The API preflights that the mandate is active. The response contains the unsigned transaction and `info.mode`; pay x402 only when sending.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Revoke RAMS Principal Eligibility
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-revoke-principal
POST /x402/rams/revoke-principal
Prepare revocation of a principal compliance record.
Maps to `ramsRevokePrincipal`. `signerAddress` must be the ComplianceProvider owner; this admin operation is always client-signed.
`reason` accepts a numeric code `0–8` or a name such as `KYC_EXPIRED`, `AML_FLAG`, `JURISDICTION_BLOCKED`, or `OTHER`. Revocation makes mandate execution fail its compliance check; it does not rewrite the mandate record.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Set RAMS Executor Action
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-set-executor-action
POST /x402/rams/set-executor-action
Register or update the ActionSpec for a function selector on an AgentExecutor.
Maps to `ramsSetExecutorAction`. `signerAddress` must be the AgentExecutor owner; the operation is always client-signed.
Pass either `selector` (4 bytes) or its left-aligned bytes32 `action`, then set the `ActionSpec` fields: `supported`, `hasAmount`, and `amountIndex` when the action carries value.
Registering a value-bearing selector with `hasAmount: false` bypasses mandate transaction and cumulative caps. Use the correct zero-based ABI word index.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Set RAMS Operator
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-set-operator
POST /x402/rams/set-operator
Approve or remove an operator for an ERC-8226 principal.
Maps to `ramsSetOperator`. Set `approved` to `true` or `false`.
## Authorization modes
| Mode | Authorization |
| ------------------- | ------------------------------------------------------------------------------------------------------------- |
| Direct | `signerAddress` is the principal |
| Principal signature | Any sender supplies `signature` and matching [typed-data](/api-reference/endpoint/rams-typed-data) `deadline` |
An operator may directly revoke or extend mandates, but EIP-712 lifecycle signatures always recover to the principal.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Unfreeze RAMS Agent
Source: https://docs.brickken.com/api-reference/endpoint/x402-rams-unfreeze-agent
POST /x402/rams/unfreeze-agent
Prepare removal of an enforcement freeze from an ERC-8226 agent.
Maps to `ramsUnfreezeAgent`. `signerAddress` must hold `ENFORCER_ROLE`.
Unfreezing removes the global overlay but does not reactivate revoked or expired mandates.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Approve Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-approve
POST /x402/token/approve
Prepare an agent-owned ERC-20 allowance approval through x402.
Prepares unsigned transactions for approving an agent-owned ERC-20 token allowance. This facade maps to `agentApproveToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| ---------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `tokenAddress` | Yes | Agent token contract address. |
| `spenderAddress` | Yes | Wallet approved to spend tokens. |
| `amount` | Yes | Human-readable allowance amount. |
| `decimals` | No | Token decimals used to normalize `amount`. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Burn Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-burn
POST /x402/token/burn
Prepare an agent-owned ERC-20 burn through x402.
Prepares unsigned transactions for burning an agent-owned ERC-20 token. This facade maps to `agentBurnToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `tokenAddress` | Yes | Agent token contract address. |
| `from` | Yes | Wallet whose tokens are burned. |
| `amount` | Yes | Human-readable amount to burn. |
| `decimals` | No | Token decimals used to normalize `amount`. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Create Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-create
POST /x402/token/create
Prepare an agent-owned ERC-20 token deployment through x402.
Prepares unsigned transactions for deploying an agent-owned ERC-20 token. This facade maps to `agentCreateToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `name` | Yes | Token name. |
| `symbol` | Yes | Token symbol. |
| `agentWallet` | Yes | Agent wallet that owns or operates the token. |
| `premint` | No | Optional initial token amount. |
| `decimals` | No | Optional token decimals. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`. Use the deployment receipt to recover the deployed `tokenAddress`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Mint Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-mint
POST /x402/token/mint
Prepare an agent-owned ERC-20 mint through x402.
Prepares unsigned transactions for minting an agent-owned ERC-20 token. This facade maps to `agentMintToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `tokenAddress` | Yes | Agent token contract address. |
| `to` | Yes | Recipient wallet. |
| `amount` | Yes | Human-readable amount to mint. |
| `decimals` | No | Token decimals used to normalize `amount`. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Transfer Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-transfer
POST /x402/token/transfer
Prepare an agent-owned ERC-20 transfer through x402.
Prepares unsigned transactions for transferring an agent-owned ERC-20 token. This facade maps to `agentTransferToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `tokenAddress` | Yes | Agent token contract address. |
| `to` | Yes | Recipient wallet. |
| `amount` | Yes | Human-readable amount to transfer. |
| `decimals` | No | Token decimals used to normalize `amount`. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Transfer From Agent Token
Source: https://docs.brickken.com/api-reference/endpoint/x402-token-transfer-from
POST /x402/token/transfer-from
Prepare an agent-owned ERC-20 allowance transfer through x402.
Prepares unsigned transactions for transferring an agent-owned ERC-20 token through allowance. This facade maps to `agentTransferFromToken`.
## Authentication
Preparing charges the first half of the operation price, and `POST /send-transactions` charges the rest. Each paid call answers `402 Payment Required` with a `PAYMENT-REQUIRED` header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with `X-PAYMENT`.
A valid `x-api-key` is accepted instead of paying, on both steps.
See [Authentication](/get-started/authentication) for the full credential matrix.
## Key Fields
| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `chainId` | Yes | Target chain ID. Use `8453` for Base mainnet or `84532` for Base Sepolia. Decimal and hex values are accepted. |
| `executionMode` | No | `client-signed` (default) or `client-broadcast`. |
| `signerAddress` | Yes | Wallet that signs the prepared transaction. |
| `tokenAddress` | Yes | Agent token contract address. |
| `from` | Yes | Source wallet. |
| `to` | Yes | Recipient wallet. |
| `amount` | Yes | Human-readable amount to transfer. |
| `decimals` | No | Token decimals used to normalize `amount`. |
## Response
Returns prepared unsigned transactions and `txId`. Sign the transaction locally and submit it to `POST /send-transactions` as `{ txId, signedTransactions }`.
## Next step
Preparing does not touch the chain. The response gives you `txId`, the unsigned `transactions`, and an `x402Requirements` quote.
`client-signed` (the default) — you sign the transaction and Brickken broadcasts it. `client-broadcast` — you sign and broadcast it yourself, then confirm with `txHash`. Either way the operation price is split evenly: half at prepare, half at send.
`POST` to [`/send-transactions`](/api-reference/endpoint/send). The first attempt answers `402 Payment Required`; read `PAYMENT-REQUIRED`, sign the payment locally, and retry with `X-PAYMENT`. An `x-api-key` is accepted here instead of paying.
Call [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) with the `txId`. Your payment settles only after the operation confirms, and is released if it reverts.
See [Authentication](/get-started/authentication) for the payment handshake and [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation cost.
# Browser wallets
Source: https://docs.brickken.com/api-reference/guides/browser-wallets
Send a prepared transaction from MetaMask or another injected wallet without breaking on its parameter validator.
`POST /prepare-transactions` returns **ethers-style unsigned transactions**. They are built to be
passed to `wallet.signTransaction()` and submitted through
[`POST /send-transactions`](/api-reference/endpoint/send).
They are **not** EIP-1193 payloads. Handing one straight to `eth_sendTransaction` fails, and the
way it fails is misleading.
## Why it fails, and why every wallet fails differently
A prepared transaction looks like this:
```json theme={null}
{
"from": "0xfd1cbe1783ca6ed03412be9cdf7b7842f8567f81",
"to": "0x28d2B01854D0aBec267a3DDcad9163580E6E8604",
"value": "0x00",
"nonce": 51,
"chainId": 11155111,
"data": "0x095ea7b3...",
"type": 2,
"maxPriorityFeePerGas": "1150000",
"maxFeePerGas": "1209073256",
"gasLimit": "0xc920"
}
```
Four things break an injected provider:
* `nonce`, `chainId`, and `type` are **numbers**; EIP-1193 requires hex strings.
* `maxPriorityFeePerGas` and `maxFeePerGas` are **decimal strings** without a `0x` prefix.
* The gas key is `gasLimit`; `eth_sendTransaction` expects `gas`.
* `from` is the wallet the API prepared for, which may not be the account the user connected.
Each wallet validates parameters in its own code, so each one throws a different generic error from
inside its own validator — `Internal JSON-RPC error`, `e.startsWith is not a function`, `undefined
is not a function`. These errors are not coming from your application, and the differences between
them mean nothing. They are all the same malformed payload.
## Normalise before sending
Convert the numeric fields to hex, rename `gasLimit` to `gas`, and let the wallet supply the nonce
and the gas fees itself.
```js theme={null}
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0xaa36a7' }], // Ethereum Sepolia
});
const [raw] = response.transactions;
const hex = (value) => '0x' + BigInt(value).toString(16);
const txHash = await window.ethereum.request({
method: 'eth_sendTransaction',
params: [{
from: account,
to: raw.to,
data: raw.data,
value: hex(raw.value ?? 0),
gas: hex(raw.gasLimit),
// Omit nonce, chainId, type and the gas fees — the wallet fills them in.
}],
});
```
This sends the first transaction only. Some responses carry more than one — see
[Multi-transaction responses](#multi-transaction-responses) below — so iterate rather than
assuming a single entry.
Switch the chain before sending. A wallet pointed at a different network will either reject the
call or, worse, prompt the user to sign against the wrong chain.
## Report the hash back
`eth_sendTransaction` broadcasts the transaction itself, so the wallet returns a real transaction
hash rather than the `txId` from the prepare step. Close the loop by telling Brickken which hash
corresponds to which prepared transaction, using the `client-broadcast` execution mode:
```bash theme={null}
curl --request POST \
--url 'https://api.sandbox.brickken.com/send-transactions' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"txId": "0x6eaf02ca...",
"txHash": "0x9ac676fc..."
}'
```
Prepare with `"executionMode": "client-broadcast"` when you intend to broadcast from the wallet, so
the prepared transaction is recorded for that mode. See
[Send Transactions](/api-reference/endpoint/send) for all three execution modes.
## MetaMask error 4100
`4100 — The requested account and/or method has not been authorized by the user` means `from` is
not an account the user has connected.
The transaction must be signed by the wallet that actually holds the asset — the token holder for a
transfer, the investor for `newInvest` and `claimTokens`, the issuer for issuance operations. If
that wallet can differ from the connected one in your application, check them and ask the user to
switch rather than letting the wallet reject the request.
If the signing wallet is a Brickken-managed wallet, no injected wallet can sign for it at all,
because the browser does not hold its key. Those flows must go through
[`POST /send-transactions`](/api-reference/endpoint/send) with a locally signed transaction
instead.
## Multi-transaction responses
Some responses contain more than one transaction — `approve` when an existing allowance has to be
reset first, and `mintToken` when a recipient still needs whitelisting. Prepared transactions carry
sequential nonces, so they must be signed and broadcast **in order**, each one confirmed before the
next.
Broadcasting only the second transaction leaves it stranded on a nonce that will never be used,
and it silently never mines. If a later call reports a balance or a token that "should" exist,
this is usually why.
Execution modes and submission shapes.
Decode a failed call.
# Tokenize an asset and run an STO
Source: https://docs.brickken.com/api-reference/guides/tokenize-and-run-an-sto
The full Dapp API lifecycle, from creating a token to distributing dividends.
Every step below is the same three moves: **prepare** an unsigned transaction, **sign** it with your whitelisted wallet, **send** it. The examples target Sepolia (`aa36a7`) on sandbox, so nothing here moves real value.
## Before you start
[Request one](/get-started/request-api-key). Every call below needs `x-api-key`.
Brickken registers the wallet you pass as `signerAddress` in the factory. Include that address in
your API key request. If you did not, or you want to use a different wallet, send it to
[tech@brickken.com](mailto:tech@brickken.com) — there is nothing for you to do on-chain, and no
separate whitelist call to make.
You broadcast the transactions, so the signer pays the gas — Sepolia ETH here.
The wallet that performs the first `newTokenization` becomes the **tokenizer** for that token. Only the tokenizer can mint it, whitelist its investors, or distribute its dividends. Transfers and burns can come from any wallet. Your API key is also scoped to the symbols it tokenized — anything else returns `Unauthorized token symbol`.
## The sign-and-send loop
You will repeat this after every prepare, so it is worth writing once. Prepare returns `{ txId, transactions }`:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"txId": "0xPreparedTransactionId",
"signedTransactions": ["0xSignedRawTransaction"]
}'
```
Signing, with ethers:
```ts theme={null}
import { Wallet } from "ethers";
const wallet = new Wallet(process.env.PRIVATE_KEY!);
const signedTransactions = await Promise.all(
prepared.transactions.map((tx) => wallet.signTransaction(tx))
);
```
Then poll until it confirms:
```bash theme={null}
curl 'https://api.sandbox.brickken.com/get-transaction-status?txId=0xPreparedTransactionId' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY'
```
`pending` means broadcast but not yet mined. Do not resubmit — you would pay gas twice.
Treat every successful transaction as a dependency boundary. Before preparing `newSto`, `mintToken`, or `whitelist`, poll the preceding `newTokenization` until it succeeds. A send response only means the transaction was broadcast; a reverted receipt does not create the token record used by later methods.
**Already run your own broadcasting?** Add `"executionMode": "client-broadcast"` to any prepare below, submit the signed transaction to the chain yourself, then confirm with `{ txId, txHash }` instead of `{ txId, signedTransactions }`. Brickken reconciles your hash so the transaction still appears in `get-transaction-status` and in the dApp. See [Send Transactions](/api-reference/endpoint/send).
## 1. Create the tokenized asset
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "newTokenization",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenizerEmail": "issuer@example.com",
"name": "Example Asset",
"tokenSymbol": "EXMPL",
"tokenType": "EQUITY",
"supplyCap": "1000000",
"url": "https://example.com/token-docs"
}'
```
The field is `name`, not `tokenName`. `tokenType` accepts `EQUITY`, `DEBT`, `BILL_FACTORING`, `ICO`, `STABLECOIN`, `REVENUE_SHARE`, `RWA_TOKEN`, or `PROFIT_SHARING`, and defaults to `EQUITY`. `supplyCap` defaults to `0`, which means uncapped — set it deliberately.
Sign and send, then confirm the token exists. The endpoint lists all symbols available to your API key; use the exact confirmed symbol in every later request.
```bash theme={null}
curl 'https://api.sandbox.brickken.com/get-token-info' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY'
```
Every field, with the request and response schema, is on the [`newTokenization` reference](/api-reference/endpoint/prepare-newTokenization).
## 2. Whitelist your investors
**Testing in Sandbox?** Pass `needKyc: false` and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.
Rehearse the real KYC flow once before you go live, since `needKyc: false` is rejected in
production with `needKyc=false is only available in the sandbox environment`.
A security token only moves between whitelisted wallets. Whitelist before you mint or accept investment.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "whitelist",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"userToWhitelist": [
{
"investorAddress": "0x1111111111111111111111111111111111111111",
"investorEmail": "investor@example.com",
"whitelistStatus": true
}
]
}'
```
`whitelistStatus: false` removes an investor. Verify with [`GET /get-whitelist-status`](/api-reference/endpoint/get-whitelist-status).
## 3. Mint tokens
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "mintToken",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"userToMint": [
{
"investorEmail": "investor@example.com",
"investorAddress": "0x1111111111111111111111111111111111111111",
"amount": "100",
"needWhitelist": true
}
]
}'
```
`needWhitelist: true` whitelists the recipient as part of the same mint, which collapses step 2 into step 3 when you are onboarding a new investor.
`investorEmail` must identify an investor distinct from the asset's `tokenizerEmail`. Do not use the issuer/tokenizer email as the mint recipient: it can conflict with the issuer account in the investor records. The recipient may use the same wallet address as the tokenizer for sandbox testing; only the email identities must differ. `needWhitelist` controls the whitelist sub-step and does not change this identity rule.
## 4. Launch the offering
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "newSto",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenizerEmail": "issuer@example.com",
"tokenSymbol": "EXMPL",
"tokenAmount": "1000",
"offeringName": "Series A",
"startDate": "2026-09-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"acceptedCoin": "USDT",
"minRaiseUSD": "10000",
"maxRaiseUSD": "100000",
"minInvestment": "100",
"maxInvestment": "10000"
}'
```
Every one of those fields is required. `acceptedCoin` is a payment token symbol — `USDT`, `USDC`, or
`BKN` — and `minRaiseUSD` is the offering's soft cap.
There is no `tokenPrice` field: the price is derived as `maxRaiseUSD / tokenAmount`. `tokenAmount`,
not `totalTokensOffered`, is the supply on offer, and the payment token field is `acceptedCoin`, not
`paymentTokenSymbol` — those three wrong names are the most common cause of a rejected `newSto`.
Send both dates as explicit UTC, with the `Z` suffix shown above, or as a unix timestamp. A timestamp
with no offset is read as UTC by the server, so a local-time value schedules the offering at a
different moment than you intended, and every investment in that gap reverts with
`IssuanceNotStarted`.
`startDate` is checked against the block timestamp when the STO transaction is mined, not when you prepare it. Set it at least 10 minutes after the time you expect to call `send-transactions`, then sign and broadcast promptly. A date that has elapsed while signing, sending, or waiting for inclusion causes the transaction to revert even when prepare and send succeeded.
Once it is live, list your offerings and keep the `uuid`:
```bash theme={null}
curl 'https://api.sandbox.brickken.com/get-stos?chainId=aa36a7&tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY'
```
## 5. Take an investment
Note there is no `signerAddress` in the required set — the **investor** signs this one, not the tokenizer.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "newInvest",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"investorEmail": "investor@example.com",
"investorAddress": "0x1111111111111111111111111111111111111111",
"investmentAmount": "1000",
"paymentTokenSymbol": "USDT"
}'
```
`newInvest` prepares the investment transaction only. Before calling it, the investor must already
have a whitelisted wallet, the payment token in that wallet, and an allowance towards **this
offering's** `escrowAddress` — prepared separately with
[`approve`](/api-reference/endpoint/prepare-approve) and confirmed on-chain. Allowances are per
spender, so an allowance granted for another offering does not count.
The whitelist and the allowance are enforced by the contract, not by an API precondition check, so
a missing one comes back as a revert rather than a readable message. See
[Troubleshooting](/api-reference/guides/troubleshooting).
Track progress with [`GET /get-investments-by-sto-id`](/api-reference/endpoint/get-investments-by-sto) and [`GET /get-sto-balance`](/api-reference/endpoint/get-sto-balance).
## 6. Close the offering
An offering can only be closed once its `endDate` has passed — there is no early close and no
override. Closing finalizes the issuance, which is what unlocks claiming.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "closeOffer",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"tokenizerEmail": "issuer@example.com"
}'
```
If the raise reached `minRaiseUSD`, the offering is successful and investors receive tokens. If it
did not, the issuance enters rollback and investors are refunded instead.
## 7. Let investors claim their tokens
Only after the offering has been finalized. The investor signs this one.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "claimTokens",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"investorEmail": "investor@example.com",
"investorAddress": "0x1111111111111111111111111111111111111111"
}'
```
The same call refunds the payment token instead of releasing tokens when the offering rolled back.
## 8. Distribute dividends
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"method": "dividendDistribution",
"signerAddress": "0xYourWhitelistedWallet",
"chainId": "aa36a7",
"tokenSymbol": "EXMPL",
"amount": "1000"
}'
```
Only the tokenizer can do this. Read the result with [`GET /get-dividend-distribution`](/api-reference/endpoint/get-dividend-distribution).
## When something fails
| Response | What it means |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `401` / `400 API key is missing` | No `x-api-key`, or this endpoint needs one and did not get it |
| `Unauthorized token symbol` | Your key did not tokenize that symbol |
| `Out of credits for ` | Your plan's balance for that specific method is exhausted |
| `429` + `Retry-After: 60` | Rate limited on `prepare-transactions` |
| Prepare rejects your `signerAddress` | It is not a valid EVM address, or not the wallet associated with that asset. An API key does not require a separately whitelisted signer address |
| `No company found with this token symbol` | The symbol is not a successfully confirmed asset on that chain; inspect `GET /get-token-info` and use the exact symbol it lists |
| Mint returns a uniqueness conflict | The recipient email is already the asset's tokenizer email; use a distinct `investorEmail` |
| `newSto` reverts after send | `startDate` became past or too close by the mined block; retry with at least a 10-minute send-time buffer |
| Send reverts on-chain | Usually an unwhitelisted recipient, an unapproved allowance, or no gas |
| `Tokenizer already has an ongoing STO` | A token can have only one ongoing offering; wait for it to end |
| `newInvest` reverts with `IssuanceNotStarted` | The offering has not opened. Send `startDate` as explicit UTC with a `Z` suffix |
| `newInvest` reverts with panic `0x11` | Zero allowance to *this* offering's escrow, or not enough payment token |
| `closeOffer` reverts with `IssuanceNotEnded` | The `endDate` has not passed. There is no early close |
| `claimTokens` reverts with `IssuanceNotInRollback` | The offering has not been finalized; run `closeOffer` first |
| `Insufficient allowance to distribute dividends` | Approve the **payment token**, with the **security-token address** as spender |
Each write method has its own credit balance, so exhausting `mintCredits` does not block `newSto`. See [Authentication](/get-started/authentication) for plans, scoping, and the full error reference.
For decoding raw revert data and the full symptom-to-cause list, see
[Troubleshooting](/api-reference/guides/troubleshooting).
## Doing this without writing HTTP
The same lifecycle as agent tools — `create_tokenization`, `create_sto`, `mint_tokens` — driven by an AI agent with just your API key.
Every request above, ready to run.
# Troubleshooting
Source: https://docs.brickken.com/api-reference/guides/troubleshooting
Decode a failed Dapp API call, from HTTP validation errors to raw on-chain revert data.
Most failures against the Dapp API come from one of a small number of causes. This page tells you
which layer failed, what the message actually means, and what to change.
## Which layer failed
A `POST /prepare-transactions` call passes through three checks, in this order. Knowing which one
rejected you narrows the cause immediately.
Field names, types, and formats. Returns `400` with a message naming the field, such as
`tokenAmount is required`. Nothing was read from the chain and nothing was created.
Balances, allowances, credits, and identity lookups the API performs itself. Returns `400`
with a business message, such as `Insufficient allowance to distribute dividends`. Still no
transaction was broadcast.
The API simulates the transaction against live chain state. If the contract would revert, the
simulation reverts and the raw revert data is returned to you. **The transaction never left
Brickken** — this is a simulated revert, not a failed broadcast.
A **contract revert is always a chain-state problem** — a timestamp, an allowance, a balance, a
whitelist entry, or the offering's lifecycle stage. It is never a compliance verdict. Compliance
is checked in the preflight layer, before the chain is simulated, so a KYC problem always reaches
you as a plain `400` naming it rather than as revert data.
## Decoding a revert
Revert data is a hex string. The first 4 bytes are the error selector; everything after is the
ABI-encoded arguments, one 32-byte word each.
```text theme={null}
0x3ecda1e8 000000000000000000000000c540a73f578d677dda60a5f5a1899459d6787209
└─ selector ┘└─────────────────── argument 1: an address ──────────────────┘
```
An address argument is the last 20 bytes of its word. A small integer is the whole word read as a
number.
### Selectors you are likely to see
| Selector | Error | What it means |
| ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `0x3ecda1e8` | `IssuanceNotStarted(address)` | The offering's `startDate` is still in the future. The address is the issuance's issuer as recorded on-chain — it is **not** a verdict on your investor wallet. |
| `0xffac9d14` | `IssuanceNotEnded(address,uint256)` | The offering's `endDate` has not passed yet, so it cannot be closed. |
| `0x04c7a3b1` | `IssuanceNotInRollback(uint256)` | The issuance has not been finalised. The argument is the issuance index. |
| `0xaafefe9b` | `UserIsNotWhitelisted(address)` | The address in the argument is not whitelisted for this token. |
| `0x418f5699` | `InitialValueWrong(address)` | The escrow rejected the offering parameters or the caller's state for this operation. Check the offering fields you submitted and that the signer is the asset's issuer. |
| `0x4e487b71` | `Panic(uint256)` | A Solidity panic. See below. |
Selectors are the first 4 bytes of the keccak-256 hash of the error's canonical signature, so an
overload with different arguments is a **different** selector. `IssuanceNotStarted(address)` and
`IssuanceNotStarted(address,uint256)` do not decode interchangeably.
### Solidity panics
A panic is not a custom error. It always arrives as selector `0x4e487b71` followed by a code word:
```text theme={null}
0x4e487b71 0000000000000000000000000000000000000000000000000000000000000011
└─ 0x11
```
Code `0x11` is **arithmetic overflow or underflow**. On `newInvest` it almost always means the
payment token is being asked to subtract more than the wallet holds, or to pull against an
allowance that is zero. Check the balance and the allowance for *this* offering's escrow before
looking anywhere else.
Some reverts arrive as `execution reverted: Address: low-level delegate call failed`. That is
OpenZeppelin's message when an inner call reverts with no reason string; the real reason has been
swallowed by a proxy wrapper. Retry once, and if it persists send the exact request body to
[tech@brickken.com](mailto:tech@brickken.com) so the call can be replayed directly.
## Symptom to cause
### Offerings
| Symptom | Cause | Fix |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `newSto` returns a message about `txId` and transaction values not matching | A validation error was masked by a response-shape check — usually a field name `newSto` does not accept | Use `tokenAmount` (not `totalTokensOffered`), `acceptedCoin` (not `paymentTokenSymbol`), and drop `tokenPrice`. See [`newSto`](/api-reference/endpoint/prepare-newSto). |
| `newSto` returns `Tokenizer already has an ongoing STO` | An offering for this token is already `ONGOING` | Only one ongoing offering per token. Wait for it to end and close it, or use a different token. |
| `newInvest` reverts with `IssuanceNotStarted` | The offering has not opened yet | Send `startDate` as explicit UTC with a `Z` suffix. A timestamp with no offset is read as UTC, so a local-time value opens the offering later than you intended. |
| `closeOffer` reverts with `IssuanceNotEnded` | The offering's `endDate` has not passed | Wait for the window to close. There is **no** minimum offering duration, so a short test offering is a valid way to exercise the flow. |
| `claimTokens` reverts with `IssuanceNotInRollback` | The issuance has not been finalised | Close the offering first. See the [lifecycle](#offering-lifecycle) below. |
### Payments and allowances
| Symptom | Cause | Fix |
| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `newInvest` reverts with panic `0x11` | Zero allowance to this offering's escrow, or not enough payment token in the wallet | Approvals are **spender-specific** — approving one offering's escrow does not approve another's. Approve this escrow, and confirm the wallet balance covers the amount. |
| `dividendDistribution` returns `Insufficient allowance to distribute dividends` | The allowance was granted on the wrong token, or to the wrong spender | Approve the **payment token**, with the **security-token address** as spender. See [`approve`](/api-reference/endpoint/prepare-approve). |
| `approve` returns `Missing spender address parameter` | The field was sent as `spender` | The field is `spenderAddress`. |
| `approve` rejects `spenderAddress` as invalid | A malformed address | Usually a leading or trailing space from a copied value or an environment variable, or a bad EIP-55 checksum. Trim it, or send it all lowercase. |
| `approve` reverts with empty revert data (`"data": "0x"`) | The token refuses a non-zero to non-zero allowance change | Set the allowance to `0`, wait for that transaction to confirm, then approve the new amount. If the existing allowance is already enough, skip the approval entirely. |
### Tokens and investors
| Symptom | Cause | Fix |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `burnToken` returns `Insufficient token balance` although the investor holds the tokens | `burnToken` burns the **signer's** balance | `investorEmail` is a bookkeeping label; it does not select whose tokens are burned. See [`burnToken`](/api-reference/endpoint/prepare-burnToken). |
| A later call reports the token or balance does not exist, although a transaction confirmed | An earlier transaction in a multi-transaction response was never broadcast | When `transactions` holds more than one entry, sign and send **all of them, in order**. Skipping the first leaves the rest on an unusable nonce. |
| `Investor not found`, or `get-balance-whitelist` does not recognise the investor | The investor email is the same as a tokenizer account | An email already registered as a tokenizer cannot also be onboarded as an investor. Give the investor its own email. |
| `investorEmail cannot be the tokenizer email (index N)` | Same cause, reported at mint time | Use a distinct `investorEmail` for entry `N` of `userToMint`. |
| `No company found with this token symbol` right after a confirmed tokenization | The next call was made before backend finalisation completed | Poll `GET /get-transaction-status` until `success`, then confirm the symbol with `GET /get-token-info` before preparing the next operation. |
| `Mint credit limit exceeded` / `Invitation credit limit exceeded` | Two separate license counters: mint recipients, and invitations for never-seen emails | These are account limits with no public reset endpoint. Contact [support@brickken.com](mailto:support@brickken.com). |
### Wallets and environments
| Symptom | Cause | Fix |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A browser wallet throws a different generic JavaScript error in every wallet | A prepared transaction was passed straight to `eth_sendTransaction` | Prepared transactions are ethers-style unsigned transactions, not EIP-1193 payloads. See [Browser wallets](/api-reference/guides/browser-wallets). |
| MetaMask returns code `4100` | `from` is an account the user has not connected | Ask the user to connect or switch to the wallet that actually holds the asset. |
| The storefront hangs on "Loading Secure Environment", or the KYC widget spins forever | The wrong host | Use `https://.store.sandbox.brickken.com`. The KYC widget resolves the asset from the host it is served from. See [Sandbox](/get-started/sandbox). |
| `License for user not found` | A production storefront is being used for a Sandbox asset | Same fix — Sandbox assets only resolve on Sandbox hosts. |
| Test payment tokens obtained from a public faucet are not accepted | The Sandbox uses its own payment-token contracts | Resolve the correct token through the API. See [Sandbox](/get-started/sandbox). |
## Offering lifecycle
`claimTokens` is gated on finalisation, and what it does depends on whether the offering met its
soft cap.
`newSto` schedules the offering. It opens when `startDate` passes.
`newInvest` works while the offering is open. Investors need a whitelisted wallet, an allowance
to this offering's escrow, and the payment-token balance.
`closeOffer` reverts with `IssuanceNotEnded` until `endDate` has passed. There is no admin
override and no minimum duration.
`closeOffer` finalises the issuance. If the soft cap was reached, the offering is successful.
If it was not, the issuance enters **rollback**.
`claimTokens` releases the purchased tokens on a successful issuance, and **refunds the payment
token** on a rolled-back one. It is the same call either way.
An offering that ends without reaching its soft cap will refund rather than deliver tokens. To
demonstrate a successful claim, size the soft cap so the offering can actually reach it.
## Check the chain state yourself
Before reporting a problem, read the state the contract is reading:
| Question | Call |
| -------------------------------------------------------------- | --------------------------------------------------------------- |
| Is this wallet whitelisted for the token? | `GET /get-whitelist-status?tokenSymbol=…&address=…` |
| How much has this wallet approved, and to whom? | `GET /get-allowance` |
| What are the offering's dates, caps, and raised amount? | `GET /get-sto-by-id` |
| Does this investor exist, and what is their compliance status? | `GET /get-investor-info?tokenSymbol=…&email=…` |
| Which token does this asset actually take as payment? | `GET /get-tokenizer-info?tokenSymbol=…` → `paymentTokenAddress` |
| Did my transaction land? | `GET /get-transaction-status?txId=…` |
If a call still fails after checking all of the above, send the exact request body, the `txId`, and
the timestamp to [tech@brickken.com](mailto:tech@brickken.com).
Test tokens, storefront hosts, and fast test investors.
Send a prepared transaction from MetaMask or another injected wallet.
# Dapp API
Source: https://docs.brickken.com/api-reference/introduction
API-key authenticated Brickken API for tokenization, STOs, security-token operations, and reads.
## Overview
The Brickken Dapp API is the API-key authenticated surface for tokenized asset workflows. Use it when your integration owns a Brickken API key and wants to prepare transactions for a wallet to sign, submit signed transactions, or read tokenization and STO data.
Use the [Agentic API](/api-reference/endpoint/agentic-methods-x402), [MCP](/mcp/introduction), or [CLI](/cli/introduction) for private-key based agentic flows.
## Base URLs
| Environment | API base URL | App URL |
| ----------- | ---------------------------------- | ----------------------------------- |
| Sandbox | `https://api.sandbox.brickken.com` | `https://dapp.sandbox.brickken.com` |
| Production | `https://api.brickken.com` | `https://dapp.brickken.com` |
Sandbox and production are separate deployments with separate databases. An API key issued for one does not work on the other.
## Authentication
Send your API key in every request:
```http theme={null}
x-api-key: YOUR_BRICKKEN_API_KEY
```
Two prerequisites before your first write:
1. **You need a key.** [Request one](/get-started/request-api-key) with the email tied to your Brickken account.
2. **Your `signerAddress` must be whitelisted by Brickken.** A prepare call will not accept an unknown signer. Ask for the whitelist in the same request as the key.
Your key is also scoped: it can only act on token symbols it tokenized, and each write method has its own credit balance. See [Authentication](/get-started/authentication) for the credential matrix, plans, limits, and error codes.
Ready-to-run example requests for every endpoint.
The MCP server exposes every endpoint below as a tool, using the same API key.
## Transaction Flow
Most write operations use the same three-step flow:
1. **Prepare** unsigned transactions with `POST /prepare-transactions`.
2. **Sign** every returned transaction with the wallet matching `signerAddress`.
3. **Send** the signed payloads with `POST /send-transactions`, then poll `GET /get-transaction-status`.
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"chainId": "11155111",
"method": "newTokenization",
"tokenizerEmail": "issuer@example.com",
"signerAddress": "0xYourWallet",
"name": "Example Asset",
"tokenSymbol": "EXMPL",
"tokenType": "RWA_TOKEN",
"supplyCap": "1000000",
"url": "https://example.com/token-docs"
}'
```
The response includes `txId` and `transactions`. Sign the transaction or transactions locally, then send them:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"txId": "0xPreparedTransactionId",
"signedTransactions": ["0xSignedRawTransaction"]
}'
```
## Write Endpoints
| Endpoint | Purpose |
| ---------------------------- | ------------------------------------------------------------------------------ |
| `POST /prepare-transactions` | Prepare any supported transaction method by passing `method` in the JSON body. |
| `POST /send-transactions` | Submit signed transactions returned by prepare. |
| `PATCH /patch-token-docs` | Update token documentation and branding files. |
## Supported Methods
| Area | `method` values |
| ------------ | ------------------------------------------------------------------------------------------------------------------------- |
| Tokenization | `newTokenization`, `mintToken`, `whitelist`, `burnToken`, `transferFrom`, `transferTo`, `approve`, `dividendDistribution` |
| STOs | `newSto`, `newInvest`, `claimTokens`, `closeOffer` |
## Read Endpoints
| Endpoint | Purpose |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `GET /get-network-info` | Read chain metadata and supported network configuration. |
| [`GET /get-token-info`](/api-reference/endpoint/get-token-info) | Read one asset record by symbol, or list the symbols available to the API key. |
| [`GET /get-tokenizer-info`](/api-reference/endpoint/get-tokenizer-info) | Read the tokenizer account and the token, payment-token, and escrow contract addresses. |
| [`GET /get-stos`](/api-reference/endpoint/get-stos) | List STOs for a token. |
| [`GET /get-sto-by-id`](/api-reference/endpoint/get-sto-by-id) | Read one STO by ID. |
| `GET /get-investments-by-sto-id` | List investments for one STO. |
| `GET /get-investor-info` | Read investor status by token and email. |
| `GET /get-allowance` | Read allowance between owner and spender. |
| `GET /get-balance-whitelist` | Read investor balance and whitelist status. |
| `GET /get-whitelist-status` | Check whether an investor wallet is whitelisted. |
| `GET /get-sto-balance` | Read STO balance and status. |
| `GET /get-dividend-distribution` | Read dividend distribution information. |
| `GET /get-transaction-status` | Poll a submitted blockchain transaction. |
```bash theme={null}
curl --request GET \
'https://api.sandbox.brickken.com/get-network-info?chainId=11155111' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY'
```
## Networks
| Network | Decimal | Hex |
| -------------------- | ---------- | ---------- |
| Ethereum mainnet | `1` | `0x1` |
| Base mainnet | `8453` | `0x2105` |
| BNB Smart Chain | `56` | `0x38` |
| Polygon mainnet | `137` | `0x89` |
| Sepolia testnet | `11155111` | `0xaa36a7` |
| Polygon Amoy testnet | `80002` | `0x13882` |
Pass `chainId` as decimal or hex. Client tooling normalizes common values.
Prepared transactions are on-chain actions. Verify `chainId`, `signerAddress`, token symbol or token address, and all recipient addresses before signing.
## Guides
The full lifecycle, from tokenization to dividends.
Send a prepared transaction from MetaMask or another injected wallet.
Decode a failed call, from validation errors to raw revert data.
# Postman Collection
Source: https://docs.brickken.com/api-reference/postman
Download the official Brickken API Postman collection and environments
## Overview
Get started with the Brickken API in minutes using our official Postman collection. It includes ready-to-run requests for every public endpoint — the BKN faucet, KYC onboarding, agent getters, transaction preparation, signed transaction submission, token documentation management, and the Agentic (x402) API — pre-configured with example payloads and environment variables.
## Downloads
The full client collection: Create Transaction, Send Transaction, Information, Management, Agentic API (x402) and Discovery requests.
Targets `https://api.sandbox.brickken.com` — use this for testing.
Targets `https://api.brickken.com` — use this for live operations.
If a file opens in the browser instead of downloading, right-click the card and choose **Save Link As…**.
## Import into Postman
1. Open Postman and click **Import** (top left).
2. Drop in the collection file and both environment files.
3. Select the **Brickken API — Sandbox** environment from the environment picker (top right).
4. Open the environment and set your `apiKey`. Optionally adjust `tokenSymbol`, `chainId`, `agentChainId`, `agentUuid`, and `ownerWalletAddress` for the requests you plan to run.
5. Run any request — authentication is applied automatically via the `x-api-key` header at collection level.
## Authentication
Business endpoints are authenticated with an API key in the `x-api-key` header, and your `signerAddress` must be whitelisted before writes are accepted.
The form sends a complete request — key and signer whitelist — to `tech@brickken.com`.
Agentic (x402) endpoints alternatively accept a per-call payment via the `X-Payment` header. See [Authentication](/get-started/authentication) for the full credential matrix.
The **Agent Getters** folder defaults to API-key authentication and includes disabled `X-Payment` headers for manual x402 retries. The **KYC** folder always requires the API key; creating a link can create an investor and send an invitation email.
### Faucet UUID lifecycle
The **BKN Faucet** request uses the materialized `bknFaucetIdempotencyKey` environment variable. Its pre-request script creates and validates UUID v4 when the variable is empty.
* Keep the variable unchanged when retrying the same logical claim.
* Clear `bknFaucetIdempotencyKey` before a new claim; the next run generates a new UUID v4.
* Never reuse the UUID with another recipient.
The faucet uses one of the API key's 10 dedicated lifetime claims. Postman does not sign x402 payment payloads; use the SDK, CLI, or MCP for the 0.01 USDC x402 path.
## Typical Workflow
Call a request from the **Create Transaction** folder — it returns unsigned transactions and a `txId`.
Sign the returned transactions locally with your whitelisted signer wallet (e.g. using ethers.js).
Submit the signed transactions with **Send Transactions**.
Poll **Check Transaction Status** in the **Information** folder until the transaction confirms.
# Authentication & Configuration
Source: https://docs.brickken.com/cli/authentication
Dapp API, KYC, faucet, API-key-or-x402 reads, private-key signing, environments, and CLI configuration.
## What the CLI can authenticate
The CLI uses endpoint-specific authentication. Dapp API transaction methods and JSON endpoints require an API key. Client-controlled Agentic API and RAMS writes use an API key when configured and otherwise fall back to x402; relayed writes use x402. KYC link creation requires an API key, while the BKN faucet, agent getters, and RAMS reads use an API key when configured and otherwise fall back to x402.
| Request | Credential the CLI sends |
| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Dapp transaction methods (`newTokenization`, `newSto`, `mintToken`, and other Dapp methods) | `x-api-key` (required) |
| Client-controlled Agentic/RAMS writes | `x-api-key` if configured, otherwise x402 |
| Relayed Agentic/RAMS writes | x402 only |
| `kyc create-link` | `x-api-key` (required) |
| `faucet bkn` (Sandbox/Forge) | Exactly one: `x-api-key`, or 0.01 USDC x402 with a private key |
| `agent list`, `info`, `transactions` | `x-api-key` if configured, otherwise x402 |
| `tx status` | `x-api-key` if configured, otherwise existing access or x402 |
| `rams inspect`, `status`, `can-execute`, `compliance-status`, `executor-action`, `sign` | `x-api-key` if configured, otherwise x402 |
| `dapp get`, `dapp request` | `x-api-key` (required) |
The CLI supports Dapp API transaction methods through `brickken tx prepare --method ` and Dapp API JSON endpoints through `brickken dapp get` or `brickken dapp request`. Multipart file uploads such as `/patch-token-docs` remain REST-only.
Use the [MCP server](/mcp/introduction) or [REST API](/api-reference/introduction) when you need multipart uploads or the full typed Dapp API surface.
## Write authentication
Transaction authentication depends on the method and execution mode:
1. In `brickken-relayed` mode, the CLI prepares for free and the send carries the full operation charge.
2. Dapp API transaction methods use the configured API key at prepare and send; the operation is charged against the key's credits.
3. Client-controlled Agentic API and RAMS writes use the configured API key when present. Without a key, the CLI handles the x402 challenge at each priced step.
4. When an x402 request responds `402 Payment Required`, the CLI signs the payment locally and retries with an `X-PAYMENT` header.
In the recommended `brickken-relayed` mode the private key signs **only the x402 payment** — Brickken's relayer signs and broadcasts the operation. In the default `client-signed` mode the same key also **signs the blockchain transaction** locally.
## KYC and read authentication
KYC and Dapp API JSON endpoints always need an API key. Agent getters and RAMS read/typed-data endpoints send the key when configured and otherwise use the configured private key for x402.
```bash theme={null}
export BRICKKEN_API_KEY=...
brickken kyc create-link --email investor@example.com --need-kyc true
brickken agent list --chain 84532 --limit 20
brickken rams status --chain 11155111 --agent "$AGENT" --principal "$PRINCIPAL"
```
`BKN_API_KEY` is accepted as an alias, or pass global `--api-key`. Offline `rams sign --typed-data-file` does not require a key.
Your private key never leaves your machine. Treat it as a secret: prefer an `.env` file or environment variable over passing `--private-key` inline.
## Provide a private key
```bash theme={null}
export BRICKKEN_PRIVATE_KEY=0x...
```
`BKN_PRIVATE_KEY` is accepted as an alias.
## Environments and base URLs
Select the environment with `--env` or `BRICKKEN_ENV` (default: `sandbox`):
| Environment | Base URL |
| ------------------- | ---------------------------------- |
| `sandbox` (default) | `https://api.sandbox.brickken.com` |
| `production` | `https://api.brickken.com` |
Override the base URL directly with `--base-url` or `BRICKKEN_BASE_URL` when needed. An internal `forge` environment exists for Brickken pre-release QA — contact `tech@brickken.com` for its base URL.
## Networks and chain IDs
Pass the target chain with `--chain`. Both decimal and hex forms are accepted, and common decimal IDs are normalized automatically — for example Base Sepolia can be passed as `84532` or `14a34`.
| Network | Decimal | Hex |
| ------------------------- | ---------- | ---------- |
| Base mainnet | `8453` | `0x2105` |
| Base Sepolia | `84532` | `0x14a34` |
| Ethereum Sepolia (legacy) | `11155111` | `0xaa36a7` |
## RPC URL
Some commands (notably [`create-token`](/cli/commands/token-economics)) wait for the deployment receipt to read back the deployed `tokenAddress`. Set an RPC for the target chain:
```bash theme={null}
export BRICKKEN_RPC_URL="https://sepolia.base.org" # Base Sepolia
```
`BKN_RPC_URL` is accepted as an alias, or use `--rpc-url`.
## Configuration precedence
Configuration is resolved in this order (highest priority first):
1. **Command-line flags** — `--env`, `--base-url`, `--api-key`, `--private-key`, `--rpc-url`, `--env-file`, `--json`
2. **Environment variables** — `BRICKKEN_*` or `BKN_*`
3. **`.env` file** in the current working directory (or the path given by `--env-file`)
4. **Defaults** — `sandbox` environment, `client-signed` execution mode (pass `--execution-mode brickken-relayed` to opt into relayed)
### Global flags
| Flag | Description |
| ------------------------------------ | ------------------------------------------------------------------------------------ |
| `--env ` | Target Brickken environment |
| `--base-url ` | Override the Brickken API base URL |
| `--api-key ` | API key for Dapp API, KYC, faucet, agent getters, and client-controlled reads/writes |
| `--private-key ` | Private key for local signing and x402 payments |
| `--rpc-url ` | RPC URL used to wait for token deployment receipts |
| `--env-file ` | Env file to load before resolving config |
| `--json` | Print machine-readable JSON output |
### Environment variables
| Variable | Alias | Purpose |
| ---------------------- | ----------------- | ------------------------------------------------------------------------ |
| `BRICKKEN_API_KEY` | `BKN_API_KEY` | Dapp API, KYC, faucet, agent getters, and client-controlled reads/writes |
| `BRICKKEN_PRIVATE_KEY` | `BKN_PRIVATE_KEY` | Signing and x402 payment key |
| `BRICKKEN_BASE_URL` | `BKN_BASE_URL` | API base URL |
| `BRICKKEN_RPC_URL` | `BKN_RPC_URL` | RPC for receipt polling |
| `BRICKKEN_ENV` | `BKN_ENV` | `forge`, `sandbox`, or `production` |
## Budget note
Relayed preparation is free, while client-controlled modes split the write charge between prepare and send. Agent getters cost `0.000001 USDC` per x402 call. On Base Sepolia and other non-production environments the write reference price is commonly `0.01 USDC` per operation. Fund the wallet behind `BRICKKEN_PRIVATE_KEY` with the exact asset returned by the live challenge. See [Pricing](/api-reference/endpoint/agentic-pricing) for the execution-mode matrix and mainnet write table.
# agent
Source: https://docs.brickken.com/cli/commands/agent
Manage ERC-8004 agent identity and reputation from the Brickken CLI.
`brickken agent` groups ERC-8004 reads, identity writes, and reputation operations on Base. Read commands execute immediately. Write commands are **prepare-only by default**; relayed preparation is free while client-controlled modes charge the prepare share. Add `--execute` to also send and pay the remaining x402 charge. The recommended `brickken-relayed` mode (`--execution-mode brickken-relayed`, omit `--signer-address`) lets Brickken's relayer sign and broadcast; `client-signed` signs locally with `--signer-address`.
For the field-level semantics of each underlying method, see [Agentic Methods with x402](/api-reference/endpoint/agentic-methods-x402).
## Read commands
Agent getters use the configured API key when present and otherwise fall back to x402. The x402 price is `0.000001 USDC` per call.
```bash theme={null}
brickken agent list --chain 84532 --limit 20 --offset 0 --json
brickken agent info --agent-uuid "$AGENT_UUID" --json
brickken agent transactions --agent-uuid "$AGENT_UUID" --limit 20 --offset 0 --json
```
`info` and `transactions` accept `--agent-uuid`, or `--agent-id` together with `--chain`. `list` accepts `--chain`, `--owner-wallet-address`, `--limit`, and `--offset`. In x402 mode, `list` requires both owner filters and the payment signer must match the owner wallet. Limits are 1–100 and offsets are non-negative.
See [List Agents](/api-reference/endpoint/get-agents), [Get Agent Information](/api-reference/endpoint/get-agent-info), and [Get Agent Transactions](/api-reference/endpoint/get-agent-transactions).
## Shared write options
These options apply to agent write subcommands:
| Flag | Description |
| ---------------------------- | ----------------------------------------------------------------------------- |
| `--chain ` | Chain identifier (decimal or hex). `8453` Base mainnet, `84532` Base Sepolia. |
| `--execution-mode ` | `client-signed` (default) or `brickken-relayed` (recommended) |
| `--signer-address ` | Signer wallet address. Required only for `client-signed`. |
| `--gas-limit ` | Optional explicit gas limit (client-signed) |
| `-f, --file ` | JSON/YAML input file (merged with CLI flags) |
| `--execute` | Send and pay the x402 charge (otherwise prepare-only) |
`--owner-email` / `--email` is optional metadata. Agentic operations do not require a tokenizer user in the Brickken database.
## agent register
Prepare or execute an ERC-8004 agent registration → backend method [`agentRegister`](/api-reference/endpoint/agentic-methods-x402#agentregister). The prepare response includes `info.agentUuid`; save it for the follow-up `set-uri` and `set-metadata` calls.
| Flag | Type | Required | Description |
| -------------------------------- | ------- | -------- | ----------------------------------------- |
| `--name ` | string | Yes | Agent display name |
| `--description ` | string | Yes | Agent description |
| `--image ` | string | Yes | Agent image URL or IPFS URI |
| `--service-name ` | string | Yes | Single service name |
| `--service-endpoint ` | string | Yes | Single service endpoint |
| `--service-version ` | string | No | Single service version |
| `--ai-model-name ` | string | No | AI model name |
| `--ai-model-provider ` | string | No | AI model provider |
| `--tag ` | string | No | Discovery tag (repeatable) |
| `--version ` | string | No | Agent profile version |
| `--documentation ` | string | No | Documentation URL |
| `--source-code ` | string | No | Source code URL |
| `--license ` | string | No | License identifier or URL |
| `--agent-type ` | string | No | Agent type |
| `--supported-trust ` | string | No | Supported trust capability (repeatable) |
| `--x402-support ` | boolean | No | Whether the agent advertises x402 support |
| `--active ` | boolean | No | Whether the agent is active |
| `--owner-email ` | string | No | Tokenizer owner email |
| `--email ` | string | No | Alias for `--owner-email` |
```bash theme={null}
brickken agent register \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--name "Research Agent" \
--description "On-chain AI research agent" \
--image https://example.com/agent.png \
--service-name A2A \
--service-endpoint https://agent.example/.well-known/agent-card.json \
--service-version 0.3.0 \
--ai-model-provider OpenAI \
--ai-model-name "Research Model" \
--x402-support true \
--execute \
--json | tee register-output.json
export AGENT_UUID="$(jq -r '.prepared.info.agentUuid' register-output.json)"
```
## agent set-uri
Prepare or execute an agent URI/profile update → [`agentSetURI`](/api-reference/endpoint/agentic-methods-x402#agentseturi). Run this after the registration transaction is mined; it injects the real on-chain `agentId` and publishes the final profile to IPFS.
In addition to the shared options and all `register` profile flags (`--name`, `--description`, `--image`, `--service-*`, `--ai-model-*`, `--tag`, `--version`, `--documentation`, `--source-code`, `--license`, `--agent-type`, `--supported-trust`, `--x402-support`, `--active`):
| Flag | Type | Required | Description |
| --------------------- | ------ | -------- | --------------------------- |
| `--agent-uuid ` | string | Yes¹ | Stored tokenized agent UUID |
| `--agent-id ` | string | Yes¹ | On-chain ERC-8004 agent ID |
¹ Provide either `--agent-uuid` or `--agent-id`.
```bash theme={null}
brickken agent set-uri \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-uuid "$AGENT_UUID" \
--name "Research Agent" \
--description "On-chain AI research agent" \
--tag ai-agent \
--documentation https://docs.brickken.com \
--source-code https://github.com/Brickken/brickken-api-cli \
--license MIT \
--agent-type research \
--supported-trust feedback \
--x402-support true \
--active true \
--execute \
--json
```
## agent set-metadata
Prepare or execute a metadata update → [`agentSetMetadata`](/api-reference/endpoint/agentic-methods-x402#agentsetmetadata). Writes a single key/value pair on-chain.
| Flag | Type | Required | Description |
| -------------------------------- | ------ | -------- | ------------------------------------------------- |
| `--agent-uuid ` | string | Yes¹ | Stored tokenized agent UUID |
| `--agent-id ` | string | Yes¹ | On-chain ERC-8004 agent ID |
| `--metadata-key ` | string | Yes² | Metadata key |
| `--metadata-value ` | string | No | Metadata value |
| `--metadata-encoding ` | string | No | `string` (default), `json`, or `hex` |
| `--ai-model-name ` | string | No | Shortcut for `metadataKey=modelName` |
| `--ai-model-provider ` | string | No | AI model provider stored in local profile context |
¹ Provide either `--agent-uuid` or `--agent-id`. ² Or supply `--ai-model-name` as the key shortcut.
```bash theme={null}
brickken agent set-metadata \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-uuid "$AGENT_UUID" \
--metadata-key capabilities \
--metadata-value '{"tasks":["research","summarization","token-operations"]}' \
--metadata-encoding json \
--execute \
--json
```
For complex metadata payloads, prefer a `--file` to avoid shell-quoting issues. See [the raw `tx` flow](/cli/commands/tx) for the file-based pattern.
## agent set-wallet
Prepare or execute an agent wallet update → [`agentSetWallet`](/api-reference/endpoint/agentic-methods-x402#agentsetwallet). The new wallet must sign an authorization first.
| Flag | Type | Required | Description |
| ------------------------- | ------ | -------- | ------------------------------------------- |
| `--agent-uuid ` | string | Yes¹ | Stored tokenized agent UUID |
| `--agent-id ` | string | Yes¹ | On-chain ERC-8004 agent ID |
| `--new-wallet ` | string | Yes | New agent wallet address |
| `--signature ` | string | Yes | Authorization signature from the new wallet |
| `--deadline ` | number | Yes | Unix timestamp deadline for the signature |
¹ Provide either `--agent-uuid` or `--agent-id`.
```bash theme={null}
brickken agent set-wallet \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-uuid "$AGENT_UUID" \
--new-wallet 0xNewAgentWallet \
--signature 0xSignatureFromNewWallet \
--deadline 1800000000 \
--execute \
--json
```
## agent transfer-ownership
Prepare or execute an ERC-8004 identity ownership transfer → [`agentTransferOwnership`](/api-reference/endpoint/x402-agent-transfer-ownership). Moves the identity NFT from Brickken custody to a wallet you control via an ERC-721 `safeTransferFrom`.
| Flag | Type | Required | Description |
| ----------------------- | ------ | -------- | ------------------------------------------------------------------------------ |
| `--agent-uuid ` | string | Yes¹ | Stored tokenized agent UUID |
| `--agent-id ` | string | Yes¹ | On-chain ERC-8004 agent ID |
| `--new-owner ` | string | Yes | Wallet that will receive the identity NFT (must differ from the current owner) |
¹ Provide either `--agent-uuid` or `--agent-id`. The agent must already be registered on-chain.
```bash theme={null}
brickken agent transfer-ownership \
--chain "$CHAIN" \
--execution-mode brickken-relayed \
--agent-uuid "$AGENT_UUID" \
--new-owner 0xYourWallet \
--execute \
--json
```
Ownership transfer is **irreversible** and is different from `set-wallet` (which only changes the operational wallet). After the identity leaves Brickken custody, Brickken's relayer can no longer perform owner-only operations for that agent.
## agent feedback give
Prepare or execute reputation feedback → [`agentGiveFeedback`](/api-reference/endpoint/agentic-methods-x402#agentgivefeedback).
| Flag | Type | Required | Description |
| -------------------------- | ------ | -------- | --------------------------------------------- |
| `--agent-uuid ` | string | Yes¹ | Target agent UUID |
| `--agent-id ` | string | Yes¹ | Target on-chain agent ID |
| `--value ` | string | Yes | Feedback value |
| `--value-decimals ` | string | Yes | Decimals used to interpret `value` |
| `--email ` | string | No² | Feedback owner email |
| `--tag1 ` | string | No | Feedback tag 1 |
| `--tag2 ` | string | No | Feedback tag 2 |
| `--endpoint ` | string | No | Service endpoint related to feedback |
| `--feedback-uri ` | string | No | Feedback URI |
| `--feedback-hash ` | string | No | 32-byte feedback hash (defaults to zero hash) |
¹ Provide either `--agent-uuid` or `--agent-id`. ² Required when the API cannot infer tracking context from the agent reference.
```bash theme={null}
brickken agent feedback give \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-id 7 \
--email reviewer@example.com \
--value 9500 \
--value-decimals 2 \
--tag1 quality \
--endpoint https://agent.example/.well-known/agent-card.json \
--execute \
--json
```
## agent feedback revoke
Prepare or execute feedback revocation → [`agentRevokeFeedback`](/api-reference/endpoint/agentic-methods-x402#agentrevokefeedback).
| Flag | Type | Required | Description |
| -------------------------- | ------ | -------- | -------------------------- |
| `--agent-id ` | string | Yes | On-chain ERC-8004 agent ID |
| `--feedback-index ` | number | Yes | Feedback index to revoke |
| `--email ` | string | Yes | Feedback owner email |
```bash theme={null}
brickken agent feedback revoke \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-id 7 \
--feedback-index 0 \
--email reviewer@example.com \
--execute \
--json
```
## agent feedback respond
Prepare or execute a feedback response → [`agentAppendFeedbackResponse`](/api-reference/endpoint/agentic-methods-x402#agentappendfeedbackresponse).
| Flag | Type | Required | Description |
| ---------------------------- | ------ | -------- | --------------------------------------------- |
| `--agent-id ` | string | Yes | On-chain ERC-8004 agent ID |
| `--client-address ` | string | Yes | Original feedback client address |
| `--feedback-index ` | number | Yes | Feedback index to respond to |
| `--response-uri ` | string | Yes | URI of the off-chain response payload |
| `--response-hash ` | string | No | 32-byte response hash (defaults to zero hash) |
| `--email ` | string | Yes | Agent owner email |
```bash theme={null}
brickken agent feedback respond \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-id 7 \
--client-address 0xReviewerWallet \
--feedback-index 0 \
--response-uri ipfs://QmResponseCID \
--email owner@example.com \
--execute \
--json
```
For multi-step agent flows (`register` → `set-uri` → `set-metadata`), wait for each transaction to be mined before preparing the next one. Preparing dependent transactions before the previous one is mined can produce nonce conflicts. See the [end-to-end guide](/cli/guides/agent-and-token-workflow).
# dapp
Source: https://docs.brickken.com/cli/commands/dapp
Call API-key-authenticated Dapp API read and JSON endpoints from the terminal.
`brickken dapp` calls Dapp API JSON endpoints with the configured API key. Use [`brickken tx`](/cli/commands/tx) for Dapp transaction methods that follow the prepare/sign/send flow.
```bash theme={null}
export BRICKKEN_API_KEY=...
```
## dapp get
Call a Dapp API `GET` endpoint. The path must be relative to the configured Brickken base URL.
```bash theme={null}
brickken dapp get \
--path /get-token-info \
--query tokenSymbol=EXMPL \
--json
```
For several query parameters, repeat `--query`:
```bash theme={null}
brickken dapp get \
--path /get-stos \
--query tokenSymbol=EXMPL \
--query page=1 \
--query limit=20 \
--json
```
You can also load query parameters from a JSON or YAML file:
```json theme={null}
{
"tokenSymbol": "EXMPL",
"page": 1,
"limit": 20
}
```
```bash theme={null}
brickken dapp get --path /get-stos --file query.json --json
```
## dapp request
Call a Dapp API JSON `POST` or `PATCH` endpoint with a request body loaded from a JSON or YAML file:
```bash theme={null}
brickken dapp request \
--method POST \
--path /some-dapp-endpoint \
--file request.json \
--json
```
The command sends `x-api-key` and does not create an x402 payment. The operation is charged against the API key's credits.
Multipart file uploads such as `/patch-token-docs` are not supported by this JSON command. Use the [REST API](/api-reference/introduction) directly for multipart requests.
## Related transaction flow
Dapp tokenization, STO, and security-token methods use `brickken tx prepare`:
```bash theme={null}
brickken tx prepare \
--method newTokenization \
--file new-tokenization.json \
--json
```
The transaction payload must include a whitelisted `signerAddress` and the API key must have sufficient credits. See the [raw transaction reference](/cli/commands/tx) for the method list and client-controlled signing flow.
# BKN Faucet
Source: https://docs.brickken.com/cli/commands/faucet
Request 100 BKN on Ethereum Sepolia with an API key or x402.
```bash theme={null}
brickken faucet bkn \
--recipient-address 0x1111111111111111111111111111111111111111 \
[--idempotency-key UUID_V4] \
--json
```
The command is available for Sandbox and Forge. It uses an API key when configured, or a private key to pay the 0.01 USDC x402 challenge. Configure exactly one.
Each API key has 10 dedicated lifetime faucet claims, separate from `mintToken`. Recipients have a 24-hour cooldown.
The CLI generates a UUID v4 when `--idempotency-key` is omitted and returns it in the output. Use a new UUID for a new claim; reuse the returned UUID only to retry the same logical claim.
```json theme={null}
{
"status": "submitted",
"amount": "100",
"idempotencyKey": "4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1"
}
```
# kyc
Source: https://docs.brickken.com/cli/commands/kyc
Create API-key-authenticated investor KYC links from the Brickken CLI.
`brickken kyc create-link` creates or reuses an investor and returns a Sumsub verification link. It always requires `BRICKKEN_API_KEY` or the global `--api-key` option.
```bash theme={null}
brickken kyc create-link \
--email investor@example.com \
--need-kyc true \
--json
```
| Flag | Type | Required | Description |
| -------------------------- | ------- | -------- | ---------------------------------------------------- |
| `--email ` | string | Yes | Investor email address |
| `--need-kyc ` | boolean | No | Whether verification is required; defaults to `true` |
The command can create an investor account and send an invitation email. Treat the returned Sumsub URL as sensitive and do not store it in shell history, logs, or source control.
See [Create KYC Link](/api-reference/endpoint/create-kyc-link) for the response and authorization rules.
# rams
Source: https://docs.brickken.com/cli/commands/rams
Manage ERC-8226 mandates, compliance, executor actions, reads, and EIP-712 signatures from the Brickken CLI.
`brickken rams` targets Ethereum Sepolia (`11155111`) at launch. Writes are prepare-only by default; add `--execute` for prepare → local transaction signing → send and x402 settlement. Reads and online typed-data fetches require `BRICKKEN_API_KEY`.
## Shared write options
| Flag | Description |
| ----------------------------- | ----------------------------------------------------- |
| `--chain ` | Decimal or hex chain identifier |
| `--signer-address ` | Wallet that signs the returned blockchain transaction |
| `--mandate-address ` | Optional AgentMandate override |
| `--gas-limit ` | Optional gas limit |
| `-f, --file ` | JSON/YAML input merged with flags |
| `--execute` | Sign/send instead of prepare-only |
Only `grant`, `revoke`, `extend`, and `set-operator` accept `--signature`, `--deadline`, and `--execution-mode brickken-relayed`. All other RAMS writes are client-signed only.
## rams grant
Grant scoped authority from a compliant principal to an agent (`ramsGrantMandate`).
| Flags | Required / meaning |
| ----------------------------------------------------- | ------------------------------------------------------ |
| `--agent`, `--principal`, `--valid-until` | Required mandate parties and expiry |
| `--identity-ref`, `--asset` | Required compliance identity and asset |
| `--max-transaction-value`, `--max-cumulative-value` | Raw base-unit caps; accept `max`/`unlimited` |
| `--action ` | Required, repeatable bytes32 action or 4-byte selector |
| `--valid-from`, `--compliance-provider`, `--metadata` | Optional mandate details |
Direct mode is signed by the principal. Signature mode may use any sender/relayer.
## rams revoke / extend / set-operator
| Command | Required flags | Direct signer |
| ------------------- | --------------------------------------------- | ------------------------------ |
| `rams revoke` | `--agent`, `--principal` | Principal or approved operator |
| `rams extend` | `--agent`, `--principal`, `--new-valid-until` | Principal or approved operator |
| `rams set-operator` | `--principal`, `--operator`, `--approved` | Principal |
Each accepts the signed-lifecycle options for relaying. The EIP-712 signature always belongs to the principal, including when an operator could call directly.
## rams execute
The agent executes through AgentExecutor (`ramsExecute`). `--signer-address` must be the agent and the operation is never relayed.
| Mode | Flags |
| ------------- | --------------------------------------- |
| Raw calldata | `--target`, `--data` |
| ERC-20 helper | `--asset`, `--from`, `--to`, `--amount` |
`--executor-address` overrides the per-principal executor. Amounts are raw base units.
## rams set-action
Register an executor selector (`ramsSetExecutorAction`). The signer is the AgentExecutor owner.
| Flag | Meaning |
| -------------------------- | ------------------------------------------------------------ |
| `--selector` or `--action` | 4-byte selector or left-aligned bytes32 action |
| `--supported` | Enable/disable the selector |
| `--has-amount` | Whether calldata carries a cap-gated amount |
| `--amount-index` | Zero-based ABI word index; required when `hasAmount` is true |
| `--executor-address` | Optional executor override |
A value-moving selector registered with `--has-amount false` bypasses mandate caps.
## rams freeze / unfreeze
Both commands require `--agent`; the signer must hold `ENFORCER_ROLE`. They are never relayed. The registry admin cannot be its own enforcer.
## rams grant-principal / revoke-principal
ComplianceProvider owner operations; both are client-signed only.
| Command | Required flags | Optional flags |
| ----------------------- | ------------------------------- | ----------------------------------------------- |
| `rams grant-principal` | `--principal`, `--identity-ref` | `--expires-at`, `--compliance-provider-address` |
| `rams revoke-principal` | `--principal`, `--reason` | `--compliance-provider-address` |
Run grant-principal before granting a mandate with the same provider/identity reference.
## Authenticated reads
Set `BRICKKEN_API_KEY` or pass global `--api-key`. These commands never send a transaction:
| Command | Required flags | Result |
| ------------------------ | -------------------------------------------------------------------------- | ---------------------------------------------------- |
| `rams inspect` | `--chain`, `--agent`, `--principal` | Mandate, lifecycle status, freeze, nonce |
| `rams can-execute` | `--chain`, `--agent`, `--principal`, `--asset`, `--action` or `--selector` | Authoritative result and diagnostic checks |
| `rams status` | `--chain`, `--agent`, `--principal`; optional `--operator` | Freeze, nonce, operator approval |
| `rams compliance-status` | `--chain`, `--principal`, `--identity-ref` | Eligibility, expiry, reason |
| `rams executor-action` | `--chain`, `--selector` or `--action` | ActionSpec (`supported`, `hasAmount`, `amountIndex`) |
## rams sign
Fetch and locally sign EIP-712 data for `grant-mandate`, `revoke-mandate`, `extend-mandate`, or `set-operator`:
```bash theme={null}
brickken rams sign \
--operation grant-mandate \
--chain 11155111 \
--agent "$AGENT" \
--principal "$PRINCIPAL" \
--valid-until 1789000000 \
--identity-ref "$IDENTITY_REF" \
--asset "$ASSET" \
--max-transaction-value 1000000 \
--max-cumulative-value 5000000 \
--action 0x23b872dd \
--json > signature.json
```
Online signing requires the API key and principal private key. `--typed-data-file envelope.json` skips the GET and signs offline without an API key. The CLI verifies that the configured private key matches the server's expected signer.
## Relayed grant walkthrough
Reuse exactly the fields and deadline from the signed envelope:
```bash theme={null}
brickken rams grant \
--chain 11155111 \
--agent "$AGENT" \
--principal "$PRINCIPAL" \
--valid-until 1789000000 \
--identity-ref "$IDENTITY_REF" \
--asset "$ASSET" \
--max-transaction-value 1000000 \
--max-cumulative-value 5000000 \
--action 0x23b872dd \
--signature "$(jq -r .signature signature.json)" \
--deadline "$(jq -r .deadline signature.json)" \
--execution-mode brickken-relayed \
--execute --json
```
Omit `--signer-address` in Brickken-relayed mode: the backend supplies its operation signer. The configured private key is the x402 payer key and does not need to be the principal.
# Token economics
Source: https://docs.brickken.com/cli/commands/token-economics
Create, mint, burn, transfer, and approve agentic ERC-20 tokens with the Brickken CLI.
The token economics commands deploy and manage x402-capable agentic ERC-20 tokens on Base. Each is **prepare-only by default**; relayed preparation is free while client-controlled modes charge the prepare share. Add `--execute` to also send and pay the remaining x402 charge. The recommended `brickken-relayed` mode (`--execution-mode brickken-relayed`) lets Brickken's relayer sign and broadcast; the default `client-signed` mode signs locally with `--signer-address`.
Each high-level command maps to a backend agentic method. Field-level semantics for every method are documented under [Agentic Methods with x402](/api-reference/endpoint/agentic-methods-x402).
| Command | Backend method |
| ------------------------ | ----------------------------------------------------------------------------------------------- |
| `brickken create-token` | [`agentCreateToken`](/api-reference/endpoint/agentic-methods-x402#agentcreatetoken) |
| `brickken mint` | [`agentMintToken`](/api-reference/endpoint/agentic-methods-x402#agentminttoken) |
| `brickken burn` | [`agentBurnToken`](/api-reference/endpoint/agentic-methods-x402#agentburntoken) |
| `brickken transfer` | [`agentTransferToken`](/api-reference/endpoint/agentic-methods-x402#agenttransfertoken) |
| `brickken transfer-from` | [`agentTransferFromToken`](/api-reference/endpoint/agentic-methods-x402#agenttransferfromtoken) |
| `brickken approve` | [`agentApproveToken`](/api-reference/endpoint/agentic-methods-x402#agentapprovetoken) |
## Shared options
Every command accepts these:
| Flag | Description |
| ------------------------------------------- | ------------------------------------------------------------- |
| `--chain ` | Chain identifier (`8453` Base mainnet, `84532` Base Sepolia) |
| `--execution-mode ` | `client-signed` (default) or `brickken-relayed` (recommended) |
| `--signer-address ` | Signer wallet address. Required only for `client-signed`. |
| `--gas-limit ` | Optional explicit gas limit (client-signed) |
| `--owner-email ` / `--email ` | Optional tokenizer owner email |
| `--decimals ` | Token decimals (defaults to `18`) |
| `-f, --file ` | JSON/YAML input file (merged with CLI flags) |
| `--execute` | Send and pay the x402 charge (otherwise prepare-only) |
## create-token
Deploy a new agentic ERC-20 token.
| Flag | Type | Required | Description |
| -------------------------- | ------ | -------- | --------------------------------------------------------------- |
| `--name ` | string | Yes | Token name |
| `--symbol ` | string | Yes | Token ticker (2–11 uppercase alphanumeric) |
| `--token-symbol ` | string | No | Alias for `--symbol` |
| `--agent-wallet ` | string | Yes | Wallet that owns/mints the token |
| `--premint ` | string | No | Human-readable amount minted to `agentWallet` (defaults to `0`) |
```bash theme={null}
brickken create-token \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--name "Research Agent Token" \
--symbol RAGT \
--agent-wallet "$WALLET" \
--premint 1000 \
--decimals 18 \
--execute \
--json | tee create-token-output.json
export TOKEN_ADDRESS="$(jq -r '.tokenAddress' create-token-output.json)"
```
The examples below use `--signer-address` / `--agent-wallet` for `client-signed` mode. In `brickken-relayed` mode you omit both — Brickken's relayer becomes the token owner. When `create-token --execute` succeeds, the CLI waits for the deployment receipt and adds `tokenAddress` to the JSON output; set `--rpc-url`, `BRICKKEN_RPC_URL`, or `BKN_RPC_URL` for the target chain. Do not continue into `mint` or `burn` unless `tokenAddress` is present.
## mint
Mint additional tokens. `--signer-address` must be the configured `agentWallet`.
| Flag | Type | Required | Description |
| ------------------------------- | ------ | -------- | ----------------------------- |
| `--token-address ` | string | Yes | Deployed ERC-20 token address |
| `--to ` | string | Yes | Recipient wallet |
| `--recipient-address ` | string | No | Alias for `--to` |
| `--amount ` | string | Yes | Human-readable amount to mint |
```bash theme={null}
brickken mint \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--to 0xRecipientWallet \
--amount 100 \
--decimals 18 \
--execute \
--json
```
## burn
Burn tokens. `--signer-address` must be the configured `agentWallet`.
| Flag | Type | Required | Description |
| --------------------------- | ------ | -------- | ----------------------------- |
| `--token-address ` | string | Yes | Deployed ERC-20 token address |
| `--from ` | string | Yes | Wallet address to burn from |
| `--amount ` | string | Yes | Human-readable amount to burn |
```bash theme={null}
brickken burn \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--from 0xHolderWallet \
--amount 25 \
--decimals 18 \
--execute \
--json
```
## transfer
Transfer tokens from the signer's wallet.
| Flag | Type | Required | Description |
| ------------------------------- | ------ | -------- | --------------------------------- |
| `--token-address ` | string | Yes | Deployed ERC-20 token address |
| `--to ` | string | Yes | Recipient wallet |
| `--recipient-address ` | string | No | Alias for `--to` |
| `--amount ` | string | Yes | Human-readable amount to transfer |
```bash theme={null}
brickken transfer \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--to 0xRecipientWallet \
--amount 10 \
--decimals 18 \
--execute \
--json
```
## transfer-from
Transfer tokens through an allowance. `--signer-address` is the approved spender.
| Flag | Type | Required | Description |
| ------------------------------- | ------ | -------- | --------------------------------- |
| `--token-address ` | string | Yes | Deployed ERC-20 token address |
| `--from ` | string | Yes | Source (token holder) wallet |
| `--to ` | string | Yes | Recipient wallet |
| `--recipient-address ` | string | No | Alias for `--to` |
| `--amount ` | string | Yes | Human-readable amount to transfer |
```bash theme={null}
brickken transfer-from \
--chain "$CHAIN" \
--signer-address 0xApprovedSpenderWallet \
--token-address "$TOKEN_ADDRESS" \
--from 0xTokenHolderWallet \
--to 0xRecipientWallet \
--amount 5 \
--decimals 18 \
--execute \
--json
```
## approve
Approve a spender allowance.
| Flag | Type | Required | Description |
| ----------------------------- | ------ | -------- | -------------------------------------- |
| `--token-address ` | string | Yes | Deployed ERC-20 token address |
| `--spender-address ` | string | Yes | Spender wallet receiving the allowance |
| `--spender ` | string | No | Alias for `--spender-address` |
| `--amount ` | string | Yes | Human-readable allowance amount |
```bash theme={null}
brickken approve \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--spender-address 0xSpenderWallet \
--amount 50 \
--decimals 18 \
--execute \
--json
```
# tx
Source: https://docs.brickken.com/cli/commands/tx
API-key or x402 prepare, sign, send, and status flows for Brickken Dapp and Agentic API methods.
`brickken tx` exposes the raw [API transaction flow](/api-reference/introduction#api-flow) for Dapp and Agentic API methods. Use it when you want full control over the payload, need to call a specific backend method directly, or want to inspect the unsigned transaction before broadcasting. Dapp API methods use the configured API key; client-controlled Agentic and RAMS methods use the key when configured and otherwise use x402.
| Subcommand | Purpose |
| --------------------- | ---------------------------------------------------------- |
| `brickken tx prepare` | Prepare a raw transaction payload (optionally `--execute`) |
| `brickken tx sign` | Sign a prepared transaction locally |
| `brickken tx send` | Send signed transaction payloads |
| `brickken tx status` | Look up a broadcast transaction by hash |
## tx prepare
Prepare a raw transaction for any method. Dapp API methods use the configured API key and consume the method's credits; eligible Agentic and RAMS methods use the key when configured and otherwise use x402. Relayed preparation is free. With `--execute`, the CLI also sends to `/send-transactions`; API-key-authenticated Dapp sends use the key, while x402 sends pay the operation charge. The `--execution-mode brickken-relayed` mode lets Brickken's relayer sign and broadcast (omit `--signer-address`) and always uses x402; the default `client-signed` mode signs locally with the configured private key first.
| Flag | Type | Required | Description |
| ---------------------------- | ------ | -------- | --------------------------------------------------------------------------------- |
| `--method ` | string | Yes | Brickken transaction method |
| `--chain ` | string | No | Chain identifier (`8453` Base, `84532` Base Sepolia, `11155111` Ethereum Sepolia) |
| `--execution-mode ` | string | No | `client-signed` (default) or `brickken-relayed` (recommended) |
| `--signer-address ` | string | No | Signer wallet address (required for `client-signed`) |
| `-f, --file ` | string | No | JSON/YAML input file (merged with CLI flags) |
| `--execute` | flag | No | Send and pay the x402 charge (otherwise prepare-only) |
Supported Dapp transaction methods include `newTokenization`, `newSto`, `newInvest`, `claimTokens`, `closeOffer`, `mintToken`, `whitelist`, `burnToken`, `transferFrom`, `transferTo`, `approve`, and `dividendDistribution`. Agentic token methods include `agentCreateToken`, `agentMintToken`, `agentBurnToken`, `agentTransferToken`, `agentTransferFromToken`, and `agentApproveToken` (and the `agentApprove` alias, normalized to `agentApproveToken`). Agent identity, reputation, and RAMS methods are also accepted. You can also set `executionMode` directly in the `--file` body. See the [Dapp API reference](/api-reference/introduction) and [Agentic Methods with x402](/api-reference/endpoint/agentic-methods-x402) for each method's fields.
One-shot execution from a file:
```bash theme={null}
brickken tx prepare \
--method agentCreateToken \
--file token.json \
--execute \
--json
```
Prepare-only (inspect before signing):
```bash theme={null}
brickken tx prepare \
--method agentRegister \
--file agent-register.json \
--json | tee prepared.json
```
Prefer `--file` for nested JSON, long text, or values assembled by shell scripts. A file avoids the quoting pitfalls of inline JSON. The file's keys use the backend field names (e.g. `chainId`, `signerAddress`, `metadataValue`).
Example Dapp API tokenization file:
```json theme={null}
{
"chainId": "11155111",
"tokenizerEmail": "issuer@example.com",
"signerAddress": "0xYourWhitelistedWallet",
"name": "Example Asset",
"tokenSymbol": "EXMPL",
"tokenType": "RWA_TOKEN",
"supplyCap": "1000000",
"url": "https://example.com/token-docs"
}
```
Prepare it with the API key that pays for the Dapp API operation:
```bash theme={null}
export BRICKKEN_API_KEY=...
brickken tx prepare --method newTokenization --file new-tokenization.json --json
```
Example metadata file:
```json theme={null}
{
"chainId": "84532",
"executionMode": "brickken-relayed",
"agentUuid": "00000000-0000-0000-0000-000000000000",
"metadataKey": "capabilities",
"metadataValue": "{\"tasks\":[\"research\",\"summarization\"]}",
"metadataEncoding": "json"
}
```
## tx sign
Sign a prepared transaction locally with the configured private key. This step applies to `client-signed` execution only; in `brickken-relayed` mode Brickken signs the operation, so you skip signing and send the prepared `transactions` directly.
| Flag | Type | Required | Description |
| ------------------- | ------ | -------- | ---------------------------------------- |
| `-f, --file ` | string | No | File containing the prepared transaction |
```bash theme={null}
brickken tx sign --file prepared.json --json | tee signed.json
```
## tx send
Send signed transactions. `--tx-id` and `--signed-tx` are repeatable for batched sends.
| Flag | Type | Required | Description |
| --------------------- | ------ | -------- | --------------------------------------------- |
| `--tx-id ` | string | Yes¹ | Prepared transaction ID (repeatable) |
| `--signed-tx ` | string | Yes¹ | Signed transaction hex (repeatable) |
| `-f, --file ` | string | No | File containing `txId` / `signedTransactions` |
¹ Supply via flags or a `--file`.
```bash theme={null}
brickken tx send \
--tx-id "$(jq -r '.prepared.txId' prepared.json)" \
--signed-tx "$(jq -r '.signedTransaction' signed.json)" \
--json
```
API-key-authenticated Dapp sends use the API key's credits and do not need an x402 payment header. Relayed Agentic/RAMS sends still use x402, and x402 send batches must contain only x402-eligible prepared transactions on the same chain.
## tx status
Look up a broadcast transaction by its on-chain hash. Either `--hash` or `--tx-hash` is required.
| Flag | Type | Required | Description |
| ------------------ | ------ | -------- | ---------------------------------- |
| `--hash ` | string | Yes¹ | Actual blockchain transaction hash |
| `--tx-hash ` | string | Yes¹ | Alias for `--hash` |
¹ Provide one of the two.
```bash theme={null}
brickken tx status --hash 0xBlockchainTxHash --json
```
This maps to [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status).
## Manual three-step flow
When you want full control over each step:
```bash theme={null}
brickken tx prepare --method agentRegister --file agent-register.json --json
brickken tx sign --file prepared.json --json
brickken tx send --tx-id 0xPreparedTxId --signed-tx 0xSignedRawTx --json
```
# Agent & Token Workflow
Source: https://docs.brickken.com/cli/guides/agent-and-token-workflow
An end-to-end walkthrough: register an ERC-8004 agent, then deploy and manage its token with the Brickken CLI.
This guide runs a full lifecycle on Base Sepolia: register an agent, finalize its profile and metadata, then deploy and operate its token — all through x402.
It uses **`client-signed`** mode so you keep self-custody of signing — passing `--signer-address` (and `--agent-wallet`) selects it. For the hands-off path where Brickken's relayer signs and broadcasts, drop those flags and add `--execution-mode brickken-relayed` — see the [Quickstart](/cli/quickstart).
## Prerequisites
* The CLI is [installed](/cli/installation) and a private key is set (`BRICKKEN_PRIVATE_KEY`).
* The wallet holds enough Base Sepolia Circle USDC (`0x036CbD53842c5426634e7929541eC2318f3dCF7e`) to cover x402 send fees (`0.01 USDC` per send in sandbox) and a little native ETH for gas (client-signed mode).
* `jq` is available for reading `--json` output.
```bash theme={null}
export BRICKKEN_ENV="sandbox"
export CHAIN="84532" # Base Sepolia
export WALLET="0xYourWallet"
export BRICKKEN_RPC_URL="https://sepolia.base.org"
```
Each step below depends on the previous transaction being mined. Wait for confirmation before preparing the next dependent transaction — preparing them back-to-back can cause nonce conflicts.
## Part 1 — Register the agent
### 1. Register
```bash theme={null}
brickken agent register \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--name "Research Agent" \
--description "On-chain AI research agent" \
--image https://example.com/agent.png \
--service-name A2A \
--service-endpoint https://agent.example/.well-known/agent-card.json \
--service-version 0.3.0 \
--ai-model-provider OpenAI \
--ai-model-name "Research Model" \
--x402-support true \
--execute \
--json | tee register-output.json
export AGENT_UUID="$(jq -r '.prepared.info.agentUuid' register-output.json)"
echo "$AGENT_UUID"
```
### 2. Finalize the profile URI
After the registration transaction is mined:
```bash theme={null}
brickken agent set-uri \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-uuid "$AGENT_UUID" \
--name "Research Agent" \
--description "On-chain AI research agent" \
--image https://example.com/agent.png \
--service-name A2A \
--service-endpoint https://agent.example/.well-known/agent-card.json \
--service-version 0.3.0 \
--tag ai-agent \
--documentation https://docs.brickken.com \
--source-code https://github.com/Brickken/brickken-api-cli \
--license MIT \
--agent-type research \
--supported-trust feedback \
--x402-support true \
--active true \
--execute \
--json
```
### 3. Set structured metadata
After the URI transaction is mined:
```bash theme={null}
brickken agent set-metadata \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--agent-uuid "$AGENT_UUID" \
--metadata-key capabilities \
--metadata-value '{"tasks":["research","summarization","token-operations"]}' \
--metadata-encoding json \
--execute \
--json
```
The canonical identity flow is therefore: **`register` → wait → `set-uri` → wait → `set-metadata`**. See the [agent command reference](/cli/commands/agent) for every flag.
## Part 2 — Token lifecycle
### 4. Deploy the agent token
```bash theme={null}
brickken create-token \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--name "Research Agent Token" \
--symbol RAGT \
--agent-wallet "$WALLET" \
--premint 1000 \
--decimals 18 \
--execute \
--json | tee create-token-output.json
export TOKEN_ADDRESS="$(jq -r '.tokenAddress' create-token-output.json)"
echo "$TOKEN_ADDRESS"
```
Do not continue unless `TOKEN_ADDRESS` is populated. The CLI only adds `tokenAddress` after the deployment receipt is read from the RPC.
### 5. Mint
```bash theme={null}
brickken mint \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--to 0xRecipientWallet \
--amount 100 \
--decimals 18 \
--execute \
--json
```
### 6. Approve an allowance
```bash theme={null}
brickken approve \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--spender-address 0xSpenderWallet \
--amount 50 \
--decimals 18 \
--execute \
--json
```
### 7. Transfer
```bash theme={null}
brickken transfer \
--chain "$CHAIN" \
--signer-address "$WALLET" \
--token-address "$TOKEN_ADDRESS" \
--to 0xRecipientWallet \
--amount 10 \
--decimals 18 \
--execute \
--json
```
## Track a transaction
Check the status of any broadcast transaction by hash:
```bash theme={null}
brickken tx status --hash 0xBlockchainTxHash --json
```
## See also
Full reference for identity and reputation operations.
Every token command and flag.
Prepare, sign, send, and status for any method.
Backend field-level reference.
# RAMS Mandate Workflow
Source: https://docs.brickken.com/cli/guides/rams-mandate-workflow
End-to-end Ethereum Sepolia setup and execution for a compliant principal and AI-agent wallet.
This guide crosses several on-chain roles. Use separate keys for the ComplianceProvider owner, principal, agent, AgentExecutor owner, enforcer, and optional relayer. Never paste them into a shared shell history.
## Prerequisites
* `BRICKKEN_API_KEY` for reads and typed-data fetches
* Sepolia native gas for every client-signed role
* x402 payment asset for the wallet executing CLI sends
* AgentExecutor granted `RECORDER_ROLE` on AgentMandate
* A distinct `ENFORCER_ROLE` wallet (the registry admin cannot be its enforcer)
* Principal token allowance granted to the executor before value-moving execution
```bash theme={null}
export CHAIN=11155111
export PRINCIPAL=0x...
export AGENT=0x...
export ASSET=0x...
export IDENTITY_REF=0x... # 32 bytes
export EXECUTOR=0x...
```
## 1. Grant principal eligibility
Configure the ComplianceProvider owner key, then:
```bash theme={null}
brickken rams grant-principal \
--chain "$CHAIN" --signer-address "$COMPLIANCE_OWNER" \
--principal "$PRINCIPAL" --identity-ref "$IDENTITY_REF" \
--execute --json
```
Confirm it with `brickken rams compliance-status --chain "$CHAIN" --principal "$PRINCIPAL" --identity-ref "$IDENTITY_REF"`.
## 2. Sign and relay the mandate
With the principal key configured, create `signature.json` using [`rams sign`](/cli/commands/rams#rams-sign). Switch to the relayer/payer key and run [`rams grant`](/cli/commands/rams#relayed-grant-walkthrough) with the exact same fields, signature, and deadline.
Then inspect:
```bash theme={null}
brickken rams inspect --chain "$CHAIN" --agent "$AGENT" --principal "$PRINCIPAL" --json
```
## 3. Configure the executor
With the executor-owner key, register ERC-20 `transferFrom(address,address,uint256)` (`0x23b872dd`). Its amount is ABI word index `2`:
```bash theme={null}
brickken rams set-action \
--chain "$CHAIN" --signer-address "$EXECUTOR_OWNER" \
--executor-address "$EXECUTOR" --selector 0x23b872dd \
--supported true --has-amount true --amount-index 2 \
--execute --json
```
The principal must separately call `approve(EXECUTOR, allowance)` on `ASSET`.
## 4. Check and execute
```bash theme={null}
brickken rams can-execute \
--chain "$CHAIN" --agent "$AGENT" --principal "$PRINCIPAL" \
--asset "$ASSET" --amount 2500 --selector 0x23b872dd --json
brickken rams execute \
--chain "$CHAIN" --signer-address "$AGENT" \
--executor-address "$EXECUTOR" \
--asset "$ASSET" --from "$PRINCIPAL" --to "$RECIPIENT" --amount 2500 \
--execute --json
```
The execute command must use the agent key and cannot be Brickken-relayed.
## 5. Enforcement and lifecycle
An enforcer can freeze/unfreeze the agent globally:
```bash theme={null}
brickken rams freeze --chain "$CHAIN" --signer-address "$ENFORCER" --agent "$AGENT" --execute
brickken rams unfreeze --chain "$CHAIN" --signer-address "$ENFORCER" --agent "$AGENT" --execute
```
Finally, the principal or approved operator can revoke the mandate directly, or the principal can sign a relayed revocation. Re-run `inspect` and `can-execute`; a revoked mandate remains recorded but is inactive.
Do not run this sequence against the shared deployed contracts until the chain-ops roles and token allowance are confirmed. Failed on-chain writes can still consume native gas and x402 payment.
# Installation
Source: https://docs.brickken.com/cli/installation
Install the Brickken CLI from npm and verify your setup.
## Prerequisites
* **Node.js** 18 or newer (the CLI is distributed as an npm package).
* **`jq`** (optional but recommended) — the examples in these docs use it to read fields such as `agentUuid` and `tokenAddress` out of `--json` output.
## Install from npm
The CLI is published as [`brickken-cli`](https://www.npmjs.com/package/brickken-cli). Install it globally to get the `brickken` command:
```bash npm theme={null}
npm install -g brickken-cli
```
```bash pnpm theme={null}
pnpm add -g brickken-cli
```
```bash yarn theme={null}
yarn global add brickken-cli
```
## Verify the installation
```bash theme={null}
brickken --version
brickken --help
```
`brickken --version` prints the installed package version. `brickken --help` lists the global options and command groups.
## Build from source
To build a local checkout instead of installing from npm:
```bash theme={null}
git clone https://github.com/Brickken/brickken-api-cli.git
cd brickken-api-cli
pnpm install
pnpm build
node dist/index.js --help
```
## Next step
Set up your private key, RPC URL, and target environment before running commands.
# CLI
Source: https://docs.brickken.com/cli/introduction
Public Brickken CLI for the Dapp API, KYC, the Sandbox/Forge BKN faucet, agent getters, x402-paid writes, and ERC-8226 RAMS mandates.
The **Brickken CLI** is the public terminal client for the [Dapp API](/api-reference/introduction), KYC onboarding, the Sandbox/Forge BKN faucet, and the [Agentic API](/api-reference/endpoint/agentic-methods-x402). It supports Dapp API transaction methods through `brickken tx`, Dapp API JSON endpoints through `brickken dapp`, ERC-8004 on Base, and ERC-8226 RAMS mandates on Ethereum Sepolia. Client-controlled requests use an API key when configured and otherwise use x402 where supported; relayed sends always use x402.
Install `brickken-cli` from npm.
View the public source repository.
## Install
```bash theme={null}
npm install -g brickken-cli
brickken --version
brickken --help
```
You can also run it without a global install:
```bash theme={null}
npx brickken-cli --help
```
## Authentication
Dapp API requests and KYC require an API key. Client-controlled Agentic API and RAMS requests use the key when configured and otherwise fall back to x402. Agent getters and the BKN faucet use an API key when configured and support x402 where documented.
```bash theme={null}
export BRICKKEN_API_KEY=...
export BRICKKEN_PRIVATE_KEY=0x...
```
`BKN_API_KEY` and `BKN_PRIVATE_KEY` are accepted aliases. The private key signs the x402 payment, client-signed transactions, and requested RAMS typed data locally.
With `BRICKKEN_API_KEY` configured, the CLI can prepare and send Dapp API transaction methods and call Dapp API JSON endpoints. Multipart file uploads such as `/patch-token-docs` remain REST-only.
Never paste production private keys into shared terminals, tickets, or chat logs. Prefer environment variables or an `.env` file that is not committed.
## Environments
| Environment | Base URL |
| ------------------- | ---------------------------------- |
| `sandbox` (default) | `https://api.sandbox.brickken.com` |
| `production` | `https://api.brickken.com` |
```bash theme={null}
brickken --env sandbox --help
brickken --env production --help
```
An internal `forge` environment exists for Brickken pre-release QA — contact `tech@brickken.com` for its base URL.
Override the API base URL directly when needed:
```bash theme={null}
brickken --base-url https://api.sandbox.brickken.com --help
```
## Network and RPC
Pass the target operation chain with `--chain`. Decimal and hex values are accepted. The Agentic API runs on Base, with Base Sepolia for tests.
| Network | Decimal | Hex |
| ----------------------- | ---------- | ---------- |
| Base mainnet | `8453` | `0x2105` |
| Base Sepolia | `84532` | `0x14a34` |
| Ethereum Sepolia (RAMS) | `11155111` | `0xaa36a7` |
Some commands, especially `create-token --execute`, wait for a deployment receipt to recover `tokenAddress`. Set an RPC URL for that lookup:
```bash theme={null}
export BRICKKEN_RPC_URL="https://sepolia.base.org" # Base Sepolia
```
`BKN_RPC_URL` is accepted as an alias, or pass `--rpc-url`.
## Command Model
High-level commands are prepare-only by default. With an API key, client-controlled requests use API-key authentication; without one, eligible Agentic API and RAMS requests use x402. Relayed preparation is free and relayed sends use x402. Add `--execute` to also send in one step. Add `--json` for machine-readable output.
The recommended path is `brickken-relayed` mode: pass `--execution-mode brickken-relayed` and omit `--signer-address` — Brickken's relayer signs and broadcasts. The default is `client-signed`, where you provide `--signer-address` and the CLI signs the prepared transaction locally.
```bash theme={null}
# Prepare only (free in relayed mode), relayed execution
brickken create-token \
--chain 84532 \
--execution-mode brickken-relayed \
--name "Research Agent Token" \
--symbol RAGT
# Prepare + pay the send via x402, relayed mode
brickken create-token \
--chain 84532 \
--execution-mode brickken-relayed \
--name "Research Agent Token" \
--symbol RAGT \
--execute \
--json
```
## Commands
| Command | Backend method | Purpose |
| --------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------- |
| `brickken agent register` | `agentRegister` | Register an ERC-8004 agent identity. |
| `brickken agent set-uri` | `agentSetURI` | Update an agent URI/profile. |
| `brickken agent set-metadata` | `agentSetMetadata` | Write an agent metadata key/value. |
| `brickken agent set-wallet` | `agentSetWallet` | Update the agent operational wallet. |
| `brickken agent transfer-ownership` | `agentTransferOwnership` | Transfer the ERC-8004 identity to a new owner. |
| `brickken agent feedback give` | `agentGiveFeedback` | Submit reputation feedback. |
| `brickken agent feedback revoke` | `agentRevokeFeedback` | Revoke feedback. |
| `brickken agent feedback respond` | `agentAppendFeedbackResponse` | Respond to feedback. |
| `brickken create-token` | `agentCreateToken` | Deploy an agent-owned ERC-20 token. |
| `brickken mint` | `agentMintToken` | Mint an agent-owned token. |
| `brickken burn` | `agentBurnToken` | Burn an agent-owned token. |
| `brickken transfer` | `agentTransferToken` | Transfer an agent-owned token. |
| `brickken transfer-from` | `agentTransferFromToken` | Transfer through allowance. |
| `brickken approve` | `agentApproveToken` | Approve an allowance. |
| `brickken dapp get` | `GET ` | Call a Dapp API read endpoint with an API key. |
| `brickken dapp request` | `POST/PATCH ` | Call a Dapp API JSON endpoint with an API key. |
| `brickken rams ` | `rams*` / `GET /rams/*` | Manage ERC-8226 mandates, compliance, execution, reads, and signatures. |
| `brickken tx prepare --method ` | any supported method | Prepare a Dapp or Agentic API transaction; sends an API key when configured. |
| `brickken tx sign` | local only | Sign prepared transaction JSON locally. |
| `brickken tx send` | `POST /send-transactions` | Submit signed transactions. |
| `brickken tx status` | `GET /get-transaction-status` | Poll transaction status. |
| `brickken skill path` | local only | Print the bundled Brickken AI-agent skill path. |
| `brickken skill install` | local only | Install the bundled skill into an agent skills directory. |
See the complete [`brickken rams` command reference](/cli/commands/rams) and [end-to-end mandate workflow](/cli/guides/rams-mandate-workflow).
See the [Dapp API command reference](/cli/commands/dapp) for authenticated reads and JSON requests, and the [raw transaction reference](/cli/commands/tx) for tokenization and STO methods.
## AI Agent Skill
The npm package includes a Brickken skill at `skills/brickken`, built on the open [Agent Skills](https://agentskills.io) format and compatible with any agent that supports it — Claude Code, OpenAI Codex, Gemini CLI, Cursor, GitHub Copilot, and more. Use it when an AI agent needs to choose between the Dapp API, Agentic API, CLI, or MCP.
For standalone installation without a global CLI install, see the [Skill documentation](/skill/introduction).
After installing `brickken-cli`, install the skill into the default skills directory (`~/.codex/skills`):
```bash theme={null}
brickken skill install
```
Or pass `--path` to target your agent's skills directory (for example `~/.claude/skills` for Claude Code, `~/.gemini/skills` for Gemini CLI, `~/.cursor/skills` for Cursor):
```bash theme={null}
brickken skill install --path ~/.claude/skills --force
```
To inspect where the bundled skill lives in the installed package:
```bash theme={null}
brickken skill path
```
Without a global install:
```bash theme={null}
npx brickken-cli skill install --path ~/.claude/skills --force
```
## Agent Example
```bash theme={null}
export CHAIN="84532" # Base Sepolia
brickken agent register \
--chain "$CHAIN" \
--execution-mode brickken-relayed \
--name "Research Agent" \
--description "On-chain AI research agent" \
--image https://example.com/agent.png \
--service-name A2A \
--service-endpoint https://agent.example/.well-known/agent-card.json \
--ai-model-provider OpenAI \
--ai-model-name "Research Model" \
--x402-support true \
--execute \
--json
```
## File Input
Use `--file` for nested JSON/YAML payloads, long metadata, or automation:
```bash theme={null}
brickken tx prepare \
--method agentSetMetadata \
--file metadata.json \
--execute \
--json
```
Relayed preparation is free and the full operation is x402-priced at send. Client-controlled modes split the operation charge between prepare and send. Fund the wallet behind `BRICKKEN_PRIVATE_KEY` with enough USDC on the x402 payment chain (e.g. Circle USDC on Base Sepolia). In `brickken-relayed` mode Brickken's relayer pays native gas; in `client-signed` mode you also need native gas on the operation chain.
# Quickstart
Source: https://docs.brickken.com/cli/quickstart
Set up your environment and run your first end-to-end Brickken CLI transaction.
This quickstart runs a single agentic transaction end-to-end on Base Sepolia using x402, in the recommended `brickken-relayed` mode (Brickken signs and broadcasts).
## 1. Install and authenticate
If you have not already, [install the CLI](/cli/installation) and set up a private key:
```bash theme={null}
npm install -g brickken-cli
export BRICKKEN_PRIVATE_KEY=0x...
```
## 2. Set your environment
```bash theme={null}
export BRICKKEN_ENV="sandbox"
export CHAIN="84532" # Base Sepolia
export BRICKKEN_RPC_URL="https://sepolia.base.org"
```
Fund the wallet behind `BRICKKEN_PRIVATE_KEY` with a small amount of Base Sepolia Circle USDC (`0x036CbD53842c5426634e7929541eC2318f3dCF7e`) so it can pay the x402 send fee. In `brickken-relayed` mode Brickken's relayer covers native gas.
## 3. Sanity checks
```bash theme={null}
brickken --version
test -n "$BRICKKEN_PRIVATE_KEY" && echo "private key ok" || echo "private key missing"
test -n "$BRICKKEN_RPC_URL" && echo "rpc ok" || echo "rpc missing"
command -v jq
```
## 4. Deploy a token end-to-end
Relayed preparation is free; the `--execute` flag also sends and pays the full x402 charge in one step. Client-controlled modes charge the prepare share before execution. With `--execution-mode brickken-relayed` you omit `--signer-address` and `--agent-wallet` — Brickken's relayer signs, pays gas, and becomes the token owner. The `--json` flag makes the output machine-readable so you can pipe it into `jq`.
```bash theme={null}
brickken create-token \
--chain "$CHAIN" \
--execution-mode brickken-relayed \
--name "Quickstart Token" \
--symbol QST \
--premint 1000 \
--decimals 18 \
--execute \
--json | tee create-token-output.json
```
When `create-token --execute` succeeds, the CLI waits for the deployment receipt and adds `tokenAddress` to the JSON output. Capture it for follow-up commands:
```bash theme={null}
export TOKEN_ADDRESS="$(jq -r '.tokenAddress' create-token-output.json)"
echo "$TOKEN_ADDRESS"
```
Echo critical variables such as `TOKEN_ADDRESS` and `AGENT_UUID` before reusing them. If a command seems to "drop" fields, the usual cause is shell expansion or quoting — not `--json`. Quote every value that can contain spaces, and prefer [`--file`](/cli/commands/tx) for nested JSON.
## What's next
Register an ERC-8004 agent and manage its reputation.
Mint, burn, transfer, and approve agentic tokens.
Manage compliance-gated ERC-8226 mandates on Ethereum Sepolia.
A full agent registration and token lifecycle walkthrough.
Set up compliance, sign a relayed mandate, configure an executor, and execute.
# Agentic Challenge — Hello World
Source: https://docs.brickken.com/get-started/build-programme/agentic-hello-world
Register an ERC-8004 agent and deploy its token with the Brickken CLI.
This walkthrough is the first step for the **Agentic Challenge**. You will use the Brickken CLI and x402 on Base Sepolia to register an ERC-8004 agent and deploy an ERC-20 owned by your wallet.
This path uses explicit `client-signed` execution. Your wallet signs the x402 payment and the blockchain transaction, while Brickken broadcasts the signed operation. It gives you ownership of the agent identity and token, but requires both Base Sepolia ETH for gas and Circle USDC for x402 payments.
## Outcome
At the end, your terminal will show:
* a confirmed ERC-8004 agent registration and `agentUuid`;
* the stored agent profile read back through the Agentic API;
* a confirmed agent-owned ERC-20 deployment and `tokenAddress`;
* x402 settlement metadata for the executed operations.
The complete runnable sample is in the public [Agentic Hello World example](https://github.com/fbrickken/docs/tree/main/examples/build-programme/agentic-hello-world).
## Estimated time
Allow 15–20 minutes for setup, faucet funding, two x402 payments, and confirmation on Base Sepolia.
## Prerequisites
Use the version validated for this programme:
```bash theme={null}
npm install -g brickken-cli@0.4.13
brickken --version
```
Set `BRICKKEN_PRIVATE_KEY` and the corresponding address in `WALLET`. Use a testnet-only key and never commit the `.env` file.
Get Circle USDC on Base Sepolia from the [Circle faucet](https://faucet.circle.com/). The payment asset, amount, recipient, and timeout are quoted live by x402; do not hardcode them.
Get Base Sepolia ETH from one of the sources in the [official Base faucet list](https://docs.base.org/base-chain/network-information/network-faucets). Client-signed mode uses your wallet to pay gas.
The sample uses the public fixtures below so the registration request is runnable without inventing an image or service URL:
* Image: `https://docs.brickken.com/images/build-programme/hello-world-agent.svg`
* Service endpoint: `https://docs.brickken.com/downloads/build-programme/agent-card.json`
## Setup
Clone or download the [example directory](https://github.com/fbrickken/docs/tree/main/examples/build-programme/agentic-hello-world), then run:
```bash theme={null}
cp .env.example .env
# Edit .env. WALLET must correspond to BRICKKEN_PRIVATE_KEY.
```
The environment contract is:
```text theme={null}
BRICKKEN_ENV=sandbox
BRICKKEN_PRIVATE_KEY=0x...
BRICKKEN_RPC_URL=https://sepolia.base.org
WALLET=0x...
```
Optional variables let you replace the example agent name, image, service endpoint, and token symbol.
## Run
Execute the pinned CLI workflow:
```bash theme={null}
./run.sh
```
## What the script does
1. `brickken agent register` prepares and executes an ERC-8004 registration on Base Sepolia with `--execution-mode client-signed`.
2. The script captures `agentUuid` and the blockchain transaction hash, then polls the Base Sepolia RPC until the receipt succeeds.
3. `brickken agent info` reads the stored profile. Without an API key, this getter uses x402 with the configured wallet.
4. `brickken create-token` deploys an ERC-20 with the same wallet passed as `--signer-address` and `--agent-wallet`.
5. The CLI waits for the deployment receipt and exposes `tokenAddress`; the script checks the x402 settlement and address format.
For client-controlled modes, x402 pricing is split between prepare and send. The CLI performs both payment handshakes locally and reads the live quote, so the example does not assume a fixed amount or payment token. See [Agentic pricing](/api-reference/endpoint/agentic-pricing) for the execution-mode matrix.
## Expected output
The script writes JSON files under `out/` and prints a summary similar to:
```text theme={null}
Hello World complete
Agent UUID: 00000000-0000-0000-0000-000000000000
Agent registration tx: 0x...
Agent token: 0x...
Agent token deployment tx: 0x...
```
## Verification
Inspect the sanitized fields in `out/register-output.json`, `out/agent-info-output.json`, and `out/create-token-output.json`:
* `prepared.info.agentUuid` exists;
* the registration receipt has status `0x1`;
* the registration send includes successful x402 settlement metadata;
* the profile read returns the same agent reference;
* `sent.success` is `true` for token deployment;
* `tokenAddress` is a 40-hex-character address;
* `tokenReceipt.status` is `0x1` and `tokenTxHash` identifies the deployment receipt;
* `sent._x402.settlement.success` is `true`.
## Troubleshooting
| Symptom | Check |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `brickken-cli is required` | Install the pinned `brickken-cli@0.4.13` package and confirm `brickken --version`. |
| `image is required` or service validation fails | Keep the public fixture URLs or replace them with reachable HTTPS URLs. |
| x402 payment fails | Confirm the wallet has the exact quoted Base Sepolia USDC asset and retry only after checking the quote. |
| Client transaction fails for gas | Fund the same `WALLET` with Base Sepolia ETH and confirm it matches the private key. |
| Agent profile read is empty | Wait for the registration receipt before calling `agent info`; do not prepare dependent operations against a pending identity. |
| Token address is missing | Keep `BRICKKEN_RPC_URL` set so the CLI can inspect the deployment receipt. |
## Security
* Use a disposable Base Sepolia wallet and keep the private key in an environment variable or secret manager.
* Review the live x402 quote before approving each payment; the CLI reads the amount, asset, recipient, and timeout from the challenge.
* Check chain, signer, agent wallet, token symbol, and recipient before executing a write.
* Do not commit `.env` or the generated `out/` JSON files.
## Next challenge ideas
Next, add [`agent set-uri`](/cli/commands/agent#agent-set-uri) and [`agent set-metadata`](/cli/commands/agent#agent-set-metadata), then exercise the token lifecycle with [`mint`](/cli/commands/token-economics#mint), [`approve`](/cli/commands/token-economics#approve), and [`transfer`](/cli/commands/token-economics#transfer). For compliance-gated delegation, continue to the [RAMS mandate workflow](/cli/guides/rams-mandate-workflow). MCP users can reach the same Agentic API through the [hosted MCP server](/mcp/introduction).
See the longer CLI lifecycle walkthrough.
Build the direct API path for tokenized assets and STOs.
# API Challenge — Hello World
Source: https://docs.brickken.com/get-started/build-programme/api-hello-world
Create and verify your first tokenized asset with the Brickken Dapp API.
This walkthrough is the first step for the **API Challenge**. You will create one sandbox tokenized asset with direct HTTP requests, sign the prepared transaction locally, and verify the confirmed symbol through the API.
This is a sandbox walkthrough. It uses one `newTokenization` credit and native Sepolia gas. It does not use the Brickken SDK, so you can see the underlying prepare → sign → send → poll flow used by a direct integration.
## Outcome
At the end, your terminal will show:
* a confirmed Brickken transaction ID and blockchain transaction hash;
* the wallet that signed the transaction;
* the generated token symbol;
* a `GET /get-token-info` response containing that symbol.
The complete runnable sample is in the public [API Hello World example](https://github.com/fbrickken/docs/tree/main/examples/build-programme/api-hello-world).
## Estimated time
Allow 10–15 minutes for setup and one sandbox tokenization, depending on wallet funding and API-key approval.
## Prerequisites
[Request a sandbox API key](/get-started/request-api-key) with the email of the tokenizer account. Your key needs one `newTokenization` credit.
Ask Brickken to whitelist the wallet you will use as `signerAddress` in the same key request. The API rejects an unknown signer before it prepares a transaction.
The wallet signs the prepared transaction and pays native gas on Ethereum Sepolia. Use a testnet-only wallet.
The sample uses Node's native `--env-file`, `fetch`, and local `ethers` signing.
Never commit `.env`, an API key, or a private key. The private key is used only by the local signer and is never sent to Brickken.
## Setup
Clone or download the [example directory](https://github.com/fbrickken/docs/tree/main/examples/build-programme/api-hello-world), then run:
```bash theme={null}
cp .env.example .env
# Edit .env with your sandbox values before continuing.
npm ci
```
The environment contract is:
```text theme={null}
BRICKKEN_API_KEY=your-sandbox-api-key
BRICKKEN_PRIVATE_KEY=0x...
BRICKKEN_TOKENIZER_EMAIL=issuer@example.com
BRICKKEN_BASE_URL=https://api.sandbox.brickken.com
```
## Run
Start the direct API integration:
```bash theme={null}
npm start
```
The program generates a unique 2–5 character uppercase symbol, derives the signer address from the private key, and sends the following logical operation:
```json theme={null}
{
"method": "newTokenization",
"chainId": "11155111",
"tokenizerEmail": "issuer@example.com",
"signerAddress": "0xYourWhitelistedWallet",
"name": "Hello World Asset H123",
"tokenSymbol": "H123",
"tokenType": "RWA_TOKEN",
"supplyCap": "1000000",
"url": "https://docs.brickken.com/get-started/build-programme/api-hello-world"
}
```
## What the code does
1. `POST /prepare-transactions` returns unsigned transactions and an internal `txId`. Preparing does not touch the chain.
2. `ethers` signs every returned transaction locally with the wallet matching `signerAddress`.
3. `POST /send-transactions` receives `{ txId, signedTransactions }` and broadcasts the signed payload.
4. `GET /get-transaction-status?txId=...` is polled until the status is `success`.
5. `GET /get-token-info` confirms that the new symbol is available to the API key.
The program fails on a rejected transaction, a polling timeout, an HTTP error, or a missing token symbol in the final read. It prints structured JSON without printing credentials.
## Expected result
Values vary on every run. The shape is similar to:
```json theme={null}
{
"chainId": "11155111",
"signerAddress": "0x...",
"tokenSymbol": "H123",
"txId": "0x...",
"txHash": "0x...",
"status": "success",
"tokenInfo": {
"tokenSymbols": ["H123"]
}
}
```
The API's canonical transaction flow and response contract are documented in the [Dapp API reference](/api-reference/introduction) and [Get Transaction Status](/api-reference/endpoint/get-transaction-status).
## Verification
```bash theme={null}
npm run check
```
The check runs TypeScript type-checking and mocked tests for:
* prepare and send requests;
* pending → success polling;
* rejected transactions;
* polling timeouts;
* required environment variables;
* final token readback.
## Troubleshooting
| Symptom | Check |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `BRICKKEN_API_KEY is required` | Copy `.env.example` to `.env` and set the sandbox key. |
| Prepare rejects `signerAddress` | Ask Brickken to whitelist the exact wallet derived from `BRICKKEN_PRIVATE_KEY`. |
| `Out of credits for newTokenization` | Request a key with an available sandbox `newTokenization` credit. |
| The transaction is rejected | Confirm the wallet has Sepolia ETH and that the key, tokenizer email, and signer belong to the same sandbox account. |
| The final read cannot find the symbol | Wait for `status: success`; do not reuse a symbol from a failed or pending run. |
## Security
* Use a disposable Sepolia wallet and keep the private key in a local environment variable or secret manager.
* Review the request body and derived signer address before approving a sandbox run.
* Treat the API key and tokenizer email as credentials; do not include them in screenshots or support tickets.
* The run consumes one `newTokenization` sandbox credit and native Sepolia gas.
## Next challenge ideas
Once this works, extend the same lifecycle with investor operations: [whitelist an investor](/api-reference/endpoint/prepare-whitelist), [mint tokens](/api-reference/endpoint/prepare-mintToken), and then follow the full [tokenize-and-run-an-STO guide](/api-reference/guides/tokenize-and-run-an-sto) for reporting and offering automation.
Explore every Dapp API method and read endpoint.
Try the x402-powered CLI path for ERC-8004 and agent-owned tokens.
# Choose your surface
Source: https://docs.brickken.com/get-started/choose-your-surface
Five ways to call the same Brickken backend — and which one fits what you are building.
The REST API, the SDK, the CLI, the MCP server, and the Skill all talk to the same backend at `api.brickken.com`. They differ in who is driving and which credential they carry.
## Start from what you already have
| You have | Use | Because |
| ------------------------------------ | ------------------------------------ | -------------------------------------------------------------- |
| An API key and a TypeScript codebase | **SDK** | Typed client for the whole platform, running in your process |
| An API key and any other stack | **REST API** | Plain HTTP reaches everything |
| An API key and a terminal | **CLI** | Dapp transaction methods and JSON endpoints from your terminal |
| A funded wallet and no API key | **SDK**, **Agentic API**, or **CLI** | Pay per call with x402; no account needed |
| An MCP-capable AI agent | **MCP** | One hosted endpoint, 62 tools, credentials set per session |
| A terminal and an agentic workflow | **CLI** | `npm i -g brickken-cli`, then one command per operation |
| An AI coding agent, any of the above | **Skill** | Teaches the agent when to use which surface |
## The five surfaces
Plain HTTP. Everything the platform can do. API key for the Dapp API, x402 or API key for agentic methods.
`brickken-sdk` on npm. Typed TypeScript client for the Dapp API, the Agentic API, and RAMS, in your own process.
Hosted at `https://mcp.brickken.com/mcp`. The client to use when an **AI agent** should drive the full Dapp API with just an API key.
`brickken-cli` on npm. Dapp API, KYC, the Sandbox/Forge BKN faucet, agentic, and RAMS workflows from your terminal.
Brickken knowledge for AI coding agents, with or without the CLI installed.
## What each surface can reach
| | REST | SDK | MCP | CLI | Skill |
| --------------------------------------- | :-------: | :-------: | :----------------: | :------------------------------: | :--------------: |
| Dapp API writes | Yes | Yes | Yes | Yes | Guides the agent |
| Dapp API reads | Yes | Yes | Yes | Yes | Guides the agent |
| KYC link creation | Yes | Yes | Yes | Yes | Guides the agent |
| BKN faucet (Sandbox/Forge) | Yes | Yes | Yes | Yes | Guides the agent |
| Agent getters | Yes | Yes | Yes | Yes | Guides the agent |
| Agentic writes (ERC-8004, agent tokens) | Yes | Yes | Yes | Yes | Guides the agent |
| RAMS writes | Yes | Yes | Yes | Yes | Guides the agent |
| RAMS reads | Yes | Yes | Yes | Yes | Guides the agent |
| Accepts an API key | Yes | Yes | Yes | Dapp API, KYC, faucet, and reads | — |
| Pays with x402 | Yes | Yes | Yes | Yes | — |
| Where it runs | Your code | Your code | Hosted by Brickken | Your machine | Your agent |
The CLI reaches the Dapp API with `BRICKKEN_API_KEY`: use `brickken tx prepare --method ` for tokenization, STO, and security-token transaction methods, and `brickken dapp get` for Dapp reads. Multipart file uploads such as `/patch-token-docs` remain REST-only.
For Dapp API work, use the **SDK** if you write TypeScript, **MCP** if an agent is driving, or plain **HTTP** otherwise.
## SDK or MCP for the Dapp API?
Both reach the full Dapp API with nothing but an API key. The difference is who is holding the credential:
* **SDK** — your code holds the key, and every call is typed and testable. Illegal credential combinations fail locally, before a request leaves your process.
* **MCP** — a hosted endpoint holds nothing; each session supplies its own credentials, and an AI agent picks the tools. Right when the driver is an agent rather than a program you wrote.
## Same backend, same rules
Whichever surface you pick, the mechanics are identical: writes are **prepared** into unsigned transactions, **signed**, then **sent**; preparing a relayed agentic operation is free and only the send costs anything; and your private key never leaves your machine.
The surface changes the ergonomics, not the semantics — you can prepare with the CLI and send with curl.
The credential matrix in full.
A first call on each surface.
# Quickstart
Source: https://docs.brickken.com/get-started/quickstart
Make your first Brickken call on whichever surface you picked.
Five first calls, one per surface. All of them run against **sandbox** — nothing here moves real value.
Start with a read that needs no key at all, to confirm you can reach the API:
```bash theme={null}
curl 'https://api.sandbox.brickken.com/get-network-info?chainId=11155111'
```
Then a read that does need one:
```bash theme={null}
curl 'https://api.sandbox.brickken.com/get-token-info?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY'
```
Now prepare a write. This returns unsigned transactions and a `txId` — nothing is on-chain yet:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/prepare-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"chainId": "11155111",
"method": "newTokenization",
"tokenizerEmail": "issuer@example.com",
"signerAddress": "0xYourWhitelistedWallet",
"name": "Example Asset",
"tokenSymbol": "EXMPL",
"tokenType": "RWA_TOKEN",
"supplyCap": "1000000",
"url": "https://example.com/token-docs"
}'
```
Sign each returned transaction with the wallet matching `signerAddress`, then send:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_BRICKKEN_API_KEY' \
--data '{
"txId": "0xPreparedTransactionId",
"signedTransactions": ["0xSignedRawTransaction"]
}'
```
Poll `GET /get-transaction-status` until it confirms.
`signerAddress` must be whitelisted by Brickken first. Ask for it when you [request your key](/get-started/request-api-key).
The x402 facade prepares a relayed operation without a credential. Try it right now:
```bash theme={null}
curl --request POST 'https://api.sandbox.brickken.com/x402/agent/register' \
--header 'Content-Type: application/json' \
--data '{
"chainId": "84532",
"executionMode": "brickken-relayed",
"name": "Research Agent",
"description": "Autonomous research agent",
"image": "https://example.com/agent.png",
"services": [
{
"name": "A2A",
"endpoint": "https://agent.example/.well-known/agent-card.json",
"version": "0.3.0"
}
],
"aiModelName": "Research Model",
"aiModelProvider": "OpenAI",
"x402Support": true,
"active": true
}'
```
The response carries `txId`, one prepared `transactions` entry, and an `x402Requirements` preview of what the send will cost.
Send it. The first attempt is meant to fail:
```bash theme={null}
curl -i --request POST 'https://api.sandbox.brickken.com/send-transactions' \
--header 'Content-Type: application/json' \
--data '{ "txId": "0xPreparedTransactionId", "transactions": [ { "to": "0xRegistry", "data": "0x...", "value": "0x0" } ] }'
```
You get `402 Payment Required` with a `PAYMENT-REQUIRED` header. Sign that payment locally with your funded wallet and retry with `X-PAYMENT`. Brickken's relayer then signs, pays the gas, and broadcasts.
Fund the wallet with Base Sepolia USDC first — the exact asset and amount are in the header.
```bash theme={null}
npm install brickken-sdk
```
A Dapp read with an API key:
```ts theme={null}
import { Brickken } from 'brickken-sdk'
const bkn = new Brickken({ env: 'sandbox', apiKey: process.env.BRICKKEN_API_KEY })
const token = await bkn.tokenization.info({ tokenSymbol: 'EXMPL' })
const offerings = await bkn.sto.list({ tokenSymbol: 'EXMPL' })
```
Or an agentic write with a wallet and no API key. Preparing is free in relayed mode; `execute: true` also pays and sends:
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const bkn = new Brickken({
env: 'sandbox',
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
payment: { maxAmountBaseUnits: '50000' },
})
const agent = await bkn.agent.register(
{
chainId: '84532',
name: 'Research Agent',
image: 'https://example.com/agent.png',
serviceName: 'A2A',
serviceEndpoint: 'https://agent.example/.well-known/agent-card.json',
},
{ execute: true },
)
console.log(agent.info?.agentUuid)
```
The SDK is the only typed client that reaches the Dapp API from your own code. See the [SDK quickstart](/sdk/quickstart).
```bash theme={null}
npm install -g brickken-cli
```
```bash theme={null}
export BRICKKEN_PRIVATE_KEY=0x...
export BRICKKEN_RPC_URL="https://sepolia.base.org"
```
Prepare only — free in relayed mode, nothing sent:
```bash theme={null}
brickken create-token --chain 84532 --execution-mode brickken-relayed --name "Research Agent Token" --symbol RAGT
```
Add `--execute` to prepare, pay the x402 charge, and broadcast in one step:
```bash theme={null}
brickken create-token --chain 84532 --execution-mode brickken-relayed --name "Research Agent Token" --symbol RAGT --execute --json
```
The CLI provides Dapp API, Agentic API, RAMS, KYC, and Sandbox/Forge BKN faucet workflows. Use `brickken tx prepare --method ` for Dapp tokenization/STO transactions and `brickken dapp get` for Dapp reads.
Add the hosted server to your MCP client:
```json theme={null}
{
"mcpServers": {
"brickken": {
"url": "https://mcp.brickken.com/mcp"
}
}
}
```
Configure the session with the `configure` tool. With an API key you get the full Dapp API:
```json theme={null}
{
"env": "sandbox",
"apiKey": "YOUR_BRICKKEN_API_KEY"
}
```
Then ask the agent to call `get_stos`, `get_token_info`, or `create_tokenization`.
For x402 agentic workflows instead, clear the key and set a private key:
```json theme={null}
{
"env": "sandbox",
"privateKey": "0xYOUR_PRIVATE_KEY",
"apiKey": ""
}
```
Verify with `get_config` — it reports `hasApiKey` and `hasPrivateKey` as booleans, never the values.
## Where next
Every capability, and which client reaches it.
Credentials, the 402 handshake, plans, limits, and errors.
Every tokenization, STO, and read endpoint.
Ready-to-run requests for every endpoint.
Create and verify a sandbox tokenized asset with direct HTTP requests.
Register an ERC-8004 agent and deploy its token with the CLI.
# Sandbox
Source: https://docs.brickken.com/get-started/sandbox
Fund a test wallet, reach the right storefront, and create a test investor without a KYC document.
Sandbox is a full deployment of the Brickken platform on public testnets. Everything you build
against it uses the same API, the same methods, and the same contracts as production.
| Environment | API base URL | App URL |
| ----------- | ---------------------------------- | ----------------------------------- |
| Sandbox | `https://api.sandbox.brickken.com` | `https://dapp.sandbox.brickken.com` |
| Production | `https://api.brickken.com` | `https://dapp.brickken.com` |
Sandbox and production are separate deployments with separate databases. An API key issued for one does not work on the other.
## Sandbox is a separate world
Sandbox and production have separate databases, separate API keys, and separate contract
deployments. An asset created in Sandbox does not exist in production, and vice versa.
That extends to the web surfaces, which is the single most common source of confusion:
| Surface | Sandbox host |
| ---------------- | --------------------------------------------- |
| API | `https://api.sandbox.brickken.com` |
| Dashboard | `https://dapp.sandbox.brickken.com` |
| Asset storefront | `https://.store.sandbox.brickken.com` |
The `sandbox` label comes **after** `store` — `tusc.store.sandbox.brickken.com`, not
`sandbox.tusc.store.brickken.com`. The production storefront will happily load its application
shell for any host, so a wrong URL looks like a broken page rather than a wrong environment.
Symptoms of using a production host for a Sandbox asset are an investor page stuck on **Loading
Secure Environment**, an Investor Hub that never finishes loading, and `License for user not
found`.
The KYC widget resolves which asset it is verifying for from the host it is served from. On a
generic host that lookup returns nothing and the widget spins forever. Start the KYC flow from the
asset's own storefront.
## Networks
| Network | Decimal | Hex |
| -------------------- | ---------- | ---------- |
| Ethereum mainnet | `1` | `0x1` |
| Base mainnet | `8453` | `0x2105` |
| BNB Smart Chain | `56` | `0x38` |
| Polygon mainnet | `137` | `0x89` |
| Sepolia testnet | `11155111` | `0xaa36a7` |
| Polygon Amoy testnet | `80002` | `0x13882` |
Pass `chainId` as decimal or hex. Client tooling normalizes common values.
Sandbox assets in this guide use Ethereum Sepolia (`11155111` / `aa36a7`). Every wallet that signs
a transaction needs Sepolia ETH for gas, from any public Sepolia faucet.
## Payment tokens
Sandbox uses its own payment-token registry. A token you obtained from an unrelated public faucet
will not match the contract the escrow actually pulls from, which is why generic "Sepolia USDT"
never works.
### Resolve the token from the API
Always let the API tell you which contract an asset takes as payment, rather than hardcoding one.
Different assets can be configured with different payment tokens.
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-tokenizer-info?tokenSymbol=EXMPL' \
--header 'x-api-key: YOUR_API_KEY'
```
`paymentTokenAddress` in the response is the authoritative value for that asset. The `newInvest`
prepare response also carries `paymentTokenAddress` and `paymentTokenSymbol` for the specific
offering.
### Registered Sepolia payment tokens
These addresses are a convenience for funding a wallet by hand. They can change — one of them
already has. Resolve the payment token through the API before you invest, and never hardcode an
address in application code.
| Symbol | Contract | Decimals | How to get test funds |
| ------ | -------------------------------------------- | -------- | --------------------------------------------------------------------- |
| `USDT` | `0x28d2B01854D0aBec267a3DDcad9163580E6E8604` | 6 | Request test funds from [tech@brickken.com](mailto:tech@brickken.com) |
| `USDC` | `0xb10cE8e28aEb1ae27b968Fb3bfed2FD7dd52daCb` | 6 | Request test funds from [tech@brickken.com](mailto:tech@brickken.com) |
| `BKN` | `0x2458fB1620ff84019d73216fF20aA1F82Bc8E4CC` | 18 | See [BKN Faucet](/api-reference/endpoint/bkn-faucet) |
`USDT` is the default payment token on Sepolia when a request does not specify one, so it is the
path of least resistance for testing.
To fund a test wallet, send the wallet address and the amount you need to
[tech@brickken.com](mailto:tech@brickken.com).
These are the payment tokens of the Dapp API. The Agentic API settles x402 payments on a separate
rail with its own assets, including Circle's own testnet USDC, so an address you see quoted for an
x402 payment is not interchangeable with the ones above.
## Skip KYC while you build
**Do not run the KYC flow for your test investors.** Sandbox KYC is a real Sumsub verification with
a document upload, and it proves nothing about your integration. Create investors with
`needKyc: false` and the compliance gate is satisfied from the start — no documents, no waiting, and
a fresh test investor whenever you need one.
`needKyc` is accepted on [`create-kyc-link`](/api-reference/endpoint/create-kyc-link), on each
`userToWhitelist` entry of the [`whitelist`](/api-reference/endpoint/prepare-whitelist) method, and
on each `userToMint` entry of [`mintToken`](/api-reference/endpoint/prepare-mintToken).
```bash theme={null}
curl --request POST \
--url 'https://api.sandbox.brickken.com/create-kyc-link' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "builder+sbx1@example.com",
"needKyc": false,
"walletAddress": "0x1111111111111111111111111111111111111111"
}'
```
```bash theme={null}
brickken kyc create-link --email builder+sbx1@example.com --need-kyc false
```
Confirm the result before going further:
```bash theme={null}
curl --request GET \
--url 'https://api.sandbox.brickken.com/get-investor-info?tokenSymbol=EXMPL&email=builder%2Bsbx1@example.com' \
--header 'x-api-key: YOUR_API_KEY'
```
`complianceStatus` should read `NOT_REQUIRED`, and `walletAddress` should be the address you
passed. An investor with a null `walletAddress` cannot invest.
`needKyc: false` is only applied when the investor record is created. For an email that already
has an account the stored value wins and cannot be downgraded, so use a fresh address — a `+`
alias such as `builder+sbx2@example.com` is enough.
### Rehearse the real flow once, before production
`needKyc: false` is a Sandbox affordance. In production the request is rejected with
`needKyc=false is only available in the sandbox environment`, so every real investor goes through
Sumsub.
That makes one rehearsal worthwhile before you go live — enough to see the verification screens your
investors will meet and to confirm your polling of `complianceStatus` behaves. A sample document
image is enough to reach a green applicant in the Sandbox tenant; no genuine liveness check is
required.
Never upload real identity documents to a test account.
KYC and whitelisting are independent. KYC is an off-chain, per-investor compliance record keyed
by email. Whitelisting is an on-chain, per-token permission keyed by wallet address. Whitelisting
a wallet does not approve KYC, and passing KYC does not whitelist a wallet — an offering needs
both.
## Identities are shared across the environment
A Brickken account is one identity for the whole Sandbox environment, not one per asset:
* Login is global.
* KYC is global — one record per email, reused by every asset that investor touches.
* Whitelisting is **per asset** — each token tracks its own relationship with an investor.
An email already registered as a tokenizer cannot also be onboarded as an investor. Give test
investors their own email, separate from the account you issue with; otherwise investor lookups
return `Investor not found`.
Decode a failed call, from validation errors to raw revert data.
The full lifecycle, end to end.
# What you can do
Source: https://docs.brickken.com/get-started/what-you-can-do
Every capability the Brickken APIs expose, and which client can reach it.
Brickken exposes two products through one API host:
* **The Dapp API** tokenizes real-world assets and runs everything that follows — offerings, investors, dividends, compliance. It is authenticated with an API key.
* **The Agentic API** gives AI agents an on-chain identity, their own tokens, and delegated spending authority. It is paid per call with x402, and most of it also accepts an API key.
Everything below is a real endpoint today. Where a client cannot reach a capability, the table says so.
## Tokenize and operate a real-world asset
The Dapp API's core loop. Every write follows the same shape: **prepare** an unsigned transaction, **sign** it with your whitelisted wallet, **send** it.
| Capability | Method | HTTP | SDK | MCP | CLI |
| ----------------------------------- | ------------------------- | :--: | :-: | :-: | :-: |
| Create a tokenized asset | `newTokenization` | Yes | Yes | Yes | Yes |
| Mint tokens | `mintToken` | Yes | Yes | Yes | Yes |
| Burn tokens | `burnToken` | Yes | Yes | Yes | Yes |
| Whitelist or remove an investor | `whitelist` | Yes | Yes | Yes | Yes |
| Transfer tokens | `transferTo` | Yes | Yes | Yes | Yes |
| Transfer through an allowance | `transferFrom` | Yes | Yes | Yes | Yes |
| Approve an allowance | `approve` | Yes | Yes | Yes | Yes |
| Distribute dividends | `dividendDistribution` | Yes | Yes | Yes | Yes |
| Update token documents and branding | `PATCH /patch-token-docs` | Yes | Yes | Yes | No |
## Run a Security Token Offering
| Capability | Method | HTTP | SDK | MCP | CLI |
| -------------------------------- | ------------- | :--: | :-: | :-: | :-: |
| Launch an offering | `newSto` | Yes | Yes | Yes | Yes |
| Take an investment | `newInvest` | Yes | Yes | Yes | Yes |
| Let investors claim their tokens | `claimTokens` | Yes | Yes | Yes | Yes |
| Close the offering | `closeOffer` | Yes | Yes | Yes | Yes |
## Read platform state
Thirteen read endpoints cover chains, tokens, offerings, investors, allowances, dividends, and transaction status.
| Capability | Endpoint | HTTP | SDK | MCP | CLI |
| -------------------------------------------- | -------------------------------- | :--: | :-: | :-: | :-: |
| Chain metadata and contract addresses | `GET /get-network-info` | Yes | Yes | Yes | Yes |
| Token information | `GET /get-token-info` | Yes | Yes | Yes | Yes |
| Tokenizer account and token contract address | `GET /get-tokenizer-info` | Yes | Yes | Yes | Yes |
| List offerings for a token | `GET /get-stos` | Yes | Yes | Yes | Yes |
| One offering by ID | `GET /get-sto-by-id` | Yes | Yes | Yes | Yes |
| Offering balance and status | `GET /get-sto-balance` | Yes | Yes | Yes | Yes |
| Investments in an offering | `GET /get-investments-by-sto-id` | Yes | Yes | Yes | Yes |
| Investor status | `GET /get-investor-info` | Yes | Yes | Yes | Yes |
| Whitelist status of a wallet | `GET /get-whitelist-status` | Yes | Yes | Yes | Yes |
| Balance and whitelist together | `GET /get-balance-whitelist` | Yes | Yes | Yes | Yes |
| Allowance between two parties | `GET /get-allowance` | Yes | Yes | Yes | Yes |
| Dividend distribution | `GET /get-dividend-distribution` | Yes | Yes | Yes | Yes |
| Transaction status | `GET /get-transaction-status` | Yes | Yes | Yes | Yes |
The CLI uses `brickken tx` for Dapp transaction methods and `brickken dapp get` for reads. The `PATCH /patch-token-docs` endpoint remains REST-only because it requires multipart file uploads. See the [CLI command reference](/cli/introduction).
## Give an AI agent an on-chain identity
ERC-8004 identity and reputation on Base. Relayed preparation is free; client-controlled modes split the x402 operation charge between prepare and send.
| Capability | Method | Endpoint |
| ------------------------------------- | ----------------------------- | ------------------------------------- |
| Register an agent identity | `agentRegister` | `POST /x402/agent/register` |
| Update the agent profile URI | `agentSetURI` | `POST /x402/agent/set-uri` |
| Write a metadata key/value | `agentSetMetadata` | `POST /x402/agent/set-metadata` |
| Rotate the agent's operational wallet | `agentSetWallet` | `POST /x402/agent/set-wallet` |
| Transfer identity ownership | `agentTransferOwnership` | `POST /x402/agent/transfer-ownership` |
| Give reputation feedback | `agentGiveFeedback` | `POST /x402/agent/feedback/give` |
| Revoke feedback | `agentRevokeFeedback` | `POST /x402/agent/feedback/revoke` |
| Respond to feedback | `agentAppendFeedbackResponse` | `POST /x402/agent/feedback/respond` |
## Let an agent own and operate a token
An agent-owned ERC-20, deployed and operated by the agent itself.
| Capability | Method | Endpoint |
| ----------------------------- | ------------------------ | -------------------------------- |
| Deploy an agent-owned ERC-20 | `agentCreateToken` | `POST /x402/token/create` |
| Mint | `agentMintToken` | `POST /x402/token/mint` |
| Burn | `agentBurnToken` | `POST /x402/token/burn` |
| Transfer | `agentTransferToken` | `POST /x402/token/transfer` |
| Transfer through an allowance | `agentTransferFromToken` | `POST /x402/token/transfer-from` |
| Approve an allowance | `agentApproveToken` | `POST /x402/token/approve` |
## Delegate spending authority to an agent
RAMS (ERC-8226) lets a principal grant an agent a **compliance-gated, value-capped mandate** to act on a specific asset. Caps are enforced on-chain, usage is recorded, and an enforcer can freeze an agent across every mandate at once.
**RAMS runs on Ethereum Sepolia (`11155111`) at launch**, on both sandbox and production. All `/x402/rams/*` prepare facades default to `chainId: "11155111"`.
| Capability | Method | Endpoint |
| -------------------------------- | ----------------------- | ------------------------------------- |
| Grant a mandate | `ramsGrantMandate` | `POST /x402/rams/grant-mandate` |
| Revoke a mandate | `ramsRevokeMandate` | `POST /x402/rams/revoke-mandate` |
| Extend a mandate | `ramsExtendMandate` | `POST /x402/rams/extend-mandate` |
| Approve an operator | `ramsSetOperator` | `POST /x402/rams/set-operator` |
| Execute under a mandate | `ramsExecute` | `POST /x402/rams/execute` |
| Register an executor selector | `ramsSetExecutorAction` | `POST /x402/rams/set-executor-action` |
| Freeze an agent | `ramsFreezeAgent` | `POST /x402/rams/freeze-agent` |
| Unfreeze an agent | `ramsUnfreezeAgent` | `POST /x402/rams/unfreeze-agent` |
| Make a principal eligible | `ramsGrantPrincipal` | `POST /x402/rams/grant-principal` |
| Revoke eligibility | `ramsRevokePrincipal` | `POST /x402/rams/revoke-principal` |
| Read a mandate and its status | — | `GET /rams/mandate` |
| Dry-run an execution | — | `GET /rams/can-execute` |
| Read freeze state and nonce | — | `GET /rams/status` |
| Read compliance eligibility | — | `GET /rams/compliance-status` |
| Read a registered selector | — | `GET /rams/executor-action` |
| Fetch an EIP-712 payload to sign | — | `GET /rams/typed-data/{operation}` |
Actors, lifecycle, caps, and the executor setup checklist.
## What you cannot do yet
Being explicit about the edges saves you an afternoon:
* **The CLI does not provide multipart file uploads.** Use the REST API for `/patch-token-docs`; Dapp transaction methods and JSON reads are supported through the CLI with an API key.
* **`brickken-relayed` sends cannot be paid with an API key.** Brickken pays the gas, so the x402 payment is mandatory.
* **RAMS runs on Ethereum Sepolia only** at launch, on both sandbox and production.
* **The MCP packages are not published to npm.** Use the hosted server at `https://mcp.brickken.com/mcp`.
* **Six of the ten RAMS writes cannot be relayed.** Only grant, revoke, extend, and set-operator support `brickken-relayed`, and only with a principal EIP-712 signature; the rest check `msg.sender` against a role.
Decide between HTTP, the SDK, the CLI, MCP, and the Skill.
Which credential reaches which capability.
# Brickken Developer Documentation
Source: https://docs.brickken.com/index
Tokenize real-world assets and give AI agents on-chain authority, through one API.
Brickken turns real-world assets into compliant on-chain tokens, and gives AI agents identity, reputation, and delegated spending authority. Both run on the same API.
Every capability, and which client reaches it.
HTTP, SDK, CLI, MCP, or the AI agent Skill.
API key or x402 — which one you need.
## Two APIs
| | Dapp API | Agentic API |
| ---------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| **What it does** | Tokenize assets, run offerings, manage investors and dividends | ERC-8004 agent identity and reputation, agent-owned tokens, ERC-8226 mandates |
| **Credential** | API key | x402 payment, or an API key in `client-signed` mode |
| **Networks** | Ethereum, Base, BNB Chain, Polygon, and their testnets | Base and Base Sepolia; Ethereum Sepolia for RAMS |
| **Who it's for** | Issuers, platforms, and their backends | Autonomous agents and the people who run them |
| **Start here** | [Dapp API](/api-reference/introduction) | [Agentic API](/api-reference/endpoint/agentic-methods-x402) |
Every write on both APIs follows the same three steps: **prepare** an unsigned transaction, **sign** it, **send** it. Dapp API prepares consume API-key credits; Agentic API prepares are free only in relayed mode and are priced as the first half of client-controlled operations.
## Clients
Plain HTTP. Reaches everything.
`brickken-sdk` on npm. Typed TypeScript client for all three APIs.
Hosted, 62 tools. Drives the full Dapp API from an AI agent with just an API key.
`brickken-cli` on npm, for Dapp API, KYC, faucet, agentic, and RAMS workflows.
Brickken knowledge for AI coding agents.
## Environments
| Environment | API base URL | App URL |
| ----------- | ---------------------------------- | ----------------------------------- |
| Sandbox | `https://api.sandbox.brickken.com` | `https://dapp.sandbox.brickken.com` |
| Production | `https://api.brickken.com` | `https://dapp.brickken.com` |
Sandbox and production are separate deployments with separate databases. An API key issued for one does not work on the other.
## Get access
Fill in the form — it sends a complete request to `tech@brickken.com`.
Schedule a production onboarding call.
# Base MCP
Source: https://docs.brickken.com/mcp/base-mcp
Drive the Brickken Agentic API from an agent using a Base Account wallet, with Brickken carrying the signing and the gas.
## Overview
The [Base MCP server](https://github.com/base/base-mcp) connects an MCP-compatible agent to a **Base
Account** and its wallet. With it in the session, an agent pays for Brickken's Agentic API straight
from that wallet — no separate key management, and no funding a bare EOA just to call the API.
This is the one setup where Brickken can also carry the blockchain side of the operation for you.
This page describes the Base MCP path specifically. Everywhere else in the Agentic API you sign the
prepared transaction yourself and the operation price is split evenly between prepare and send —
see [Agentic API](/api-reference/endpoint/agentic-methods-x402) and
[Pricing](/api-reference/endpoint/agentic-pricing).
## What the Base Account gives the agent
Brickken's Agentic API is paid with x402: every call answers `402 Payment Required` with a
`PAYMENT-REQUIRED` header, and the caller signs a payment authorization to proceed. The Base Account
wallet is what signs those authorizations.
That means an agent running with Base MCP can:
* Pay for Brickken operations from an account the user already controls.
* Do it without the agent holding a raw private key of its own.
* Settle in USDC on Base, the asset the Agentic API quotes.
## Relayed execution
In this setup the prepared transaction does not have to be signed by you. Passing
`executionMode: "brickken-relayed"` hands the blockchain side to Brickken's relayer:
* Brickken signs the prepared transaction and pays the native gas.
* Your wallet authorizes only the **x402 payment**.
* You need no EOA, no ETH on Base, and no on-chain signing of your own.
Because Brickken carries the signing and the gas, the charge falls differently: **preparing is free**
and the full operation price is collected on `POST /send-transactions`.
```json theme={null}
{
"chainId": "8453",
"executionMode": "brickken-relayed",
"name": "Research Agent",
"description": "On-chain AI research agent",
"image": "https://example.com/agent.png",
"serviceName": "A2A",
"serviceEndpoint": "https://agent.example/.well-known/agent-card.json",
"x402Support": true,
"active": true
}
```
Omit `signerAddress` — and `agentWallet` for `agent_create_token` — since Brickken supplies the
signer. Prepare returns a single `txId`, exactly one transaction, and `x402Requirements`.
Relayed execution is only available through this path. A direct
[`POST /prepare-transactions`](/api-reference/endpoint/create) call, the
[Brickken MCP server](/mcp/introduction), the [SDK](/sdk/introduction) and the
[CLI](/cli/introduction) all sign client-side.
### What relaying does not cover
Relaying works where Brickken's relayer is allowed to be the sender. It is not available for
operations whose contract checks `msg.sender` against a specific on-chain role — most of
[RAMS](/api-reference/endpoint/rams-overview) falls in that group, since `signerAddress` has to be
the role holder itself.
Because Brickken's relayer is the sender, it is also the on-chain owner of anything the operation
creates. Use
[`agentTransferOwnership`](/api-reference/endpoint/x402-agent-transfer-ownership) when you want to
take custody of an agent identity yourself.
## Payment behaviour
x402 payment is **mandatory** on a relayed send — an API key is not accepted there, because the whole
point is that Brickken is doing the signing on your behalf.
The payment is reserved when you pay and **settles only after the operation confirms on-chain**. If
the operation reverts, or its authorization expires before confirmation, the reservation is released.
Poll with [`GET /get-transaction-status`](/api-reference/endpoint/get-transaction-status) using the
`txId`. A `status: "pending"` means the operation was broadcast but not yet confirmed — do not pay or
resubmit the same `txId`.
The hosted Brickken MCP server, for API-key and client-signed x402 workflows.
The x402 surface, its methods, and the payment handshake.
# MCP
Source: https://docs.brickken.com/mcp/introduction
Hosted Brickken MCP server for API-key and x402 workflows in MCP-compatible AI agents.
## Overview
The Brickken MCP server exposes the Brickken Dapp API and Agentic API as 63 tools for MCP-compatible AI agents.
It is **the client to reach for when an AI agent should drive the full Dapp API with nothing but an API key**, including KYC link creation. If your own code is driving rather than an agent, use the [SDK](/sdk/introduction). See [Choose your surface](/get-started/choose-your-surface).
Open the official Brickken MCP page.
Check hosted server availability.
## Connect
Use the hosted endpoint in Claude Code, Codex, or any MCP-compatible client. Note the `/mcp` path — the bare host serves an HTML landing page, not the MCP endpoint:
```json theme={null}
{
"mcpServers": {
"brickken": {
"url": "https://mcp.brickken.com/mcp"
}
}
}
```
## Session Configuration
Every MCP session is isolated. Configure credentials at runtime with the `configure` tool, then use `get_config` to verify the active environment without exposing secrets.
A session is **either API-key mode or x402 mode, never both.** When an API key is configured the server attaches `x-api-key` to every outbound request and never falls back to the payment handshake. Set `"apiKey": ""` to force x402.
### API-key mode
Use this mode for the [Dapp API](/api-reference/introduction). An API key alone unlocks every Dapp tool listed below — KYC, tokenization, STOs, security-token operations, and all reads.
```json theme={null}
{
"env": "production",
"apiKey": "YOUR_BRICKKEN_API_KEY"
}
```
### x402 private-key mode
Use this mode for the [Agentic API](/api-reference/endpoint/agentic-methods-x402). The private key is used by the MCP server session to sign x402 payments and to sign the prepared blockchain transaction.
```json theme={null}
{
"env": "production",
"privateKey": "0xYOUR_PRIVATE_KEY",
"apiKey": ""
}
```
For sandbox:
```json theme={null}
{
"env": "sandbox",
"privateKey": "0xYOUR_PRIVATE_KEY",
"apiKey": ""
}
```
A custom `baseUrl` overrides the selected environment when needed. An internal `forge` environment exists for Brickken pre-release QA — contact `tech@brickken.com` for its base URL.
Only configure a private key in MCP clients and environments you trust. `get_config` returns booleans such as `hasApiKey` and `hasPrivateKey`, never the secret values.
The hosted `/mcp` endpoint has no inbound authentication — anyone can connect, and every credential is supplied by the client per session. Nothing you configure is persisted server-side beyond the life of your session.
## Configuration Tools
| Tool | Purpose |
| ------------ | ------------------------------------------------------------------------ |
| `configure` | Set `env`, `baseUrl`, `apiKey`, or `privateKey` for the current session. |
| `get_config` | Inspect `env`, `baseUrl`, `hasApiKey`, and `hasPrivateKey`. |
## BKN Faucet Tool
`request_bkn_faucet` requests 100 BKN on Ethereum Sepolia in Sandbox or Forge. Pass `recipientAddress` and optionally `idempotencyKey` as UUID v4. The tool generates and returns a UUID when omitted; use a new UUID for a new claim and the same UUID for a retry of that claim.
Configure exactly one credential. An API key has 10 dedicated lifetime faucet claims, separate from `mintToken`; private-key mode pays 0.01 USDC through x402. Recipients have a 24-hour cooldown. The public bearer/reCAPTCHA flow is not exposed.
## Transaction Tools
| Tool | Purpose |
| ------------------------ | ----------------------------------------------------- |
| `prepare_transactions` | Prepare unsigned transactions for a backend `method`. |
| `send_transactions` | Submit signed transactions to Brickken. |
| `get_transaction_status` | Poll a transaction hash. |
## Dapp API Tools
These tools map to API-key authenticated dapp flows and are **the legacy Dapp API, reachable from an AI agent with nothing but an API key**. If a private key is also configured, write tools can prepare, sign, and send automatically; otherwise they return prepared transactions for external signing.
The signer wallet must be whitelisted by Brickken before a write is accepted, and your key can only act on token symbols it tokenized. See [Authentication](/get-started/authentication).
| Area | Tools |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| KYC | `create_kyc_link` |
| BKN faucet | `request_bkn_faucet` |
| Tokenization | `create_tokenization` |
| STOs | `create_sto`, `invest_in_sto`, `claim_sto`, `close_sto` |
| Security-token operations | `mint_tokens`, `whitelist_investor`, `burn_tokens`, `transfer_tokens`, `approve_tokens`, `distribute_dividend` |
| Reads | `get_network_info`, `get_token_info`, `get_tokenizer_info`, `get_stos`, `get_sto_by_id`, `get_investments_by_sto_id`, `get_investor_info`, `get_allowance`, `get_whitelist_status`, `get_balance_whitelist`, `get_sto_balance`, `get_dividend_info` |
`create_kyc_link` can create an investor account and send an invitation email. Treat its returned Sumsub URL as sensitive.
## x402 Agent Tools
These tools map to ERC-8004 and agent-token methods on Base. Relayed preparation is free; client-controlled modes split the x402 USDC payment between prepare and send.
| Area | Tools |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Agent reads | `get_agents`, `get_agent_info`, `get_agent_transactions` |
| Agent identity | `agent_register`, `agent_set_uri`, `agent_set_metadata`, `agent_set_wallet`, `agent_transfer_ownership` |
| Reputation | `agent_give_feedback`, `agent_revoke_feedback`, `agent_append_feedback_response` |
| Agent-owned tokens | `agent_create_token`, `agent_mint_token`, `agent_burn_token`, `agent_transfer_token`, `agent_transfer_from_token`, `agent_approve_token` |
| RAMS mandates (ERC-8226) | `rams_grant_mandate`, `rams_revoke_mandate`, `rams_extend_mandate`, `rams_set_operator`, `rams_execute`, `rams_set_executor_action`, `rams_freeze_agent`, `rams_unfreeze_agent`, `rams_grant_principal`, `rams_revoke_principal`, `rams_get_mandate`, `rams_can_execute`, `rams_get_status`, `rams_check_compliance`, `rams_get_executor_action`, `rams_get_typed_data` |
RAMS reads and typed-data fetches use the session's API key when one is set, and fall back to x402 when it is not. `rams_get_typed_data` auto-signs when the session has a private key matching the principal; otherwise it returns the envelope with a warning for external signing. Pass the result's signature and deadline to the matching lifecycle tool.
The three agent getters follow the same API-key-or-x402 rule and cost `0.000001 USDC` per x402 call. In x402 mode, `get_agents` requires `chainId` and `ownerWalletAddress`, and the payment signer must match that owner. Detail and transaction reads accept `agentUuid`, or `agentId` together with `chainId`; x402 payment is checked against the stored owner wallet.
## Networks
Use `chainId: "8453"` for Base mainnet and `chainId: "84532"` for Base Sepolia tests (decimal or hex accepted). On Base Sepolia the x402 asset is Circle USDC `0x036CbD53842c5426634e7929541eC2318f3dCF7e` (EIP-3009, 6 decimals). Always fund the payer with the exact asset quoted in `x402Requirements`.
## Execution modes
Agentic tools support both client-controlled modes:
* **`client-signed` (default).** Provide `signerAddress`; the session signs the prepared transaction locally, and Brickken broadcasts it.
* **`client-broadcast`.** The session signs and broadcasts the transaction itself, then confirms it with `txHash`.
Either way the operation price is split evenly between prepare and send. See [Pricing](/api-reference/endpoint/agentic-pricing).
If you would rather not hold an EOA or native gas at all, see [Base MCP](/mcp/base-mcp), where the
wallet only authorizes the payment and Brickken carries the signing and the gas.
## Example
Configure x402 mode, then register an agent on Base Sepolia:
```json theme={null}
{
"env": "sandbox",
"privateKey": "0xYOUR_PRIVATE_KEY",
"apiKey": ""
}
```
```json theme={null}
{
"chainId": "84532",
"signerAddress": "0x1111111111111111111111111111111111111111",
"name": "Research Agent",
"description": "On-chain AI research agent",
"image": "https://example.com/agent.png",
"serviceName": "A2A",
"serviceEndpoint": "https://agent.example/.well-known/agent-card.json",
"aiModelProvider": "OpenAI",
"aiModelName": "Research Model",
"x402Support": true,
"active": true
}
```
The `agent_register` result includes prepared transaction data and, when executed, the send result. Save `prepared.info.agentUuid` for later agent updates, including `agent_transfer_ownership`.
# Authentication
Source: https://docs.brickken.com/sdk/authentication
API key or x402 signer — which credential the SDK uses, and which combinations it refuses.
The SDK does not ask you to pick a credential mode. It derives one from what you pass to the constructor:
| You pass | Mode | What it can do |
| --------------------- | ----------- | -------------------------------------------------------------------------------------------------- |
| `apiKey` | `api-key` | The full Dapp API and KYC, plus agent getters, agentic writes, and RAMS in client-controlled modes |
| `signer`, no `apiKey` | `x402` | Agent getters, agentic writes, and RAMS, paying per call; every execution mode including relayed |
| Neither | `anonymous` | Public reads, and relayed prepares of x402-eligible agentic methods |
Passing both is legal — the SDK uses the key for authentication and the signer for transaction signing — but it takes `brickken-relayed` off the table, because a relayed send must be paid with x402.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
// api-key mode
const dapp = new Brickken({ env: 'sandbox', apiKey: process.env.BRICKKEN_API_KEY })
// x402 mode
const agentic = new Brickken({
env: 'sandbox',
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
})
dapp.credentialMode // 'api-key'
agentic.credentialMode // 'x402'
```
## What each credential reaches
| | `apiKey` | `signer`, no key |
| ------------------------------------------------------ | :-------------------------------: | :------------------: |
| KYC link creation | Yes | No |
| BKN faucet (Sandbox/Forge) | Yes, 10 dedicated lifetime claims | Yes, 0.01 USDC |
| Agent getters | Yes | Yes |
| Dapp API writes (`tokenization.*`, `sto.*`) | Yes | No |
| Dapp API reads | Yes | No |
| Agentic API, `client-signed` | Yes | Yes |
| Agentic API, `client-broadcast` | Yes | Yes |
| Agentic API, `brickken-relayed` | **Rejected** | Yes |
| RAMS writes | Yes | Yes |
| RAMS reads and typed data | Yes | Yes |
| `GET /get-network-info`, `GET /get-transaction-status` | Yes | Yes, and anonymously |
Brickken treats the two credentials as alternatives, not layers: when `x-api-key` is present the API skips the x402 path entirely, so no payment is taken.
## Combinations the SDK refuses locally
These throw before any request leaves your process, with the fix named in the message.
| Attempt | Error |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `brickken-relayed` while an `apiKey` is configured | `RelayedRequiresPaymentError` |
| `brickken-relayed` on a method whose on-chain call checks `msg.sender` | `ValidationError` |
| `brickken-relayed` with a `signerAddress` passed | `ValidationError` — Brickken supplies its relayer as the signer |
| `client-signed` or `client-broadcast` without a `signerAddress` | `ValidationError` — prepare builds against that account's nonce |
| A Dapp method with no credential at all, even to prepare | `ValidationError` |
| `execute: true` with no credential | `ValidationError` |
| `client-signed` or `client-broadcast` with a signer that has no `signTransaction` | `ValidationError` |
| BKN faucet with both `apiKey` and `signer`, or in production | `ValidationError` |
```ts theme={null}
const bkn = new Brickken({ apiKey: 'key', signer })
await bkn.agent.register(input, { executionMode: 'brickken-relayed' })
// RelayedRequiresPaymentError — no network round trip
```
Credential rules that only bind at **send** time are checked only when you pass `execute: true`. A relayed prepare is not rejected for a credential it does not yet need; client-controlled prepares require the signer and its prepare payment share.
## Prepare without a credential
An x402-eligible agentic method — everything under `/x402/*` — can prepare with no credential when it uses relayed execution. A client-controlled prepare needs a signer and its payment share. A Dapp method does not: the backend requires a key for any non-x402 method at prepare as well as at send, so the SDK refuses the call rather than spending a round trip on it.
```ts theme={null}
const anon = new Brickken({ env: 'sandbox' })
await anon.agent.register(input) // fine: prepares, returns a quote
await anon.tokenization.info({ tokenSymbol: 'EXMPL' }) // reaches the API, which requires the key
await anon.tokenization.create(input) // ValidationError: this method requires an apiKey
```
## Environment variables
`Brickken.fromEnv` reads the same variables the CLI and MCP server already use, including the `BKN_*` aliases:
```ts theme={null}
const bkn = Brickken.fromEnv(process.env)
```
| Variable | Alias | Purpose |
| ------------------- | -------------- | ------------------------------------------------------------------ |
| `BRICKKEN_API_KEY` | `BKN_API_KEY` | Brickken API key |
| `BRICKKEN_ENV` | `BKN_ENV` | `sandbox` or `production` |
| `BRICKKEN_BASE_URL` | `BKN_BASE_URL` | Override the API base URL |
| `BRICKKEN_RPC_URL` | `BKN_RPC_URL` | JSON-RPC used for `client-broadcast`, receipts, and token metadata |
`BRICKKEN_PRIVATE_KEY` is deliberately **not** read. Turning a key into a signer is an explicit choice, never an implicit one:
```ts theme={null}
const bkn = Brickken.fromEnv(process.env, {
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
})
```
## Key handling
Your private key never leaves your process. It signs the x402 payment authorization, `client-signed` and `client-broadcast` transactions, and RAMS typed data, all locally. The SDK never puts it in a request body or a header.
Never paste production API keys or private keys into shared terminals, tickets, chat logs, or committed `.env` files. Use your platform's secret store or process environment.
For institutional custody, implement the [`Signer` interface](/sdk/signers) against your KMS or MPC provider instead of holding a raw key.
# Configuration
Source: https://docs.brickken.com/sdk/configuration
Every constructor option, the environment table, and how to build a client from the environment.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
new Brickken({
env: 'sandbox', // 'sandbox' | 'production'
baseUrl, // overrides env
apiKey,
signer,
rpcUrl, // client-broadcast writes, receipt polling, and on-chain token metadata
timeoutMs: 30_000,
retry: { attempts: 3, baseDelayMs: 500, jitter: true },
payment: { maxAmountBaseUnits: '50000' },
fetch, // inject your own
})
```
Every option is optional. `new Brickken()` with no arguments is a valid anonymous sandbox client.
| Option | Type | Default | Purpose |
| ----------- | --------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------ |
| `env` | `'sandbox' \| 'production'` | `'sandbox'` | Selects the base URL |
| `baseUrl` | `string` | — | Overrides `env`. Use for any non-public deployment |
| `apiKey` | `string` | — | Selects API-key mode; sent as `x-api-key` |
| `signer` | `Signer` | — | Selects x402 mode when no key is set. See [Signers](/sdk/signers) |
| `rpcUrl` | `string` | — | JSON-RPC endpoint for `client-broadcast`, `waitForReceipt`, and token metadata |
| `timeoutMs` | `number` | `30000` | Per-request timeout |
| `retry` | `RetryPolicy` | `{ attempts: 3, baseDelayMs: 500, jitter: true }` | See [Errors](/sdk/errors#retries) |
| `payment` | `PaymentPolicy` | `{}` | Spending controls. See [Payments](/sdk/payments) |
| `fetch` | `typeof fetch` | `globalThis.fetch` | Injectable for tests, proxies, or a runtime whose global you do not want |
The constructor throws a `TypeError` if no `fetch` implementation is available — use Node 20 or newer, or pass one explicitly.
## Environments
| Environment | API base URL | App URL |
| ----------- | ---------------------------------- | ----------------------------------- |
| Sandbox | `https://api.sandbox.brickken.com` | `https://dapp.sandbox.brickken.com` |
| Production | `https://api.brickken.com` | `https://dapp.brickken.com` |
Sandbox and production are separate deployments with separate databases. An API key issued for one does not work on the other.
| `env` | Base URL |
| ------------ | ---------------------------------- |
| `sandbox` | `https://api.sandbox.brickken.com` |
| `production` | `https://api.brickken.com` |
An internal `forge` environment exists for Brickken pre-release QA — contact `tech@brickken.com` for its base URL and pass it as `baseUrl`.
Read back what the client resolved:
```ts theme={null}
bkn.baseUrl // 'https://api.sandbox.brickken.com'
bkn.credentialMode // 'api-key' | 'x402' | 'anonymous'
```
## From the environment
`Brickken.fromEnv` reads the same variables the CLI and MCP server already document, including the `BKN_*` aliases.
```ts theme={null}
const bkn = Brickken.fromEnv(process.env)
```
| Variable | Alias | Purpose |
| ------------------- | -------------- | ------------------------------------------------------------------ |
| `BRICKKEN_API_KEY` | `BKN_API_KEY` | Brickken API key |
| `BRICKKEN_ENV` | `BKN_ENV` | `sandbox` or `production` |
| `BRICKKEN_BASE_URL` | `BKN_BASE_URL` | Override the API base URL |
| `BRICKKEN_RPC_URL` | `BKN_RPC_URL` | JSON-RPC used for `client-broadcast`, receipts, and token metadata |
An empty string is treated as unset, and an unrecognised `BRICKKEN_ENV` is ignored rather than guessed at.
`BRICKKEN_PRIVATE_KEY` is deliberately **not** read. Turning a key into a signer is an explicit choice, never an implicit one — pass it as an override:
```ts theme={null}
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const bkn = Brickken.fromEnv(process.env, {
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
payment: { maxAmountBaseUnits: '50000' },
})
```
Overrides win over the environment, so this composes cleanly with a `.env` file.
## Injecting `fetch`
Useful for a proxy, for request logging, or for a test that must not touch the network:
```ts theme={null}
const bkn = new Brickken({
env: 'sandbox',
apiKey,
fetch: async (input, init) => {
console.log('→', input)
return await undici.fetch(input, init)
},
})
```
The injected implementation is used for API requests, for JSON-RPC broadcasting, and for receipt polling.
Every method the configured client exposes.
# Errors
Source: https://docs.brickken.com/sdk/errors
Fourteen typed error classes, what each one means, and which ones carry recoverable state.
Branch on the **class**, never on the status code. The API reports the same missing-key cause as `401` on one endpoint and `400` on another, so a status-based branch is wrong somewhere by construction.
```ts theme={null}
import { CreditsExhaustedError, RateLimitError, ValidationError } from 'brickken-sdk'
try {
await bkn.tokenization.create(input, { execute: true, signerAddress })
} catch (error) {
if (error instanceof ValidationError) throw error // your bug; will fail identically next time
if (error instanceof CreditsExhaustedError) return topUp(error.method)
if (error instanceof RateLimitError) return retryAfter(error.retryAfterSeconds)
throw error
}
```
## The classes
Every one extends `BrickkenError`, which carries `.code`, and — where the API supplied them — `.status` and `.body`.
| Class | Meaning |
| ------------------------------ | ------------------------------------------------------------------------------------ |
| `ValidationError` | Refused locally; no request was made |
| `AuthError` | Credential missing, wrong, or not accepted here |
| `RelayedRequiresPaymentError` | Relayed execution attempted with an API key configured |
| `CreditsExhaustedError` | Plan balance for that write method is spent; carries `.method` |
| `UnauthorizedTokenSymbolError` | Your key did not tokenize that symbol |
| `PaymentRequiredError` | An x402 payment is needed and none could be authorized; carries `.requirement` |
| `PaymentDeclinedError` | Your ceiling or your `onPaymentRequired` hook refused to pay; carries `.requirement` |
| `RateLimitError` | `429`; carries `.retryAfterSeconds` |
| `ApiError` | Any other non-2xx; carries `.status` and `.body` |
| `NetworkError` | Transport failure or timeout |
| `RpcRejectedError` | The configured JSON-RPC node rejected a call |
| `BroadcastConfirmationError` | Broadcast succeeded but backend confirmation failed; carries `.txId` and `.txHash` |
| `TxRevertedError` | The transaction was mined and reverted |
| `BrickkenError` | The base class — catch this to catch everything the SDK raises |
## Errors that carry recoverable state
Three of them exist so a failure does not cost you the work already done.
### `BroadcastConfirmationError`
The transaction is already on chain. Re-signing and re-broadcasting would be wrong. Resume only the confirmation step:
```ts theme={null}
import { BroadcastConfirmationError } from 'brickken-sdk'
try {
await bkn.tokenization.create(input, { execute: true, executionMode: 'client-broadcast', signerAddress })
} catch (error) {
if (error instanceof BroadcastConfirmationError) {
await bkn.tx.send({ txId: error.txId, txHash: error.txHash })
}
}
```
### `CreditsExhaustedError`
Each Dapp write method carries its own credit balance, so one method can run out while others still work. `.method` names the one that did.
### Any error with `.payment`
A failure that happened **after** an x402 payment was authorized sets `.payment` on the error, so the charge can be reconciled against what actually ran.
```ts theme={null}
catch (error) {
if (error instanceof BrickkenError && error.payment !== undefined) {
await reconcile(error.payment)
}
}
```
## Retries
| Condition | Retried |
| ----------------------------------------------------- | :--------------------------: |
| `429` (`RateLimitError`) | Yes, honouring `Retry-After` |
| `5xx` | Yes |
| Transport failure or timeout (`NetworkError`) | Yes |
| Any other `4xx` | No |
| Anything raised locally (`ValidationError`) | No |
| **A send for which a payment was already authorized** | **Never** |
Retries use jittered exponential backoff. The defaults are three attempts with a 500 ms base delay, and are configurable:
```ts theme={null}
new Brickken({
apiKey,
retry: { attempts: 5, baseDelayMs: 250, jitter: true },
})
```
The paid-send rule is the important one: a send whose payment was authorized is never retried automatically, because a retry could be a second charge. If it fails, the error carries `.payment` and the decision is yours.
The controls that stop a payment before it happens.
# Execution modes
Source: https://docs.brickken.com/sdk/execution-modes
Who signs the transaction, who broadcasts it, and what each mode costs.
`executionMode` decides two things: who produces the signature, and who puts the transaction on chain. Every write accepts it, and every write has a sensible default — most callers never set it.
| Mode | Signs | Broadcasts | Needs |
| ------------------ | ------------------ | ------------------ | -------------------------------------------------------------- |
| `client-signed` | You | Brickken | A signer with `signTransaction`, and `signerAddress` |
| `client-broadcast` | You | You, over `rpcUrl` | A signer with `signTransaction`, `signerAddress`, and `rpcUrl` |
| `brickken-relayed` | Brickken's relayer | Brickken | An x402 payment, so **no** `apiKey` |
## Defaults per namespace
The API's own default depends on which entry point you hit, which is exactly the asymmetry the SDK removes: it always sends the mode explicitly, and reports it back on `result.executionMode`.
| Namespace | Default | Relaying |
| -------------------------------------------------------------------- | ------------------ | ------------------------------------- |
| `tokenization.*`, `sto.*` (Dapp) | `client-signed` | Not available |
| `agent.*`, `agentToken.*` (ERC-8004) | `brickken-relayed` | Available |
| `rams.grantMandate`, `revokeMandate`, `extendMandate`, `setOperator` | `client-signed` | Available, with a principal signature |
| Every other `rams.*` write | `client-signed` | Rejected locally |
The six RAMS operations that cannot be relayed — `execute`, `setExecutorAction`, `freezeAgent`, `unfreezeAgent`, `grantPrincipal`, `revokePrincipal` — require `msg.sender` to hold an on-chain role, so no relayer can send them on your behalf. The SDK throws `ValidationError` rather than letting the server answer `400`.
## What each mode costs
Only relaying gives you a free prepare, because there Brickken carries the signing and the gas. In the two client-controlled modes the same total is split evenly across prepare and send.
| Mode | Prepare | Send |
| ------------------ | -------------- | -------------- |
| `brickken-relayed` | Free | The full price |
| `client-signed` | Half the price | Half the price |
| `client-broadcast` | Half the price | Half the price |
Dapp writes made with an API key are not x402-priced at all — they draw on the per-method credit balance attached to your key. See [Pricing](/api-reference/endpoint/agentic-pricing) for the agentic per-operation table.
## `client-signed`
The default for Dapp writes. You sign locally and hand the signed transaction to Brickken to broadcast.
```ts theme={null}
const done = await bkn.tokenization.mint(
{ chainId: '11155111', tokenSymbol: 'EXMPL', userToMint: [{ email: 'investor@example.com', amount: '100' }] },
{ execute: true, signerAddress: await signer.address() },
)
done.sent?.transactionHashes
```
`signerAddress` is required: prepare builds the transaction against that account's nonce. The SDK checks the configured signer's address against it and refuses a mismatch locally.
## `brickken-relayed`
The recommended mode for agentic work. Omit `signerAddress` — Brickken supplies its relayer as the signer, pays the native gas, and broadcasts. Your signer only authorizes the x402 payment.
```ts theme={null}
const done = await bkn.agent.register(
{ chainId: '84532', name: 'Research Agent', image: 'https://example.com/agent.png' },
{ execute: true }, // brickken-relayed is already the default here
)
```
Prepare returns a single `txId`, exactly one transaction, and an `x402Requirements` quote.
A relayed send **rejects an API key**. Brickken pays the gas, so the payment is mandatory. Configuring both `apiKey` and `signer` and then asking for relayed execution raises `RelayedRequiresPaymentError` with no network round trip.
For `agentToken.create` in relayed mode, omit `agentWallet` as well as `signerAddress`.
## `client-broadcast`
Submit the signed transaction yourself through your own JSON-RPC endpoint, then confirm `{ txId, txHash }` back to Brickken. Use it when you need to own the mempool path — your own node, a private relay, or your own gas and nonce policy.
```ts theme={null}
const bkn = new Brickken({ apiKey: 'key', signer, rpcUrl: 'https://your-node.example' })
const done = await bkn.tokenization.create(input, {
execute: true,
executionMode: 'client-broadcast',
signerAddress: await signer.address(),
})
done.sent?.transactionHashes[0] // the hash your node assigned
```
It takes **exactly one** prepared transaction. The SDK rejects an empty response or a batch locally rather than reporting a partial execution.
### When your node refuses
If the RPC endpoint rejects the transaction — `nonce too low`, `insufficient funds`, anything else — you get an `RpcRejectedError` carrying the node's own code and message. An `already known` response is not an error: the SDK recovers the hash deterministically from the signed transaction and carries on.
### When confirmation fails
After broadcasting, the SDK retries the Brickken confirmation while the backend RPC catches up with transaction propagation. If confirmation still fails, the transaction is already on chain, so re-signing and re-broadcasting would be wrong. `BroadcastConfirmationError` preserves both `.txId` and `.txHash` so you can resume only the confirmation step:
```ts theme={null}
import { BroadcastConfirmationError } from 'brickken-sdk'
try {
await bkn.tokenization.create(input, options)
} catch (error) {
if (error instanceof BroadcastConfirmationError) {
await bkn.tx.send({ txId: error.txId, txHash: error.txHash })
}
}
```
## Waiting for a receipt
`waitForReceipt: true` polls the chain after the send and fills in `result.receipt`. For a deployment it also recovers `result.deployedAddress` from the receipt.
```ts theme={null}
const done = await bkn.agentToken.create(
{ chainId: '84532', name: 'Agent Token', symbol: 'AGT' },
{ execute: true, waitForReceipt: true },
)
done.deployedAddress
```
This needs an `rpcUrl` on the client. Without one the SDK throws rather than silently returning a result with no receipt.
Cap what an autonomous agent can spend before it spends it.
# BKN Faucet
Source: https://docs.brickken.com/sdk/faucet
Request test BKN with automatic UUID-v4 idempotency and API-key or x402 authentication.
The `faucet` namespace exposes the Sandbox/Forge BKN faucet. It does not expose the public bearer/reCAPTCHA flow.
```ts theme={null}
const result = await bkn.faucet.requestBkn({
recipientAddress: '0x1111111111111111111111111111111111111111',
idempotencyKey: '4d0f91d8-453d-4fb5-a8e1-c722bc7b75a1', // optional
})
```
With `apiKey`, the call consumes one of the key's 10 dedicated lifetime faucet credits. With `signer` and no key, the SDK handles the 0.01 USDC x402 challenge and exposes the payment as `result.payment`. Do not configure both for this namespace.
When `idempotencyKey` is omitted, the SDK generates UUID v4 locally and returns it as `result.idempotencyKey`. A new claim needs a new UUID; retry the same logical claim with the same UUID. The recipient cooldown is 24 hours.
```ts theme={null}
interface BknFaucetResult {
claimId: string
status: 'confirmed' | 'submitted'
chainId: '11155111'
recipientAddress: Address
amount: '100'
transactionHash: string
cooldownEndsAt: string
idempotencyKey: string
payment?: PaymentRecord
}
```
# Agent and token workflow
Source: https://docs.brickken.com/sdk/guides/agent-and-token-workflow
Register an ERC-8004 agent with the SDK, then deploy and operate its own ERC-20.
The agentic path needs no Brickken account and no API key — a funded wallet is the whole credential. Everything below runs on **Base Sepolia** (`84532`), where the x402 asset is Circle USDC.
## Set up the client
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const bkn = new Brickken({
env: 'sandbox',
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
rpcUrl: 'https://sepolia.base.org', // needed for waitForReceipt
payment: {
maxAmountBaseUnits: '50000', // hard ceiling, in the asset's base units
onPaymentRequired: async quote => {
console.log(`about to pay ${quote.displayPrice}`)
return true
},
onPayment: record => console.log('settled', record.settlement),
},
})
const chainId = '84532'
```
Do **not** pass an `apiKey` here. A relayed send rejects one, and configuring both would take `brickken-relayed` off the table — the SDK would raise `RelayedRequiresPaymentError` before any request left the process.
`brickken-relayed` is already the default for `agent.*` and `agentToken.*`. Brickken's relayer signs, broadcasts, and pays the native gas; your signer only authorizes the x402 payment. Omit `signerAddress` — passing one in relayed mode raises `ValidationError`.
## 1. Preview the cost
Preparing is free in relayed mode. Do it first and read the quote before committing to anything.
```ts theme={null}
const prepared = await bkn.agent.register({
chainId,
name: 'Research Agent',
description: 'On-chain AI research agent',
image: 'https://example.com/agent.png',
serviceName: 'A2A',
serviceEndpoint: 'https://agent.example/.well-known/agent-card.json',
aiModelProvider: 'OpenAI',
aiModelName: 'Research Model',
x402Support: true,
active: true,
})
prepared.x402Requirements // what sending will cost
prepared.sent // undefined: nothing was sent
```
`image` is required and must be a publicly reachable HTTPS URL. `serviceName` / `serviceEndpoint` are the flat form of a single service — pass `services: [{ name, endpoint, version }]` instead when you have more than one.
## 2. Register the agent
Same call, with `execute: true`. This prepares, pays the x402 charge, and sends.
```ts theme={null}
const agent = await bkn.agent.register(
{
chainId,
name: 'Research Agent',
description: 'On-chain AI research agent',
image: 'https://example.com/agent.png',
serviceName: 'A2A',
serviceEndpoint: 'https://agent.example/.well-known/agent-card.json',
aiModelProvider: 'OpenAI',
aiModelName: 'Research Model',
x402Support: true,
active: true,
},
{ execute: true },
)
const agentUuid = agent.info?.agentUuid
console.log(agent.payment?.settlement)
```
**Save `agentUuid`.** `setUri`, `setMetadata`, `setWallet`, `transferOwnership`, and every feedback call identify the agent by it. There is no lookup-by-name.
## 3. Update the agent's profile
```ts theme={null}
await bkn.agent.setMetadata(
{ chainId, agentUuid, metadataKey: 'specialty', metadataValue: 'on-chain research' },
{ execute: true },
)
await bkn.agent.setUri(
{ chainId, agentUuid, documentation: 'https://agent.example/docs' },
{ execute: true },
)
```
Rotating the operational wallet is its own call, so the identity survives a key rotation:
```ts theme={null}
await bkn.agent.setWallet({ chainId, agentUuid, newWallet: '0xNewOperationalWallet' }, { execute: true })
```
## 4. Deploy the agent's token
`waitForReceipt: true` polls the chain after the send and recovers the deployed contract address. It needs the `rpcUrl` configured in step 0.
```ts theme={null}
const token = await bkn.agentToken.create(
{ chainId, name: 'Research Agent Token', symbol: 'RAGT', decimals: 18, premint: '1000' },
{ execute: true, waitForReceipt: true },
)
const tokenAddress = token.deployedAddress
```
In relayed mode omit `agentWallet` as well as `signerAddress` — Brickken supplies both.
## 5. Operate the token
Amounts here are **human-readable** and scaled by `decimals`.
```ts theme={null}
await bkn.agentToken.mint(
{ chainId, tokenAddress, to: '0xRecipient', amount: '250' },
{ execute: true },
)
await bkn.agentToken.approve(
{ chainId, tokenAddress, spenderAddress: '0xSpender', amount: '100' },
{ execute: true },
)
await bkn.agentToken.transfer(
{ chainId, tokenAddress, to: '0xRecipient', amount: '25' },
{ execute: true },
)
await bkn.agentToken.burn(
{ chainId, tokenAddress, from: '0xHolder', amount: '10' },
{ execute: true },
)
```
Agent-token amounts are `HumanAmount`. [RAMS](/sdk/guides/rams-mandate-workflow) caps are `RawBaseUnits` and are **not** scaled. The types keep the two apart so the distinction cannot be crossed by accident.
## 6. Reputation
```ts theme={null}
await bkn.agent.feedback.give(
{ chainId, agentUuid, value: '5', tag1: 'accuracy', feedbackURI: 'https://example.com/review/1' },
{ execute: true },
)
await bkn.agent.feedback.respond(
{ chainId, agentUuid, feedbackIndex: 0, responseURI: 'https://agent.example/replies/1' },
{ execute: true },
)
await bkn.agent.feedback.revoke({ chainId, agentUuid, feedbackIndex: 0 }, { execute: true })
```
## Signing it yourself instead
Pass `executionMode: 'client-signed'` and a `signerAddress` to sign the prepared transaction locally. You then need native gas on Base Sepolia as well as USDC for the payment, and the price is split evenly across prepare and send rather than being free at prepare.
```ts theme={null}
const signerAddress = await signer.address()
await bkn.agentToken.create(input, {
execute: true,
executionMode: 'client-signed',
signerAddress,
})
```
## Funding and failure
Fund the wallet behind your signer with the exact asset quoted in `x402Requirements` — on Base Sepolia that is Circle USDC, six decimals. Read the amount from the live quote rather than a table.
| Error | What to do |
| ----------------------------- | -------------------------------------------------------------------------------------------- |
| `PaymentDeclinedError` | Your ceiling or `onPaymentRequired` refused the quote; raise the cap or accept it |
| `PaymentRequiredError` | A payment was needed and none could be authorized — usually no signer, or an unfunded wallet |
| `RelayedRequiresPaymentError` | An `apiKey` is configured; drop it for relayed execution |
| `RateLimitError` | Too many outstanding prepared transactions for the wallet; send some before preparing more |
Cap what an autonomous agent can spend.
Give the agent delegated, capped spending authority.
# RAMS mandate workflow
Source: https://docs.brickken.com/sdk/guides/rams-mandate-workflow
Grant, use, and revoke an ERC-8226 mandate with the SDK, including the signature-authorized path.
RAMS (ERC-8226) lets a **principal** grant an **agent** a compliance-gated, value-capped mandate to move a specific asset. Caps are enforced on chain, usage is recorded, and an enforcer can freeze an agent across every mandate at once.
**RAMS runs on Ethereum Sepolia (`11155111`) at launch**, on both sandbox and production. All `/x402/rams/*` prepare facades default to `chainId: "11155111"`.
Every `rams.*` call defaults to `chainId: '11155111'`, so you can omit it entirely.
## The actors
| Role | Does |
| ----------------------- | ------------------------------------------------------------------------- |
| **Principal** | Owns the asset and grants the mandate |
| **Agent** | Spends under the mandate, within its caps |
| **Operator** | Optionally acts on the principal's behalf |
| **Executor** | The contract that performs the transfer; its selectors must be registered |
| **Compliance provider** | Decides which principals are eligible |
## Set up the client
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const bkn = new Brickken({
env: 'sandbox',
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
payment: { maxAmountBaseUnits: '50000' },
})
```
An `apiKey` also works for RAMS — reads, typed data, and the two client-controlled execution modes all accept one. Only `brickken-relayed` requires x402.
## 1. Check the principal is eligible
A mandate cannot be granted to an ineligible principal, so check before you spend anything.
```ts theme={null}
await bkn.rams.complianceStatus({
principal: '0xPrincipal',
identityRef: 'urn:example:principal:1',
})
```
If the principal is not yet registered, whoever holds the compliance role grants it:
```ts theme={null}
await bkn.rams.grantPrincipal(
{ principal: '0xPrincipal', identityRef: 'urn:example:principal:1', expiresAt: '1893456000' },
{ execute: true, signerAddress: complianceAddress },
)
```
`grantPrincipal` is role-bound: it requires `msg.sender` to hold the role, so it is always `client-signed`.
## 2. Grant the mandate
The four lifecycle operations — `grantMandate`, `revokeMandate`, `extendMandate`, `setOperator` — accept either authorization flow.
### Direct authorization
The transaction sender authorizes on chain. This is the default.
```ts theme={null}
await bkn.rams.grantMandate(
{
agent: '0xAgent',
principal: '0xPrincipal',
asset: '0xAsset',
identityRef: 'urn:example:principal:1',
validUntil: '1893456000',
maxTransactionValue: 'max', // alias for 2^256-1
maxCumulativeValue: '1000000', // raw base units, no decimal scaling
actions: ['0x23b872dd'], // bytes32 or a bare 4-byte selector
},
{ execute: true, signerAddress: principalAddress },
)
```
### Signature authorization
The principal signs EIP-712 off chain, so any relayer can send the transaction. Doing this by hand means fetching the typed data, signing it, and resubmitting the same parameters **with the same deadline** — the constraint most easily broken. `authorize: 'signature'` does all three steps for you.
```ts theme={null}
await bkn.rams.grantMandate(
{
agent: '0xAgent',
principal: '0xPrincipal',
asset: '0xAsset',
identityRef: 'urn:example:principal:1',
validUntil: '1893456000',
maxTransactionValue: 'max',
maxCumulativeValue: '1000000',
actions: ['0x23b872dd'],
},
{ authorize: 'signature', executionMode: 'brickken-relayed', execute: true },
)
```
Before signing, the SDK checks the fetched domain against the expected RAMS domain (`{ name: "RAMS", version: "1" }`) and refuses to sign anything else.
`maxTransactionValue` and `maxCumulativeValue` are **raw base units** — no decimal scaling, because the backend cannot know an arbitrary asset's decimals. `1000000` on a 6-decimal USDC mandate is 1 USDC, not one million. Agent-token amounts, by contrast, are human-readable and scaled.
## 3. Register the executor's selectors
An executor can only perform actions whose selectors are registered. This is role-bound and always `client-signed`.
```ts theme={null}
await bkn.rams.setExecutorAction(
{
selector: '0x23b872dd', // transferFrom
supported: true,
hasAmount: true, // the selector carries a value the caps apply to
amountIndex: 2,
executorAddress: '0xExecutor',
},
{ execute: true, signerAddress: executorAdminAddress },
)
```
Registering a value-bearing selector with `hasAmount: false` makes its transfers **bypass the mandate caps entirely**. Set it deliberately.
## 4. Dry-run before spending
`canExecute` answers whether a specific spend would pass right now, without touching the chain.
```ts theme={null}
await bkn.rams.canExecute({
agent: '0xAgent',
principal: '0xPrincipal',
asset: '0xAsset',
amount: '250000',
selector: '0x23b872dd',
})
```
## 5. Execute under the mandate
Two paths: the `transferFrom` helper, or raw calldata.
```ts theme={null}
// helper path
await bkn.rams.execute(
{ asset: '0xAsset', from: '0xPrincipal', to: '0xRecipient', amount: '250000' },
{ execute: true, signerAddress: agentAddress },
)
// raw calldata path
await bkn.rams.execute(
{ target: '0xTarget', data: '0x23b872dd...' },
{ execute: true, signerAddress: agentAddress },
)
```
`execute` is role-bound — `msg.sender` must be the agent — so it cannot be relayed.
## 6. Extend, revoke, freeze
```ts theme={null}
await bkn.rams.extendMandate(
{ agent: '0xAgent', principal: '0xPrincipal', newValidUntil: '1924992000' },
{ authorize: 'signature', executionMode: 'brickken-relayed', execute: true },
)
await bkn.rams.revokeMandate(
{ agent: '0xAgent', principal: '0xPrincipal' },
{ authorize: 'signature', executionMode: 'brickken-relayed', execute: true },
)
// enforcer-only, and it applies across every mandate the agent holds
await bkn.rams.freezeAgent({ agent: '0xAgent' }, { execute: true, signerAddress: enforcerAddress })
```
## Reads
```ts theme={null}
await bkn.rams.mandate({ agent: '0xAgent', principal: '0xPrincipal' })
await bkn.rams.status({ agent: '0xAgent', principal: '0xPrincipal' })
await bkn.rams.executorAction({ selector: '0x23b872dd', executorAddress: '0xExecutor' })
```
Need the raw envelope rather than the automatic flow — to sign in a different process, or with hardware?
```ts theme={null}
const envelope = await bkn.rams.typedData.grantMandate({ agent, principal, asset, validUntil, /* ... */ })
envelope.primaryType
envelope.deadline // resubmit this verbatim with the signature
envelope.nonce // per-principal, shared across all four lifecycle operations
```
Pass the resulting `signature` and that exact `deadline` back into the lifecycle call. A fresh deadline will not verify.
## What can and cannot be relayed
| Operation | Relayable |
| --------------------------------------------------------------------------------------------------- | :-----------------------------: |
| `grantMandate`, `revokeMandate`, `extendMandate`, `setOperator` | Yes, with a principal signature |
| `execute`, `setExecutorAction`, `freezeAgent`, `unfreezeAgent`, `grantPrincipal`, `revokePrincipal` | No |
The second group's on-chain call checks `msg.sender` against a role, so no relayer can stand in. Asking for `brickken-relayed` on one raises `ValidationError` locally rather than a `400` from the server.
Actors, lifecycle, caps, and the executor setup checklist.
Every `rams.*` method and its endpoint.
# Tokenize an asset and run an STO
Source: https://docs.brickken.com/sdk/guides/tokenize-and-run-an-sto
The full Dapp API lifecycle with the SDK, from creating a token to distributing dividends.
The Dapp API is where the SDK earns its place: it is the typed client for the full Dapp surface, while the [CLI](/cli/introduction) provides raw transaction-method and JSON endpoint commands. Everything below targets **sandbox** on Sepolia (`11155111`), so nothing here moves real value.
## Before you start
[Request one](/get-started/request-api-key). Every call below needs it.
Brickken must whitelist the wallet you pass as `signerAddress` before any prepare accepts it. Ask for it in the same request as the key.
Dapp writes default to `client-signed`: you sign, Brickken broadcasts, and your wallet pays the gas — Sepolia ETH here.
The wallet that performs the first `newTokenization` becomes the **tokenizer** for that token. Only the tokenizer can mint it, whitelist its investors, or distribute its dividends. Your API key is also scoped to the symbols it tokenized — anything else raises `UnauthorizedTokenSymbolError`.
## Set up the client once
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const signer = fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!)
const signerAddress = await signer.address()
const bkn = new Brickken({
env: 'sandbox',
apiKey: process.env.BRICKKEN_API_KEY,
signer,
})
const chainId = '11155111'
const write = { execute: true, signerAddress } as const
```
`write` is the option object every step below reuses: `execute: true` prepares, signs, and sends in one call, and `signerAddress` is required in `client-signed` mode because prepare builds the transaction against that account's nonce.
Drop `execute: true` from any step to prepare only and inspect `result.transactions` before committing. Chain ids accept decimal or `0x`-prefixed hex — a bare `aa36a7` is rejected.
## 1. Create the tokenized asset
```ts theme={null}
const token = await bkn.tokenization.create(
{
chainId,
tokenizerEmail: 'issuer@example.com',
name: 'Example Asset',
tokenSymbol: 'EXMPL',
tokenType: 'EQUITY',
supplyCap: '1000000',
url: 'https://example.com/token-docs',
},
write,
)
token.sent?.transactionHashes
```
The field is `name`, not `tokenName`. `tokenType` accepts `EQUITY`, `DEBT`, `BILL_FACTORING`, `ICO`, `STABLECOIN`, `REVENUE_SHARE`, `RWA_TOKEN`, or `PROFIT_SHARING`, and defaults to `EQUITY`. `supplyCap` defaults to `0`, which means uncapped — set it deliberately.
Confirm it exists:
```ts theme={null}
await bkn.tokenization.info({ tokenSymbol: 'EXMPL' })
```
## 2. Whitelist your investors
A security token only moves between whitelisted wallets. Whitelist before you mint or accept investment.
```ts theme={null}
await bkn.tokenization.whitelist(
{
chainId,
tokenSymbol: 'EXMPL',
userToWhitelist: [
{
investorAddress: '0x1111111111111111111111111111111111111111',
investorEmail: 'investor@example.com',
whitelistStatus: true,
},
],
},
write,
)
```
`whitelistStatus: false` removes an investor. Verify with:
```ts theme={null}
await bkn.tokenization.whitelistStatus({
tokenSymbol: 'EXMPL',
investorAddress: '0x1111111111111111111111111111111111111111',
})
```
## 3. Mint tokens
```ts theme={null}
await bkn.tokenization.mint(
{
chainId,
tokenSymbol: 'EXMPL',
userToMint: [
{
investorEmail: 'investor@example.com',
investorAddress: '0x1111111111111111111111111111111111111111',
amount: '100',
needWhitelist: true,
},
],
},
write,
)
```
`needWhitelist: true` whitelists the recipient as part of the same mint, which collapses step 2 into step 3 when you are onboarding a new investor.
## 4. Launch the offering
```ts theme={null}
await bkn.sto.create(
{
chainId,
tokenizerEmail: 'issuer@example.com',
tokenSymbol: 'EXMPL',
tokenAmount: '1000',
offeringName: 'Series A',
startDate: '2026-09-01T00:00:00.000Z',
endDate: '2026-12-31T23:59:59.000Z',
acceptedCoin: 'USDT',
minRaiseUSD: '10000',
maxRaiseUSD: '100000',
minInvestment: '100',
maxInvestment: '10000',
},
write,
)
```
Every one of those fields is required — the type will tell you if one is missing. Dates are ISO 8601, and `acceptedCoin` is a payment token symbol: `USDT`, `USDC`, or `BKN`.
Once it is live, list your offerings and keep the `uuid`:
```ts theme={null}
const offerings = await bkn.sto.list({ tokenSymbol: 'EXMPL' })
```
## 5. Take an investment
The **investor** signs this one, not the tokenizer — so build a second client with the investor's signer, or pass their address as `signerAddress`.
```ts theme={null}
const investment = await bkn.sto.invest(
{
chainId,
tokenSymbol: 'EXMPL',
investorEmail: 'investor@example.com',
investorAddress: '0x1111111111111111111111111111111111111111',
investmentAmount: '1000',
paymentTokenSymbol: 'USDT',
},
{ execute: true, signerAddress: '0x1111111111111111111111111111111111111111' },
)
investment.transactions.length // may be 2: an ERC-20 approve, then the investment
```
The investor needs the payment token in their wallet, and prepare may return **two** transactions — an ERC-20 `approve` followed by the investment. The SDK signs and sends both, in order.
Track progress:
```ts theme={null}
await bkn.sto.investments({ tokenSymbol: 'EXMPL', id: offeringUuid })
await bkn.sto.balance({ tokenSymbol: 'EXMPL', id: offeringUuid })
```
## 6. Let investors claim their tokens
The investor signs this too.
```ts theme={null}
await bkn.sto.claim(
{
chainId,
tokenSymbol: 'EXMPL',
investorEmail: 'investor@example.com',
investorAddress: '0x1111111111111111111111111111111111111111',
},
{ execute: true, signerAddress: '0x1111111111111111111111111111111111111111' },
)
```
## 7. Close the offering
```ts theme={null}
await bkn.sto.close(
{ chainId, tokenSymbol: 'EXMPL', tokenizerEmail: 'issuer@example.com' },
write,
)
```
## 8. Distribute dividends
Only the tokenizer can do this.
```ts theme={null}
await bkn.tokenization.distributeDividend(
{ chainId, tokenSymbol: 'EXMPL', amount: '1000' },
write,
)
await bkn.tokenization.dividend({ tokenSymbol: 'EXMPL' })
```
## Broadcasting it yourself
Add `rpcUrl` to the client and `executionMode: 'client-broadcast'` to any step. You sign and submit through your own node, and the SDK confirms `{ txId, txHash }` back to Brickken so the transaction still appears in `get-transaction-status` and in the dApp.
```ts theme={null}
const bkn = new Brickken({ env: 'sandbox', apiKey, signer, rpcUrl: 'https://your-node.example' })
await bkn.tokenization.create(input, { ...write, executionMode: 'client-broadcast' })
```
If the confirmation fails after a successful broadcast, catch `BroadcastConfirmationError` and resume only that step — see [Execution modes](/sdk/execution-modes#when-confirmation-fails).
## When something fails
| Error | What it means |
| ------------------------------ | ------------------------------------------------------------------------------------- |
| `ValidationError` | Refused locally — usually a missing `signerAddress`, or a Dapp method with no API key |
| `AuthError` | The key is missing, wrong, or not accepted on that endpoint |
| `UnauthorizedTokenSymbolError` | Your key did not tokenize that symbol |
| `CreditsExhaustedError` | That specific method's credit balance is spent; `.method` names it |
| `RateLimitError` | Rate limited on prepare; `.retryAfterSeconds` says for how long |
| `ApiError` | Anything else non-2xx; `.status` and `.body` carry the API's own answer |
Each write method has its own credit balance, so exhausting mint credits does not block `newSto`. See [Errors](/sdk/errors) for the full list.
Every method above, mapped to its backend endpoint.
The raw request bodies, if you would rather not use the SDK.
# Installation
Source: https://docs.brickken.com/sdk/installation
Install brickken-sdk, and pick the signer adapter that matches your stack.
## Install
```bash theme={null}
npm install brickken-sdk
```
```bash theme={null}
pnpm add brickken-sdk
```
```bash theme={null}
yarn add brickken-sdk
```
## Requirements
| | |
| -------------------- | --------------------------------------------------------- |
| Node.js | 20 or newer |
| Browsers | Any runtime with global `fetch` and `WebCrypto` |
| Edge runtimes | Supported — the package is side-effect free and ships ESM |
| Runtime dependencies | One: `micro-eth-signer` |
The package publishes both ESM and CommonJS entry points with matching type declarations, so `import` and `require` both work.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
```
```js theme={null}
const { Brickken } = require('brickken-sdk')
```
## Signer adapters
Signing is optional. You only need a signer for x402 payments, `client-signed` and `client-broadcast` writes, and RAMS EIP-712 authorization — a read-only or Dapp-with-API-key integration needs none.
Three adapters ship with the package, each on its own subpath:
```ts theme={null}
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key' // raw hex key
import { fromEthers } from 'brickken-sdk/adapters/ethers' // ethers v6
import { fromViem } from 'brickken-sdk/adapters/viem' // viem Account or WalletClient
```
`ethers` and `viem` are **optional peer dependencies**, imported only from their own subpath. A consumer using neither installs neither, and nothing pulls them into your bundle.
```bash theme={null}
npm install ethers # only if you use brickken-sdk/adapters/ethers
npm install viem # only if you use brickken-sdk/adapters/viem
```
`fromPrivateKey` needs no peer dependency at all — it signs with the bundled `micro-eth-signer`.
See [Signers](/sdk/signers) for the `Signer` interface and how to bring your own KMS or MPC wallet.
## Verify the install
```ts theme={null}
import { Brickken, VERSION } from 'brickken-sdk'
console.log(VERSION)
const bkn = new Brickken({ env: 'sandbox' })
const network = await bkn.network.info({ chainId: '11155111' })
console.log(network)
```
`GET /get-network-info` needs no credential, so this confirms the package resolves and can reach the API before you configure anything.
Your first authenticated call.
# SDK
Source: https://docs.brickken.com/sdk/introduction
Typed TypeScript client for the Dapp API, the Agentic API, and RAMS mandates.
The **Brickken SDK** is the official TypeScript client for the whole platform: the [Dapp API](/api-reference/introduction) (tokenization, STOs, security-token operations), the [Agentic API](/api-reference/endpoint/agentic-methods-x402) (x402 payments, ERC-8004 identity and reputation, agent-owned tokens), and [RAMS mandates](/api-reference/endpoint/rams-overview) (ERC-8226).
It runs on Node 20+, in browsers, and on edge runtimes. The core has one runtime dependency.
```bash theme={null}
npm install brickken-sdk
```
Install `brickken-sdk` from npm.
View the public source repository.
## Why this surface
The SDK is the client to reach for when **your own code** is driving and you want typed methods for the full Dapp API. The [CLI](/cli/introduction) also reaches Dapp transaction methods and JSON endpoints through raw commands, while the SDK additionally covers the typed multipart surface. Unlike the [MCP server](/mcp/introduction), it runs in your process rather than behind a hosted agent endpoint.
* **One client, three APIs.** Dapp, agentic, and RAMS live behind the same `Brickken` instance.
* **Illegal combinations fail locally.** The SDK derives the credential mode from what you pass and refuses combinations the API rejects, before a request leaves your process.
* **Typed results, typed errors.** Every write returns the same `WriteResult` shape, and every failure is one of fourteen error classes you can branch on.
* **Your private key stays put.** It signs x402 payments, `client-signed` transactions, and RAMS typed data in your process, and is never sent anywhere.
## Two credentials, and they are alternatives
Brickken accepts an API key **or** an x402 payment, never both on one request. When `x-api-key` is present the API skips the payment path entirely, which means no payment is taken and `brickken-relayed` execution becomes unavailable.
| | `apiKey` | `signer`, no key |
| ------------------------------------ | :----------: | :--------------: |
| KYC link creation | Yes | No |
| Agent getters | Yes | Yes |
| Dapp API (tokenization, STOs, reads) | Yes | No |
| Agentic API, `client-signed` | Yes | Yes |
| Agentic API, `client-broadcast` | Yes | Yes |
| Agentic API, `brickken-relayed` | **Rejected** | Yes |
| RAMS reads and typed data | Yes | Yes |
The SDK enforces this locally:
```ts theme={null}
const bkn = new Brickken({ apiKey: 'key', signer })
await bkn.agent.register(input, { executionMode: 'brickken-relayed' })
// throws RelayedRequiresPaymentError, naming both fixes, with no network round trip
```
See [Authentication](/sdk/authentication) for the full matrix.
## Every write is prepare → sign → send
Preparing builds unsigned transactions; sending puts them on chain. The SDK defaults to **prepare-only**, so `execute: true` is an explicit opt-in.
```ts theme={null}
const prepared = await bkn.agentToken.create({ chainId: '84532', name: 'Agent Token', symbol: 'AGT' })
prepared.txId // the prepared transaction id
prepared.transactions // unsigned transactions
prepared.x402Requirements // what sending will cost
prepared.sent // undefined: nothing was sent
const done = await bkn.agentToken.create(
{ chainId: '84532', name: 'Agent Token', symbol: 'AGT' },
{ execute: true, waitForReceipt: true }, // waitForReceipt needs rpcUrl
)
done.payment?.requirement.amount
done.deployedAddress // recovered from the receipt
```
Payment metadata is always a sibling field on the result. It is never mixed into the response body.
## Where to go next
Runtimes, module formats, and optional peer dependencies.
A first Dapp read and a first agentic write, on sandbox.
Who signs, who broadcasts, and what each mode costs.
Every method, mapped to its backend endpoint.
## Prerequisites the API does not expose
Two things fail at request time and are invisible beforehand:
1. The wallet you pass as `signerAddress` must be **whitelisted by Brickken** before any prepare accepts it. Request it together with your [API key](/get-started/request-api-key).
2. An API key may only act on token symbols whose tokenizer email matches a `newTokenization` performed under that same key. Anything else raises `UnauthorizedTokenSymbolError`.
Each Dapp write method also carries its own credit balance, so one method can run out while others still work — that one surfaces as `CreditsExhaustedError`, carrying `.method`.
# Namespaces
Source: https://docs.brickken.com/sdk/namespaces
Every SDK method, mapped to the backend method or endpoint it reaches.
One client exposes nine namespaces. Writes take `(input, options?)` and return a [`WriteResult`](/sdk/quickstart#reading-the-result); reads take a query object and return the API's payload.
```ts theme={null}
const bkn = new Brickken({ env: 'sandbox', apiKey })
bkn.tokenization bkn.sto bkn.faucet bkn.agent bkn.agentToken
bkn.rams bkn.tx bkn.network bkn.discovery
```
## `tokenization`
Tokenization and security-token operations, plus the reads scoped to a token. **API key required**, default mode `client-signed`.
| Method | Backend |
| ------------------------------------- | -------------------------------- |
| `create(input, options?)` | `newTokenization` |
| `mint(input, options?)` | `mintToken` |
| `whitelist(input, options?)` | `whitelist` |
| `burn(input, options?)` | `burnToken` |
| `transfer(input, options?)` | `transferTo` |
| `transferFrom(input, options?)` | `transferFrom` |
| `approve(input, options?)` | `approve` |
| `distributeDividend(input, options?)` | `dividendDistribution` |
| `patchDocs(form)` | `PATCH /patch-token-docs` |
| `info(query)` | `GET /get-token-info` |
| `tokenizer(query)` | `GET /get-tokenizer-info` |
| `allowance(query)` | `GET /get-allowance` |
| `whitelistStatus(query)` | `GET /get-whitelist-status` |
| `balanceAndWhitelist(query)` | `GET /get-balance-whitelist` |
| `dividend(query)` | `GET /get-dividend-distribution` |
## `sto`
Security Token Offerings: the lifecycle, plus the reads scoped to an offering. **API key required**, default mode `client-signed`.
| Method | Backend |
| ------------------------- | -------------------------------- |
| `create(input, options?)` | `newSto` |
| `invest(input, options?)` | `newInvest` |
| `claim(input, options?)` | `claimTokens` |
| `close(input, options?)` | `closeOffer` |
| `list(query)` | `GET /get-stos` |
| `get(query)` | `GET /get-sto-by-id` |
| `balance(query)` | `GET /get-sto-balance` |
| `investments(query)` | `GET /get-investments-by-sto-id` |
| `investor(query)` | `GET /get-investor-info` |
## `faucet`
Sandbox/Forge BKN faucet. **API key or x402 signer; configure exactly one.**
| Method | Backend |
| --------------------------------------------------- | ------------------ |
| `requestBkn({ recipientAddress, idempotencyKey? })` | `POST /faucet/bkn` |
It requests 100 BKN on Ethereum Sepolia. An API key has 10 dedicated lifetime claims, separate from `mintToken`; x402 costs 0.01 USDC. The SDK generates and returns a UUID v4 when omitted and includes payment metadata for x402 calls. Recipients have a 24-hour cooldown.
## `agent`
ERC-8004 identity and reputation on Base. API key **or** x402; default mode `brickken-relayed`.
| Method | Backend |
| ------------------------------------ | ------------------------------------- |
| `list(query)` | `GET /get-agents` |
| `get(reference)` | `GET /get-agent-info` |
| `transactions(query)` | `GET /get-agent-transactions` |
| `register(input, options?)` | `POST /x402/agent/register` |
| `setUri(input, options?)` | `POST /x402/agent/set-uri` |
| `setMetadata(input, options?)` | `POST /x402/agent/set-metadata` |
| `setWallet(input, options?)` | `POST /x402/agent/set-wallet` |
| `transferOwnership(input, options?)` | `POST /x402/agent/transfer-ownership` |
| `feedback.give(input, options?)` | `POST /x402/agent/feedback/give` |
| `feedback.revoke(input, options?)` | `POST /x402/agent/feedback/revoke` |
| `feedback.respond(input, options?)` | `POST /x402/agent/feedback/respond` |
`register` returns `info.agentUuid` — save it, because `setUri`, `setMetadata`, and `transferOwnership` all need it.
The three getters accept an API key or x402. References use `agentUuid`, or `agentId` with `chainId`. In x402 mode, `list` also requires `ownerWalletAddress`, and the SDK checks that the payment signer matches it. Pagination limits are 1–100 and offsets are non-negative.
## `agentToken`
Agent-owned ERC-20 tokens. API key **or** x402; default mode `brickken-relayed`.
| Method | Backend |
| ------------------------------- | -------------------------------- |
| `create(input, options?)` | `POST /x402/token/create` |
| `mint(input, options?)` | `POST /x402/token/mint` |
| `burn(input, options?)` | `POST /x402/token/burn` |
| `transfer(input, options?)` | `POST /x402/token/transfer` |
| `transferFrom(input, options?)` | `POST /x402/token/transfer-from` |
| `approve(input, options?)` | `POST /x402/token/approve` |
Amounts here are `HumanAmount` and are scaled by `decimals`. RAMS caps are `RawBaseUnits` and are not. The types make the asymmetry visible so it cannot be crossed by accident.
## `rams`
ERC-8226 mandates. Every call defaults to `chainId: '11155111'` (Ethereum Sepolia). API key **or** x402; default mode `client-signed`.
### Lifecycle — relayable with a principal signature
| Method | Backend |
| -------------------------------- | -------------------------------- |
| `grantMandate(input, options?)` | `POST /x402/rams/grant-mandate` |
| `revokeMandate(input, options?)` | `POST /x402/rams/revoke-mandate` |
| `extendMandate(input, options?)` | `POST /x402/rams/extend-mandate` |
| `setOperator(input, options?)` | `POST /x402/rams/set-operator` |
These four accept `authorize: 'direct' | 'signature'`. With `'signature'` the SDK fetches the typed data, signs it, and resubmits the same parameters and **the same deadline**.
### Role-bound writes — never relayable
| Method | Backend |
| ------------------------------------ | ------------------------------------- |
| `execute(input, options?)` | `POST /x402/rams/execute` |
| `setExecutorAction(input, options?)` | `POST /x402/rams/set-executor-action` |
| `freezeAgent(input, options?)` | `POST /x402/rams/freeze-agent` |
| `unfreezeAgent(input, options?)` | `POST /x402/rams/unfreeze-agent` |
| `grantPrincipal(input, options?)` | `POST /x402/rams/grant-principal` |
| `revokePrincipal(input, options?)` | `POST /x402/rams/revoke-principal` |
Their on-chain call requires `msg.sender` to hold a role, so `brickken-relayed` is rejected locally.
### Reads and typed data
| Method | Backend |
| -------------------------------- | ------------------------------------- |
| `mandate(query)` | `GET /rams/mandate` |
| `status(query)` | `GET /rams/status` |
| `canExecute(query)` | `GET /rams/can-execute` |
| `complianceStatus(query)` | `GET /rams/compliance-status` |
| `executorAction(query)` | `GET /rams/executor-action` |
| `typedData.grantMandate(query)` | `GET /rams/typed-data/grant-mandate` |
| `typedData.revokeMandate(query)` | `GET /rams/typed-data/revoke-mandate` |
| `typedData.extendMandate(query)` | `GET /rams/typed-data/extend-mandate` |
| `typedData.setOperator(query)` | `GET /rams/typed-data/set-operator` |
The `typedData.*` calls return a `TypedDataEnvelope` carrying `domain`, `types`, `primaryType`, `message`, and — critically — `deadline` and `nonce`, which must be resubmitted verbatim alongside the signature.
## `tx` — the escape hatch
Any backend method is reachable the day it ships, without waiting for a typed namespace.
| Method | Backend |
| -------------------------- | -------------------------------------------------------------------- |
| `prepare(input, options?)` | `POST /prepare-transactions`, or the method's facade when one exists |
| `sign(transactions)` | Local only |
| `send(body)` | `POST /send-transactions` |
| `status(query)` | `GET /get-transaction-status` |
| `waitForReceipt(input)` | Local only, over `rpcUrl` |
```ts theme={null}
await bkn.tx.prepare({ method: 'someNewMethod', chainId: '8453', custom: 'value' })
await bkn.tx.sign(transactions)
await bkn.tx.send({ txId, signedTransactions })
await bkn.tx.status({ txId })
await bkn.tx.waitForReceipt({ txHash, chainId: '8453' })
```
An unknown method name passes through with only `chainId` normalized. A known one is mapped exactly as its typed namespace would map it. Three aliases from the CLI core are still accepted: `createToken`, `agentApprove`, and `newTokenizedAgent`.
## `network` and `discovery`
| Method | Backend | Credential |
| --------------------- | ----------------------- | ------------- |
| `network.info(query)` | `GET /get-network-info` | None required |
| `discovery.x402()` | `GET /.well-known/x402` | Public |
| `discovery.openapi()` | `GET /openapi.json` | Public |
## Chain identifiers
`CHAINS` is exported for the common values, and any `chainId` accepts decimal or hex — both are normalized to a canonical decimal string before the request.
```ts theme={null}
import { CHAINS, normalizeChainId } from 'brickken-sdk'
CHAINS.base // '8453'
CHAINS.baseSepolia // '84532'
CHAINS.sepolia // '11155111'
CHAINS.ethereum // '1'
CHAINS.bnb // '56'
CHAINS.polygon // '137'
CHAINS.polygonAmoy // '80002'
normalizeChainId('0x14a34') // '84532'
```
# Payments
Source: https://docs.brickken.com/sdk/payments
How the SDK handles the x402 handshake, and the three controls that bound what it can spend.
The SDK performs the whole x402 handshake for you. A send that answers `402 Payment Required` is decoded, quoted against your policy, signed locally, and retried with an `X-PAYMENT` header — all inside the call you already made.
You never construct a payment yourself. You decide whether one is allowed.
## Spending controls
x402 payments are non-refundable, and an autonomous agent with no policy is an unbounded spender. Three controls, all optional and all strongly recommended:
```ts theme={null}
new Brickken({
signer,
payment: {
maxAmountBaseUnits: '50000', // hard ceiling; throws before signing
onPaymentRequired: async quote => BigInt(quote.amountBaseUnits) <= 20_000n,
onPayment: record => audit.log(record), // called after settlement
},
})
```
| Control | When it runs | Effect |
| -------------------------- | ------------------------- | ---------------------------------------------------------------- |
| `maxAmountBaseUnits` | Before anything is signed | Refuses any quote above the ceiling, with `PaymentDeclinedError` |
| `onPaymentRequired(quote)` | Before anything is signed | Return `false` to refuse this specific payment |
| `onPayment(record)` | After the payment settles | Observe-only, for audit logging and accounting |
The ceiling is expressed in the advertised asset's **base units**, as an integer string. Base units are the only unambiguous unit available at that point: the quote does not always carry the asset's decimals.
## The quote
`onPaymentRequired` receives everything the server advertised, so a policy can branch on the asset and the network, not only the number:
```ts theme={null}
interface PaymentQuote {
requirement: X402Requirement
amountBaseUnits: string
displayPrice?: string // e.g. "0.010000000000000000 USDC"
tokenSymbol?: string
network: string // CAIP-2, e.g. "eip155:84532"
asset: string
payTo: string
routeKey?: string
transferMethodAssumed: boolean // true when the server did not advertise one and eip3009 was assumed
}
```
```ts theme={null}
payment: {
onPaymentRequired: async quote => {
if (quote.transferMethodAssumed) return false // refuse anything under-specified
if (quote.network !== 'eip155:84532') return false // testnet only
return BigInt(quote.amountBaseUnits) <= 20_000n
},
}
```
## What the SDK guarantees
* **Every signed value comes from the live header.** Chain, asset, transfer rail, amount, recipient, and the authorization window are read from the `PAYMENT-REQUIRED` response, never hardcoded.
* **No `txId` is ever paid twice.** The client remembers what it has paid for. The API reserves a payment and settles it only after the operation confirms, so a `pending` status must not be paid again — paying twice for one `txId` is money gone.
* **A paid send is never retried.** `429`, `5xx`, and transport failures retry with jittered backoff, but not a send for which a payment was already authorized. If that one fails, the error carries `.payment` so you can reconcile the charge.
* **Payment metadata stays a sibling.** `result.payment` is never spliced into the response body.
```ts theme={null}
const done = await bkn.agent.register(input, { execute: true })
done.payment?.payer
done.payment?.requirement.amount
done.payment?.settlement // decoded PAYMENT-RESPONSE header, when the server sent one
```
## What is free and what is not
Preparing is free in `brickken-relayed` mode only. The two client-controlled modes split the same total evenly across prepare and send — so a prepare-only call in `client-signed` mode is a paid call.
| Mode | Prepare | Send |
| ------------------ | -------------- | -------------- |
| `brickken-relayed` | Free | The full price |
| `client-signed` | Half the price | Half the price |
| `client-broadcast` | Half the price | Half the price |
Dapp writes authenticated with an API key are not x402-priced at all; they draw on the per-method credit balance attached to your key, and exhausting one raises `CreditsExhaustedError` carrying `.method`.
See [Pricing](/api-reference/endpoint/agentic-pricing) for the per-operation table.
## Payment asset
On Base Sepolia the x402 payment asset is Circle USDC:
```text theme={null}
0x036CbD53842c5426634e7929541eC2318f3dCF7e
```
It has 6 decimals and uses the EIP-3009 transfer method (EIP-712 name `USDC`, version `2`, 300-second authorization window). The signed authorization carries the transfer, so no separate ERC-20 `approve` transaction is required. A live sandbox quote looks like this:
```json theme={null}
{
"scheme": "exact",
"network": "eip155:84532",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"amount": "10000",
"payTo": "0x6b0173489007dE9E2e619eccd98E8fa9c610849a",
"maxTimeoutSeconds": 300,
"extra": {
"tokenSymbol": "USDC",
"displayPrice": "0.010000000000000000 USDC",
"assetTransferMethod": "eip3009",
"routeKey": "POST /send-transactions"
}
}
```
Read the chain, asset, transfer method, amount, and recipient from the `PAYMENT-REQUIRED` header of the live `402` response. Never hardcode the values above — they are an illustration, not a contract.
## Rate limits on prepare
Preparing is free in relayed mode, but not unlimited. The API caps how many prepared transactions a wallet may have outstanding and answers `429` with `Too many outstanding prepared transactions for this wallet`.
The SDK honours the `Retry-After` it comes with, but only for the configured number of attempts — three by default. After that it throws `RateLimitError`, carrying `.retryAfterSeconds`. A loop that prepares without sending will therefore slow down and then fail: treat the quota as a limit to respect, not a delay to wait out.
Every failure class, and which ones carry payment state.
# Quickstart
Source: https://docs.brickken.com/sdk/quickstart
A first Dapp read and a first agentic write with the SDK, on sandbox.
Everything here runs against **sandbox** — nothing moves real value.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
const bkn = new Brickken({ env: 'sandbox', apiKey: process.env.BRICKKEN_API_KEY })
const token = await bkn.tokenization.info({ tokenSymbol: 'EXMPL' })
const offerings = await bkn.sto.list({ tokenSymbol: 'EXMPL' })
```
Now prepare a write. Nothing is on chain yet — this returns unsigned transactions and a `txId`:
```ts theme={null}
const prepared = await bkn.tokenization.create(
{
chainId: '11155111',
tokenizerEmail: 'issuer@example.com',
name: 'Example Asset',
tokenSymbol: 'EXMPL',
tokenType: 'RWA_TOKEN',
supplyCap: '1000000',
url: 'https://example.com/token-docs',
},
{ signerAddress: '0xYourWhitelistedWallet' },
)
prepared.txId
prepared.transactions
```
Add a signer and `execute: true` to sign locally and let Brickken broadcast:
```ts theme={null}
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const signer = fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!)
const bkn = new Brickken({ env: 'sandbox', apiKey: process.env.BRICKKEN_API_KEY, signer })
const done = await bkn.tokenization.create(input, {
execute: true,
signerAddress: await signer.address(),
})
done.sent?.transactionHashes
```
`signerAddress` must be whitelisted by Brickken first. Ask for it when you [request your key](/get-started/request-api-key).
No API key. The signer pays with x402 and Brickken's relayer does the rest:
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key'
const bkn = new Brickken({
env: 'sandbox',
signer: fromPrivateKey(process.env.BRICKKEN_PRIVATE_KEY!),
payment: {
maxAmountBaseUnits: '50000', // ceiling in the asset's base units
onPaymentRequired: async quote => {
console.log(`about to pay ${quote.displayPrice}`)
return true
},
},
})
const agent = await bkn.agent.register(
{
chainId: '84532',
name: 'Research Agent',
image: 'https://example.com/agent.png', // required, must be publicly reachable
serviceName: 'A2A',
serviceEndpoint: 'https://agent.example/.well-known/agent-card.json',
},
{ execute: true }, // relayed prepare is free here; this also pays and sends
)
console.log(agent.info?.agentUuid) // save it: set-uri and set-metadata need it
console.log(agent.payment?.settlement) // what the payment settled to
```
Drop `execute: true` to prepare only and inspect the quote before committing:
```ts theme={null}
const prepared = await bkn.agent.register(input)
prepared.x402Requirements // what sending will cost
prepared.sent // undefined: nothing was sent
```
Fund the wallet with Base Sepolia USDC first — the exact asset and amount come from the live quote.
Two things work with nothing configured: the public reads, and preparing an x402-eligible agentic method.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
const bkn = new Brickken({ env: 'sandbox' })
const network = await bkn.network.info({ chainId: '11155111' })
```
Sending always needs a credential. Attempting it without one raises `ValidationError` before any request leaves your process.
## Reading the result
Every write returns the same shape, whatever the API or the execution mode:
```ts theme={null}
interface WriteResult {
txId: string
transactions: UnsignedTransactionLike[]
executionMode: ExecutionMode // the effective mode, stated rather than implied
info?: TInfo // method-specific data, e.g. agentUuid
x402Requirements?: X402Requirement[]
sent?: SendResult // present only when you passed execute: true
payment?: PaymentRecord // present only when a payment was made
receipt?: ReceiptSummary // present only with waitForReceipt
deployedAddress?: Address // recovered from the receipt, for deployments
raw: unknown
}
```
## Where to go next
Which credential reaches which method.
Who signs, who broadcasts, and what it costs.
The Dapp lifecycle end to end.
Register an agent, then deploy its token.
# Signers
Source: https://docs.brickken.com/sdk/signers
The Signer contract, the three bundled adapters, and how to bring your own KMS or MPC wallet.
The SDK does not own a wallet. It defines a minimal contract and signs through whatever you hand it.
```ts theme={null}
interface Signer {
address(): Promise
signTypedData(data: TypedDataDefinition): Promise
signTransaction?(transaction: TransactionRequest): Promise // optional
}
```
Three methods, one of them optional. Nothing derived from a signer is ever sent to the API except a signature.
## The bundled adapters
```ts theme={null}
import { fromPrivateKey } from 'brickken-sdk/adapters/private-key' // raw hex key
import { fromEthers } from 'brickken-sdk/adapters/ethers' // ethers v6
import { fromViem } from 'brickken-sdk/adapters/viem' // viem Account or WalletClient
```
| Adapter | Accepts | Peer dependency |
| ---------------- | ---------------------------------- | ------------------------------------------------ |
| `fromPrivateKey` | A `0x`-prefixed hex private key | None — signs with the bundled `micro-eth-signer` |
| `fromEthers` | Any ethers v6 signer | `ethers ^6` |
| `fromViem` | A viem `Account` or `WalletClient` | `viem ^2` |
`ethers` and `viem` are optional peers, imported only from their own subpath. A consumer using neither installs neither.
```ts theme={null}
import { Brickken } from 'brickken-sdk'
import { fromEthers } from 'brickken-sdk/adapters/ethers'
import { Wallet } from 'ethers'
const bkn = new Brickken({
env: 'sandbox',
signer: fromEthers(new Wallet(process.env.BRICKKEN_PRIVATE_KEY!)),
})
```
## Why `signTransaction` is optional
A KMS, MPC, or browser-wallet signer can sign typed data but not a raw transaction. That is deliberately enough for:
* the entire **`brickken-relayed`** path — your key signs only the x402 payment authorization, which is EIP-712 typed data;
* every **RAMS EIP-712 flow**, including the four signature-authorized lifecycle operations.
Requiring `signTransaction` would exclude exactly the custody setups an institutional integrator uses. What it does exclude is `client-signed` and `client-broadcast`: those need a raw transaction signature, and the SDK throws `ValidationError` locally if the configured signer cannot produce one.
```ts theme={null}
import { canSignTransactions } from 'brickken-sdk'
canSignTransactions(signer) // false for a typed-data-only signer
```
## Bring your own
Implement the three methods against your provider. Nothing else is required.
```ts theme={null}
import type { Signer, TypedDataDefinition, TransactionRequest } from 'brickken-sdk'
const kmsSigner: Signer = {
async address() {
return await kms.getAddress()
},
async signTypedData(data: TypedDataDefinition) {
return await kms.signTypedData(data)
},
// omit signTransaction entirely if the provider cannot sign raw transactions
}
const bkn = new Brickken({ env: 'production', signer: kmsSigner })
```
Adapters must forward the `TransactionRequest` to the underlying library **as-is**, rather than rebuilding it field by field. Prepare may include fee or type fields the SDK does not model, and dropping them changes what gets signed.
## Address checking
For `client-signed` and `client-broadcast` writes, the SDK compares the configured signer's address against the `signerAddress` you passed and refuses a mismatch locally, case-insensitively — before any transaction is signed.
```ts theme={null}
const signerAddress = await signer.address()
await bkn.tokenization.mint(input, { execute: true, signerAddress })
```
In `brickken-relayed` mode `signerAddress` must be **omitted**: Brickken supplies its relayer as the signer, and passing one raises `ValidationError`.
Which credential the SDK derives from what you pass.
# Skill
Source: https://docs.brickken.com/skill/introduction
Brickken AI-agent skill for the Dapp API, Agentic API, CLI, and MCP.
## Overview
The **Brickken Skill** is an AI-agent skill built on the open [Agent Skills](https://agentskills.io) format (`SKILL.md`). It works with any agent that supports the standard — including Claude Code, OpenAI Codex, Gemini CLI, Cursor, and GitHub Copilot — and helps agents choose and use the right Brickken surface:
* **Dapp API** when you have a Brickken API key.
* **Agentic API** when you do not have an API key and want to use private-key based x402 flows.
* **SDK** when the agent is writing TypeScript and wants a typed client for any of the three APIs.
* **MCP** when your agent can connect to the hosted Brickken MCP server.
* **CLI** when local signing and terminal execution are the best fit.
Use the skill when an agent needs to inspect Brickken endpoints, prepare request bodies, understand expected responses, or decide whether a task should go through the API, the SDK, the CLI, or MCP.
Download the standalone Brickken skill archive.
Install the public `brickken-cli` package from npm.
The typed TypeScript client the skill points agents at for code.
View the public CLI and bundled skill source.
Open the official Brickken MCP page.
## Install Only the Skill
Use this path when you want the Brickken Skill without installing the CLI globally. Download the archive and unzip it into your agent's skills directory:
| Agent | Personal skills directory |
| ------------------------ | ------------------------------------------------------- |
| Claude Code | `~/.claude/skills` |
| OpenAI Codex | `~/.codex/skills` |
| Gemini CLI | `~/.gemini/skills` |
| Cursor | `~/.cursor/skills` |
| GitHub Copilot / VS Code | `~/.copilot/skills` |
| Other agents | See your agent's documentation for its skills directory |
```bash theme={null}
export SKILLS_DIR=~/.claude/skills # set to your agent's skills directory
mkdir -p "$SKILLS_DIR"
curl -L https://raw.githubusercontent.com/fbrickken/docs/main/downloads/brickken-skill.zip -o /tmp/brickken-skill.zip
rm -rf "$SKILLS_DIR/brickken"
unzip -o /tmp/brickken-skill.zip -d "$SKILLS_DIR"
```
Verify the installation:
```bash theme={null}
test -f "$SKILLS_DIR/brickken/SKILL.md" && echo "Brickken skill installed"
```
Most agents also discover project-level skills from a directory inside the repository (for example `.claude/skills`, `.cursor/skills`, `.gemini/skills`, or `.github/skills`). Unzip the archive there instead to share the skill with your team through version control.
Start a new agent session after installing the skill so the agent reloads its available skills.
## Install with the CLI
If you already use the [Brickken CLI](/cli/introduction), install the bundled skill with:
```bash theme={null}
npm install -g brickken-cli
brickken skill install
```
By default the installer targets `~/.codex/skills`. Pass `--path` to install into any other agent's skills directory:
```bash theme={null}
brickken skill install --path ~/.claude/skills --force
```
To install without a global CLI install, run the installer through `npx`:
```bash theme={null}
npx brickken-cli skill install --path ~/.claude/skills --force
```
Inspect where the npm package bundles the skill:
```bash theme={null}
brickken skill path
```
## Configure Credentials
### Dapp API
Use the [Dapp API](/api-reference/introduction) when you have a Brickken API key.
```bash theme={null}
export BRICKKEN_API_KEY="YOUR_BRICKKEN_API_KEY"
```
The skill guides the agent toward API-key authenticated endpoints, request bodies, response examples, and transaction preparation or send flows.
### Agentic API
Use the [Agentic API](/api-reference/endpoint/agentic-methods-x402) when you want x402-paid flows without a Brickken API key. It runs on Base mainnet (`8453`) and Base Sepolia (`84532`).
```bash theme={null}
export BRICKKEN_PRIVATE_KEY="0xYOUR_PRIVATE_KEY"
export BRICKKEN_RPC_URL="https://sepolia.base.org" # Base Sepolia
```
Preparing an operation is free in `brickken-relayed` mode; client-controlled modes split the x402 USDC charge between prepare and send. In the recommended `brickken-relayed` mode the private key signs only the x402 payment, and Brickken's relayer signs, pays native gas, and broadcasts the operation — so you do not need to sign the blockchain transaction or hold native gas. In `client-signed` mode the key also signs the prepared transaction locally. Never send a private key to the Brickken API.
Do not paste production API keys or private keys into shared chats, tickets, terminals, or logs. Use your agent client's secret store or local environment variables.
## Example Prompts
```text theme={null}
Use the Brickken skill to prepare a new tokenization with my Dapp API key.
```
```text theme={null}
Use the Brickken skill to register an ERC-8004 agent with the Agentic API and no API key.
```
```text theme={null}
Use the Brickken skill to decide whether this workflow should use the API, CLI, or MCP.
```