Testnet
Request Testnet Faucet (Signed)
Request testnet funds via the unified transaction endpoint
POST
/
order
Request faucet
curl -X POST https://exchange-api.bulk.trade/api/v1/order \
-H "Content-Type: application/json" \
-d '{"actions":[{"faucet":{"u":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7"}}],"nonce":1704067200000,"account":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7","signer":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7","signature":"5j7s...base58..."}'
import requests
url = "https://exchange-api.bulk.trade/api/v1/order"
payload = {
"actions": [{ "faucet": { "u": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7" } }],
"nonce": 1704067200000,
"account": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signer": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signature": "5j7s...base58..."
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
actions: [{faucet: {u: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7'}}],
nonce: 1704067200000,
account: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
signer: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
signature: '5j7s...base58...'
})
};
fetch('https://exchange-api.bulk.trade/api/v1/order', 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://exchange-api.bulk.trade/api/v1/order",
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([
'actions' => [
[
'faucet' => [
'u' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7'
]
]
],
'nonce' => 1704067200000,
'account' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
'signer' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
'signature' => '5j7s...base58...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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://exchange-api.bulk.trade/api/v1/order"
payload := strings.NewReader("{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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://exchange-api.bulk.trade/api/v1/order")
.header("Content-Type", "application/json")
.body("{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://exchange-api.bulk.trade/api/v1/order")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": [
{
"deposit": {
"amount": 10000
}
}
]
}
}
}
This action is only available on paper / testnet environments. You can claim once every 24 hours per account.Use the testnet endpoint,
https://exchange-api.bulk.trade/api/v1, for the faucet. It is not available through the primary mainnet endpoint.POST /order endpoint. Send a transaction with a faucet action in the actions array.
Transaction Envelope
Every request toPOST /order has this shape:
{
"actions": [Action, ...],
"nonce": 1704067200000,
"account": "base58_pubkey",
"signer": "base58_pubkey",
"signature": "base58_signature"
}
faucet object.
Faucet Action
| Field | Type | Description |
|---|---|---|
u | string | Recipient public key (base58). |
Request Example
{
"actions": [
{"faucet": {"u": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7"}}
],
"nonce": 1704067200000,
"account": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signer": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signature": "5j7sVt3k2YxPqH4w..."
}
Response
SameOrderResponse format as other actions. Success returns a deposit status:
{
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": [{"deposit": {"amount": 10000.0}}]
}
}
}
depositFailed:
{
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": [{"depositFailed": {"message": "Rate limit exceeded"}}]
}
}
}
Before You Start
See the Transaction Signing guide for how to sign your requests.Nonce: Use a unique value (e.g. timestamp in nanoseconds):
BigInt(Date.now()) * 1_000_000nBody
application/json
Transaction with a single faucet action
Must contain exactly one faucet action
Show child attributes
Show child attributes
Unique nonce (e.g. nanoseconds)
Account public key (base58)
Signer public key (base58)
Ed25519 signature (base58)
⌘I
Request faucet
curl -X POST https://exchange-api.bulk.trade/api/v1/order \
-H "Content-Type: application/json" \
-d '{"actions":[{"faucet":{"u":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7"}}],"nonce":1704067200000,"account":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7","signer":"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7","signature":"5j7s...base58..."}'
import requests
url = "https://exchange-api.bulk.trade/api/v1/order"
payload = {
"actions": [{ "faucet": { "u": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7" } }],
"nonce": 1704067200000,
"account": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signer": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7",
"signature": "5j7s...base58..."
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
actions: [{faucet: {u: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7'}}],
nonce: 1704067200000,
account: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
signer: 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
signature: '5j7s...base58...'
})
};
fetch('https://exchange-api.bulk.trade/api/v1/order', 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://exchange-api.bulk.trade/api/v1/order",
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([
'actions' => [
[
'faucet' => [
'u' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7'
]
]
],
'nonce' => 1704067200000,
'account' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
'signer' => 'FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7',
'signature' => '5j7s...base58...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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://exchange-api.bulk.trade/api/v1/order"
payload := strings.NewReader("{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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://exchange-api.bulk.trade/api/v1/order")
.header("Content-Type", "application/json")
.body("{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://exchange-api.bulk.trade/api/v1/order")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"actions\": [\n {\n \"faucet\": {\n \"u\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\"\n }\n }\n ],\n \"nonce\": 1704067200000,\n \"account\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signer\": \"FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7\",\n \"signature\": \"5j7s...base58...\"\n}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": [
{
"deposit": {
"amount": 10000
}
}
]
}
}
}