Developer guide
Overview
Base URL: https://developers.tokenanvil.store/v1. JSON in, JSON out, HTTPS only. The API is for servers; it does not send CORS headers, so do not call it from a browser with your key.
How it works
- Get a key. Connect your wallet in the portal, pay $10 once, create your key.
- Host metadata (optional):
POST /v1/metadatareturns a stable URL for your token's name, image and links. - Build:
POST /v1/tokensreturns an unsigned transaction that creates the token and pays the $2.99 fee. - Sign and send with your own wallet. We never see your private key.
- Verify (optional):
GET /v1/transactions/{signature}confirms mint, supply and fee on-chain.
Quickstart
# 1) host the metadata
curl -s https://developers.tokenanvil.store/v1/metadata \
-H "Authorization: Bearer $TOKENANVIL_KEY" -H "Content-Type: application/json" \
-d '{"name":"My Token","symbol":"MYT","description":"A demo token","imageUrl":"https://example.com/logo.png"}'
# 2) build the unsigned transaction (use the metadataUri from step 1)
curl -s https://developers.tokenanvil.store/v1/tokens \
-H "Authorization: Bearer $TOKENANVIL_KEY" -H "Content-Type: application/json" \
-d '{"payer":"YOUR_WALLET","name":"My Token","symbol":"MYT","supply":"1000000","decimals":9,"revokeMint":true,"metadataUri":"METADATA_URI"}'
Authentication
Send your key as a bearer token: Authorization: Bearer tak_live_xxxxxxxx_.... Keys are shown once when created. We store only a keyed hash, so a lost key cannot be recovered: rotate it in the portal (the old key stops working at once) or delete it. Keep it server-side and out of source control.
Hosted metadata
POST /v1/metadata stores your image (PNG, JPEG or WebP, up to 1 MB) and a Metaplex-standard JSON, and returns metadataUri. Hosted files are public and permanent while the service operates. If you need to control hosting yourself, skip this call and pass your own https metadataUri to /v1/tokens.
Build a token
POST /v1/tokens validates your parameters, checks the payer's SOL balance, simulates the transaction on Solana and returns it unsigned. Defaults: decimals 9, revokeFreeze true (no freeze authority), revokeMint false. Revoking mint authority fixes the supply forever and cannot be undone. The mint address is derived from the payer and a random seed, so no mint keypair exists and the payer is the only signer.
Sign and submit
The transaction is a legacy transaction with one required signature. It is valid for about a minute. Node.js:
import { Connection, Keypair, Transaction } from "@solana/web3.js";
import bs58 from "bs58";
const API = "https://developers.tokenanvil.store/v1";
const headers = { Authorization: `Bearer ${process.env.TOKENANVIL_KEY}`, "Content-Type": "application/json" };
const wallet = Keypair.fromSecretKey(bs58.decode(process.env.WALLET_SECRET_KEY)); // your own server wallet
const post = async (path, body) => {
const res = await fetch(API + path, { method: "POST", headers, body: JSON.stringify(body) });
const json = await res.json();
if (!res.ok) throw new Error(JSON.stringify(json.error));
return json;
};
// 1) host metadata + image
const meta = await post("/metadata", { name: "My Token", symbol: "MYT", description: "A demo token", imageUrl: "https://example.com/logo.png" });
// 2) build the unsigned transaction
const built = await post("/tokens", {
payer: wallet.publicKey.toBase58(), name: "My Token", symbol: "MYT",
supply: "1000000", decimals: 9, revokeMint: true, revokeFreeze: true, metadataUri: meta.metadataUri,
});
// 3) sign it yourself and send it (within ~60 seconds)
const tx = Transaction.from(Buffer.from(built.transaction, "base64"));
tx.partialSign(wallet);
const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");
const signature = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(signature, "confirmed");
// 4) optional: have us verify mint, supply and fee on-chain
const check = await (await fetch(`${API}/transactions/${signature}`, { headers })).json();
console.log(built.mint, check.status, check.feeVerified);Python (illustrative; check the current solders API):
import base64, os, requests
from solders.keypair import Keypair
from solders.transaction import Transaction
API = "https://developers.tokenanvil.store/v1"
H = {"Authorization": f"Bearer {os.environ['TOKENANVIL_KEY']}"}
kp = Keypair.from_base58_string(os.environ["WALLET_SECRET_KEY"])
meta = requests.post(f"{API}/metadata", headers=H, json={"name": "My Token", "symbol": "MYT", "imageUrl": "https://example.com/logo.png"}).json()
built = requests.post(f"{API}/tokens", headers=H, json={
"payer": str(kp.pubkey()), "name": "My Token", "symbol": "MYT", "supply": "1000000",
"decimals": 9, "revokeMint": True, "metadataUri": meta["metadataUri"]}).json()
tx = Transaction.from_bytes(base64.b64decode(built["transaction"]))
tx.partial_sign([kp], tx.message.recent_blockhash)
sent = requests.post(f"{API}/transactions", headers=H, json={"transaction": base64.b64encode(bytes(tx)).decode()}).json()
print(built["mint"], sent["signature"])
Verify
GET /v1/transactions/{signature} reads the confirmed transaction from Solana and reports status, the mint, the full supply and whether the TokenAnvil fee is present (feeVerified). A creation without the fee in the same transaction is not counted and may lead to key suspension.
Pricing and limits
| Item | Amount |
|---|---|
| API key (one time) | $10, in SOL, USDC or USDT. One active key per purchase; rotating is free; after deleting a key you can create a new one on the same purchase. |
| Per token | $2.99, paid in SOL inside each creation transaction |
| Solana network costs | About 0.016 to 0.02 SOL per token (rent, Metaplex metadata fee, network fee), paid by the payer wallet to Solana |
| Requests | 600 per hour per key |
| Tokens | 25 per day per key (resets 00:00 UTC) |
| Hosted metadata | 100 per day, images up to 1 MB |
Need higher limits? Contact us.
Errors
Errors look like {"error":{"code":"invalid_request","message":"...","fields":{"symbol":"..."}}}.
| Status and code | Meaning |
|---|---|
400 invalid_request | A field is missing or invalid. error.fields names each one. |
400 insufficient_funds | The payer wallet cannot cover the fee plus Solana costs. |
400 simulation_failed | Solana says the transaction would fail. Nothing was built. |
401 unauthorized | Missing, wrong, revoked or banned key. |
404 not_found | Unknown endpoint, token or transaction. |
413 payload_too_large | Request body is too large. |
429 rate_limited / daily_limit | Per-hour request limit or daily token or metadata limit reached. |
503 price_unavailable | The SOL price feed is temporarily unavailable. Retry. |
500 server_error | Our side. Retry; contact us if it persists. |
Security and responsibility
- Non-custodial: we cannot move your funds or tokens. Always inspect what you sign.
- Use a dedicated server wallet with limited funds for automation.
- Rotate keys that may have leaked. Deleted keys stop working immediately.
- You are responsible for the tokens you create, their names and claims. Impersonating projects or brands, scams and rug pulls are prohibited and lead to key revocation.
- We may refuse names that match well-known projects. Tokens are not investments and TokenAnvil gives no financial advice.
Changelog
2026-10-13: v1 released: metadata hosting, token build, submit, verify.