GraveMint v1 API
Base URL — https://api.solanadeads.com/gravemint/v1
Recorded responses below show the API output at capture time. Live consoles let you inspect current responses for the sample collection.
Authentication
Choose a key for the environment making the request.
| header | bounded by | use it | |
|---|---|---|---|
| Publishable | X-API-Key: gm_pub_… | the origin allow-list on the key | in your web page |
| Secret | X-API-Key: gm_live_… | secrecy | from your server |
Use a publishable key in browser applications and a secret key on your server. Register each browser origin, including staging and previews, and keep server keys out of browser bundles. See keys and origins for sandbox keys and collection scope.
Try it live
Use Send to inspect the request and response, including status and timing. The consoles use a sandbox key scoped to DEAD DAWGS — ONCHAIN TEST on solana-devnet. This key is restricted to registered documentation origins, the sample collection and test networks.
Preparation makes a live devnet request and may reserve supply when a funded wallet is supplied. Execution is an example builder: it requires a wallet-signed transaction and cannot be sent from this page.
Discovery
/No parameters. Confirms the surface and its stability contract.
Sent
GET https://api.solanadeads.com/gravemint/v1/
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const result = await gm.v1.version();
console.log(result);Read a drop
Address a collection by its short ID, UUID or on-chain address. Use short IDs in public links and preserve address case.
/collections/{identifier}Everything needed to build a mint page, in one call.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const collection = await gm.v1.collection("7zn5qa");
console.log(collection);Where are the sales phases?
The collection response includes phases: { active, upcoming, all }. Each array contains phase schedules, wallet limits and resolved priceDisplay values. The response also includes serverTime for countdowns.
Use the returned phase status. GraveMint manages phase transitions on the server; refresh the collection response when a countdown expires to obtain the current state.
Check eligibility
Server-side verdict for one wallet against one phase. Gating criteria stay on our side — you receive the decision, never the allowlist.
/collections/{collectionId}/eligibility/{phaseId}/{walletAddress}Checks wallet requirements. phase.hasStarted and phase.hasEnded report the time window separately.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/eligibility/8426923e-0d64-480d-925f-90324c2dedf5/11111111111111111111111111111111
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const eligibility = await gm.v1.eligibility("7zn5qa", "8426923e-0d64-480d-925f-90324c2dedf5", "11111111111111111111111111111111");
console.log(eligibility);The rest of the drop
Everything else a mint page is built from, scoped to the key the same way.
The sample key is scoped to one collection. Requests for another collection return 403 COLLECTION_NOT_IN_SCOPE.
/collections/{identifier}/galleryAvailable artwork, with limit and offset pagination.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/gallery?limit=3
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const gallery = await gm.v1.gallery("7zn5qa", {
limit: 3,
});
console.log(gallery);/collections/{identifier}/recently-mintedThe live 'just minted' feed.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/recently-minted?limit=3
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const recentlyMinted = await gm.v1.recentlyMinted("7zn5qa", {
limit: 3,
});
console.log(recentlyMinted);/collections/{collectionId}/wallet-mints/{walletAddress}Minted and remaining counts per phase, including bonus mints. Use this response for wallet counts; eligibility uses separate allocation rules.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/wallet-mints/11111111111111111111111111111111
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const walletMints = await gm.v1.walletMints("7zn5qa", "11111111111111111111111111111111");
console.log(walletMints);/collections/{identifier}/bountyBounty configuration and rewards. Collections without a bounty return an empty summary.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/bounty
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const bounty = await gm.v1.bounty("7zn5qa");
console.log(bounty);/collections/{identifier}/bounty-prizesThe public prize table. Returns enabled: false when there is no bounty.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/bounty-prizes
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const bountyPrizes = await gm.v1.bountyPrizes("7zn5qa");
console.log(bountyPrizes);Claim codes
Read the collection's code configuration and the benefits a wallet has already redeemed. Validation checks a code without redeeming it or consuming a use.
/collections/{collectionId}/claim-codesDoes this drop use codes, and of what kind?
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/claim-codes
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const claimCodes = await gm.v1.claimCodes("7zn5qa");
console.log(claimCodes);/collections/{collectionId}/claim-codes/benefits/{walletAddress}What a wallet is already entitled to from codes it has redeemed.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/claim-codes/benefits/11111111111111111111111111111111
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const claimCodeBenefits = await gm.v1.claimCodeBenefits("7zn5qa", "11111111111111111111111111111111");
console.log(claimCodeBenefits);/collections/{collectionId}/claim-codes/validateREAD-ONLY — checking a code does not redeem it or consume a use.
Sent
POST https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/claim-codes/validate
X-API-Key: gm_test_47716d…
Content-Type: application/json
{
"code": "TRY-A-CODE"
}Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const validateClaimCode = await gm.v1.validateClaimCode("7zn5qa", "TRY-A-CODE");
console.log(validateClaimCode);Pricing
Use priceDisplay on the phase for the initial display. Pegged prices can be marked approximate. The helpers below refresh pegged or Dutch prices without reloading the collection.
/token-pricesPlatform token prices — what an SPL-priced drop is worth in USD. Global: it names no collection, so it carries no drop data and needs no collection scope.
Sent
GET https://api.solanadeads.com/gravemint/v1/token-prices
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const getTokenPrices = await gm.platform.getTokenPrices();
console.log(getTokenPrices);/phases/{phaseId}/pegged-priceThe resolved amount for a USD- or native-pegged phase. Scoped through the phase's own collection — a phase id is not a way around collection scope.
Sent
GET https://api.solanadeads.com/gravemint/v1/phases/8426923e-0d64-480d-925f-90324c2dedf5/pegged-price
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const peggedPrice = await gm.v1.peggedPrice("8426923e-0d64-480d-925f-90324c2dedf5");
console.log(peggedPrice);/phases/{phaseId}/dutch-priceThe live price of a dynamic Dutch phase, which moves with time.
Sent
GET https://api.solanadeads.com/gravemint/v1/phases/8426923e-0d64-480d-925f-90324c2dedf5/dutch-price
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const dutchPrice = await gm.v1.dutchPrice("8426923e-0d64-480d-925f-90324c2dedf5");
console.log(dutchPrice);Supply, traits and social proof
/collections/{collectionId}/availabilityApproximate supply counts, including burned items. available may be null for open-ended supply; pending reservations can still appear available.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/availability
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const availability = await gm.v1.availability("7zn5qa");
console.log(availability);/collections/{identifier}/traitsTrait names and values, for filtering a gallery.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/traits
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const traits = await gm.v1.traits("7zn5qa");
console.log(traits);/collections/{identifier}/all-mintedOne page of minted items. Continue with limit and offset for a full history.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/all-minted
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const allMinted = await gm.v1.allMinted("7zn5qa");
console.log(allMinted);/collections/{identifier}/top-holdersLargest holders.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/top-holders
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const topHolders = await gm.v1.topHolders("7zn5qa");
console.log(topHolders);/collections/{identifier}/top-mintersWho minted the most.
Sent
GET https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/top-minters
X-API-Key: gm_test_47716d…Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const topMinters = await gm.v1.topMinters("7zn5qa");
console.log(topMinters);What your key can reach
Every route that names a collection is scoped to the collections your key was issued for. Measured against production with a key scoped to one drop, asking for another:
| Request | Result |
|---|---|
GET /collections/{other} | 403 COLLECTION_NOT_IN_SCOPE |
GET /collections/{other}/gallery | 403 |
GET /collections/{other}/recently-minted | 403 |
GET /collections/{other}/bounty · /bounty-prizes | 403 |
GET /collections/{other}/wallet-mints/{wallet} | 403 |
GET /collections/{other}/eligibility/{phase}/{wallet} | 403 |
POST /prepare-mint with another drop's id | 403 |
GET / (version — names no collection) | 200 |
The refusal is deliberately identical whether or not the drop exists, so an unauthorised caller learns only that this key cannot read it — never whether the collection is real.
Two further bounds apply on top of scope: a key with an origin list is refused from any other origin (403 ORIGIN_NOT_ALLOWED, including a request with no Origin at all, which is why a browser key cannot be used server-side), and a sandbox key is refused on any production chain (403 SANDBOX_KEY_ON_MAINNET).
Prepare a mint
Preparation checks eligibility, pricing and supply, then creates transactions for signing. The default sample wallet is expected to return INSUFFICIENT_BALANCE before a supply reservation. A funded devnet wallet can receive transactions and sessions, reserving devnet supply for the session lifetime.
/prepare-mintReturns transactions for your wallet to sign and GraveMint to submit.
Sent
POST https://api.solanadeads.com/gravemint/v1/prepare-mint
X-API-Key: gm_test_47716d…
Content-Type: application/json
{
"collectionId": "2e239364-fc9b-4191-ba62-b57dbac76394",
"phaseId": "8426923e-0d64-480d-925f-90324c2dedf5",
"walletAddress": "11111111111111111111111111111111",
"quantity": "1"
}Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const result = await gm.mint.prepare({
collectionId: "2e239364-fc9b-4191-ba62-b57dbac76394",
phaseId: "8426923e-0d64-480d-925f-90324c2dedf5",
walletAddress: "11111111111111111111111111111111",
quantity: 1,
});
console.log(result);Execute a mint
/execute-mintnot sentSend the signed transaction as base64. A transactionHash returns CLIENT_BROADCAST_NOT_ALLOWED.
Sent
POST https://api.solanadeads.com/gravemint/v1/execute-mint
X-API-Key: gm_test_47716d…
Content-Type: application/json
{
"sessionId": "<from prepare-mint>",
"signedTransaction": "<base64 signed tx>"
}Received
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_test_your_key" });
const result = await gm.mint.execute({
sessionId: "<from prepare-mint>",
signedTransaction: "<base64 signed tx>",
});
console.log(result);Recorded responses
These examples were captured from the API. Sample collection data can change; use the consoles above for current values.
Discovery
Confirms the surface and its stability contract.
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
const result = await gm.v1.version();
console.log(result);import { GraveMintClient, GraveMintError } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
try {
const result = await gm.v1.version();
console.log(result);
} catch (err) {
// `code` is stable — branch on it. `message` is a sentence you can show a user.
if (err instanceof GraveMintError) console.error(err.code, err.message);
else throw err;
}curl -s \
-H 'X-API-Key: gm_pub_your_key' \
'https://api.solanadeads.com/gravemint/v1/'{
"success": true,
"version": "v1",
"stability": "additive-only",
"docs": "https://www.npmjs.com/package/@solanadeads/gravemint"
}Reading a drop
One call returns everything needed to build a mint page: the collection, every phase with its resolved price, live supply, and our clock for countdowns.
Use the collection's short ID, UUID or on-chain address. Recorded examples can reflect an earlier API deployment; the published SDK reference describes the current identifier contract.
GET /v1/collections/:identifier
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
const collection = await gm.v1.collection("7zn5qa");
console.log(collection);import { GraveMintClient, GraveMintError, type V1Collection } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
try {
const collection: V1Collection = await gm.v1.collection("7zn5qa");
console.log(collection);
} catch (err) {
// `code` is stable — branch on it. `message` is a sentence you can show a user.
if (err instanceof GraveMintError) console.error(err.code, err.message);
else throw err;
}curl -s \
-H 'X-API-Key: gm_pub_your_key' \
'https://api.solanadeads.com/gravemint/v1/collections/7zn5qa'{
"success": true,
"collection": {
"id": "2e239364-fc9b-4191-ba62-b57dbac76394",
"shortId": "7zn5qa",
"name": "DEAD DAWGS - ONCHAIN TEST",
"symbol": "ONCHAIN1",
"description": "Testing",
"image": "https://gravemint-storage.s3.us-east-1.amazonaws.com/launchpad-collection-images/1774886146380/collection.png",
"bannerImage": "https://gravemint-storage.s3.us-east-1.amazonaws.com/launchpad-collection-images/1774886157110/banner.png",
"chain": "solana-devnet",
"collectionAddress": "7mS96x56GoeE23R8DRXYusjecFY9udEw2NTnedqJ1Ed5",
"contractAddress": null,
"externalUrl": null,
"twitter": null,
"discord": null,
"isVerified": false
},
"stats": {
"totalSupply": 888,
"mintedCount": 21,
"availableCount": 867,
"percentMinted": 2.364864864864865
},
"phases": {
"all": [
{
"id": "8426923e-0d64-480d-925f-90324c2dedf5",
"name": "Public",
"status": "active",
"startDate": "2026-03-30T16:02:00.000Z",
"endDate": null,
"priceDisplay": {
"kind": "amount",
"amount": 1,
"currency": "USD",
"isFree": false
},
"bogo": null,
"isGated": false,
"maxPerWallet": 100,
"maxPerTransaction": 10,
"phaseSupply": null,
"msUntilStart": null,
"msUntilEnd": null
}
],
"active": [
{
"id": "8426923e-0d64-480d-925f-90324c2dedf5",
"name": "Public",
"status": "active",
"startDate": "2026-03-30T16:02:00.000Z",
"endDate": null,
"priceDisplay": {
"kind": "amount",
"amount": 1,
"currency": "USD",
"isFree": false
},
"bogo": null,
"isGated": false,
"maxPerWallet": 100,
"maxPerTransaction": 10,
"phaseSupply": null,
"msUntilStart": null,
"msUntilEnd": null
}
],
"upcoming": []
},
"capabilities": {
"requiresFeatures": [
"claim_codes",
"nft_selection"
],
"supportedBySurface": false,
"mintUrl": "https://gravemint.io/mint/7zn5qa"
},
"serverTime": "2026-08-31T12:17:45.816Z"
}Price is a shape, not a number
priceDisplay is the resolved display price. Use prepare when the collector is ready to mint to obtain the final wallet-specific breakdown, including fees and benefits.
kind | meaning | render |
|---|---|---|
amount | a settled figure | the number and its currency |
range | varies within the phase | "from X" |
hidden | the creator chose to hide it until eligible | do not guess — say it is hidden |
unknown | no display price available for this request | do not render 0 |
Show “Free” only when kind is amount and isFree is true. Keep hidden and unknown prices distinct from zero.
Eligibility
Server-side verdict for one wallet against one phase. Gating criteria stay on our side; you receive the decision, never the allowlist.
GET /v1/collections/:collectionId/eligibility/:phaseId/:wallet
import { GraveMintClient } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
const eligibility = await gm.v1.eligibility("7zn5qa", "8426923e-0d64-480d-925f-90324c2dedf5", "11111111111111111111111111111111");
console.log(eligibility);import { GraveMintClient, GraveMintError, type V1Eligibility } from "@solanadeads/gravemint";
const gm = new GraveMintClient({ apiKey: "gm_pub_your_key" });
try {
const eligibility: V1Eligibility = await gm.v1.eligibility("7zn5qa", "8426923e-0d64-480d-925f-90324c2dedf5", "11111111111111111111111111111111");
console.log(eligibility);
} catch (err) {
// `code` is stable — branch on it. `message` is a sentence you can show a user.
if (err instanceof GraveMintError) console.error(err.code, err.message);
else throw err;
}curl -s \
-H 'X-API-Key: gm_pub_your_key' \
'https://api.solanadeads.com/gravemint/v1/collections/7zn5qa/eligibility/8426923e-0d64-480d-925f-90324c2dedf5/11111111111111111111111111111111'{
"success": true,
"gated": false,
"phase": {
"id": "8426923e-0d64-480d-925f-90324c2dedf5",
"name": "Public",
"startDate": "2026-03-30T16:02:00+00:00",
"endDate": null,
"hasStarted": true,
"hasEnded": false
},
"address": "11111111111111111111111111111111",
"message": "This phase is open to everyone — no allowlist or holder requirements."
}Errors
Coded, and the code is the part you branch on. The human sentence may be reworded at any time; the code will not.
No credential at all
No Origin, no key. With the SDK this arrives as a thrown GraveMintError whose code is API_KEY_REQUIRED.
curl -s \
'https://api.solanadeads.com/gravemint/v1/collections/7zn5qa'{
"success": false,
"error": "This request could not be authorised.",
"code": "API_KEY_REQUIRED"
}An origin we do not recognise
Register the requesting origin for the key. This response is distinct from a missing credential. With the SDK this arrives as a thrown GraveMintError whose code is ORIGIN_NOT_ALLOWED.
curl -s \
-H 'Origin: https://partner.example' \
'https://api.solanadeads.com/gravemint/v1/collections/7zn5qa'{
"success": false,
"error": "This request could not be authorised.",
"code": "ORIGIN_NOT_ALLOWED"
}| code | status | meaning |
|---|---|---|
API_KEY_REQUIRED | 401 | no key and no recognised origin |
API_KEY_INVALID | 401 | the key did not match a live record |
ORIGIN_NOT_ALLOWED | 403 | the origin is not on this key |
COLLECTION_NOT_IN_SCOPE | 403 | this key is not issued for that drop |
AUTH_UNAVAILABLE | 503 | we could not check — retry; never treat as denial |
CLIENT_BROADCAST_NOT_ALLOWED | 400 | you sent a transaction hash. See below |
CHAIN_NOT_SUPPORTED_BY_SURFACE | 400 | v1 mints Solana only |
Transaction submission
prepare-mint returns transactions for your wallet to sign. Send the signed bytes to execute-mint; GraveMint validates and submits them. A client-submitted transaction hash returns CLIENT_BROADCAST_NOT_ALLOWED.
