curl --request POST \
--url https://api.sandbox.brickken.com/prepare-transactions \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"method": "newSto",
"chainId": "aa36a7",
"signerAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"offeringName": "Series A",
"tokenAmount": "1000",
"acceptedCoin": "USDT",
"startDate": "2026-09-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"minRaiseUSD": "10000",
"maxRaiseUSD": "100000",
"minInvestment": "100",
"maxInvestment": "10000"
}
'import requests
url = "https://api.sandbox.brickken.com/prepare-transactions"
payload = {
"method": "newSto",
"chainId": "aa36a7",
"signerAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"offeringName": "Series A",
"tokenAmount": "1000",
"acceptedCoin": "USDT",
"startDate": "2026-09-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"minRaiseUSD": "10000",
"maxRaiseUSD": "100000",
"minInvestment": "100",
"maxInvestment": "10000"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
method: 'newSto',
chainId: 'aa36a7',
signerAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
tokenizerEmail: 'tokenizer@example.com',
tokenSymbol: 'EXMPL',
offeringName: 'Series A',
tokenAmount: '1000',
acceptedCoin: 'USDT',
startDate: '2026-09-01T00:00:00.000Z',
endDate: '2026-12-31T23:59:59.000Z',
minRaiseUSD: '10000',
maxRaiseUSD: '100000',
minInvestment: '100',
maxInvestment: '10000'
})
};
fetch('https://api.sandbox.brickken.com/prepare-transactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.brickken.com/prepare-transactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'method' => 'newSto',
'chainId' => 'aa36a7',
'signerAddress' => '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
'tokenizerEmail' => 'tokenizer@example.com',
'tokenSymbol' => 'EXMPL',
'offeringName' => 'Series A',
'tokenAmount' => '1000',
'acceptedCoin' => 'USDT',
'startDate' => '2026-09-01T00:00:00.000Z',
'endDate' => '2026-12-31T23:59:59.000Z',
'minRaiseUSD' => '10000',
'maxRaiseUSD' => '100000',
'minInvestment' => '100',
'maxInvestment' => '10000'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.brickken.com/prepare-transactions"
payload := strings.NewReader("{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.brickken.com/prepare-transactions")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/prepare-transactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}"
response = http.request(request)
puts response.read_body{
"transactions": [
{
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0xabcdef1234567890abcdef1234567890abcdef12",
"value": "0x00",
"nonce": 3792,
"chainId": 11155111,
"data": "0xd362e8a70000000000000000000000000000000000000000000000000000000000000040...",
"type": 2,
"maxPriorityFeePerGas": "1150000",
"maxFeePerGas": "1156037",
"gasLimit": "0xccef"
}
],
"txId": "0x46adea7bdf49c576a760102e0d6bc9ecd650b3998588cd3d7f576a7973426aad",
"info": {
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"investorEmail": "investor@example.com"
}
}newSto
Launch a Security Token Offering for an existing tokenized asset.
curl --request POST \
--url https://api.sandbox.brickken.com/prepare-transactions \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"method": "newSto",
"chainId": "aa36a7",
"signerAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"offeringName": "Series A",
"tokenAmount": "1000",
"acceptedCoin": "USDT",
"startDate": "2026-09-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"minRaiseUSD": "10000",
"maxRaiseUSD": "100000",
"minInvestment": "100",
"maxInvestment": "10000"
}
'import requests
url = "https://api.sandbox.brickken.com/prepare-transactions"
payload = {
"method": "newSto",
"chainId": "aa36a7",
"signerAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"offeringName": "Series A",
"tokenAmount": "1000",
"acceptedCoin": "USDT",
"startDate": "2026-09-01T00:00:00.000Z",
"endDate": "2026-12-31T23:59:59.000Z",
"minRaiseUSD": "10000",
"maxRaiseUSD": "100000",
"minInvestment": "100",
"maxInvestment": "10000"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
method: 'newSto',
chainId: 'aa36a7',
signerAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
tokenizerEmail: 'tokenizer@example.com',
tokenSymbol: 'EXMPL',
offeringName: 'Series A',
tokenAmount: '1000',
acceptedCoin: 'USDT',
startDate: '2026-09-01T00:00:00.000Z',
endDate: '2026-12-31T23:59:59.000Z',
minRaiseUSD: '10000',
maxRaiseUSD: '100000',
minInvestment: '100',
maxInvestment: '10000'
})
};
fetch('https://api.sandbox.brickken.com/prepare-transactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.brickken.com/prepare-transactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'method' => 'newSto',
'chainId' => 'aa36a7',
'signerAddress' => '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
'tokenizerEmail' => 'tokenizer@example.com',
'tokenSymbol' => 'EXMPL',
'offeringName' => 'Series A',
'tokenAmount' => '1000',
'acceptedCoin' => 'USDT',
'startDate' => '2026-09-01T00:00:00.000Z',
'endDate' => '2026-12-31T23:59:59.000Z',
'minRaiseUSD' => '10000',
'maxRaiseUSD' => '100000',
'minInvestment' => '100',
'maxInvestment' => '10000'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.brickken.com/prepare-transactions"
payload := strings.NewReader("{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.brickken.com/prepare-transactions")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/prepare-transactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"method\": \"newSto\",\n \"chainId\": \"aa36a7\",\n \"signerAddress\": \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n \"tokenizerEmail\": \"tokenizer@example.com\",\n \"tokenSymbol\": \"EXMPL\",\n \"offeringName\": \"Series A\",\n \"tokenAmount\": \"1000\",\n \"acceptedCoin\": \"USDT\",\n \"startDate\": \"2026-09-01T00:00:00.000Z\",\n \"endDate\": \"2026-12-31T23:59:59.000Z\",\n \"minRaiseUSD\": \"10000\",\n \"maxRaiseUSD\": \"100000\",\n \"minInvestment\": \"100\",\n \"maxInvestment\": \"10000\"\n}"
response = http.request(request)
puts response.read_body{
"transactions": [
{
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0xabcdef1234567890abcdef1234567890abcdef12",
"value": "0x00",
"nonce": 3792,
"chainId": 11155111,
"data": "0xd362e8a70000000000000000000000000000000000000000000000000000000000000040...",
"type": 2,
"maxPriorityFeePerGas": "1150000",
"maxFeePerGas": "1156037",
"gasLimit": "0xccef"
}
],
"txId": "0x46adea7bdf49c576a760102e0d6bc9ecd650b3998588cd3d7f576a7973426aad",
"info": {
"tokenizerEmail": "tokenizer@example.com",
"tokenSymbol": "EXMPL",
"investorEmail": "investor@example.com"
}
}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. |
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 asmaxRaiseUSD / 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
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 theONGOING state. Preparing a second returns
Tokenizer already has an ongoing STO.
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 youtxId and an array of unsigned transactions — you still have to sign and submit them.
Sign every returned transaction
signerAddress, or investorAddress for newInvest and claimTokens. It must be whitelisted by Brickken, and it needs native gas on the target chain.Submit the signed payloads
POST them to /send-transactions 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.Poll until it confirms
GET /get-transaction-status with the txId. A pending status means it is broadcast but not yet mined — do not resubmit.newInvest, then
closeOffer and
claimTokens for the rest of the lifecycle.Authorizations
Body
Required. Operation to prepare. Must be newSto for this endpoint.
newSto "newSto"
Required. Blockchain network identifier. Hex format is recommended, for example Sepolia aa36a7.
"aa36a7"
Required. Tokenizer wallet that signs the offering creation.
"0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
Required. Email of the tokenizer that owns the token. The token must not already have an ongoing offering; a second one is rejected with Tokenizer already has an ongoing STO.
"tokenizer@example.com"
Required. Symbol of the token offered. The token must already be deployed on chainId.
"EXMPL"
Required. Name of the STO offering.
"Series A"
Required. Number of tokens offered in the STO. This is the field some clients call totalTokensOffered, which is not accepted.
"1000"
Required. Symbol of the payment token accepted for investments. It must be supported on chainId. This method does not accept paymentTokenSymbol.
"USDT"
Required. STO start date, as explicit UTC with a Z suffix or a unix timestamp. A timestamp with no offset is read as UTC. It must be in the future when the transaction is mined and earlier than endDate; set it at least 10 minutes after the planned send time.
"2026-09-01T00:00:00.000Z"
Required. STO end date, as explicit UTC with a Z suffix or a unix timestamp. There is no minimum offering duration, but the offering cannot be closed before this date has passed.
"2026-12-31T23:59:59.000Z"
Required. Minimum raise amount in USD. This is the offering's soft cap: an offering that ends below it enters rollback and refunds investors instead of delivering tokens.
"10000"
Required. Maximum raise amount in USD. Token price is derived as maxRaiseUSD / tokenAmount; there is no tokenPrice input.
"100000"
Required. Minimum investment amount.
"100"
Required. Maximum investment amount.
"10000"
Response
Successful response
Array of unsigned transaction objects ready for signing
Show child attributes
Show child attributes
Unique identifier for this transaction batch (required for /send-transactions). This is NOT a blockchain transaction hash.
"0x46adea7bdf49c576a760102e0d6bc9ecd650b3998588cd3d7f576a7973426aad"
Metadata about the operation
Show child attributes
Show child attributes