API Reference
The complete MAGMA REST surface, grouped by resource. All paths are relative to:
https://api.magmaprotocol.xyz
Read the Overview for conventions, Authentication for the wallet-signed write model, and Errors for status codes. Method badges: GET POST PUT DELETE AUTH (credential or signature required).
Narratives
Prefix: /v1/narratives. The feed and lifecycle of narratives — read a single
narrative or the feed, validate, polish, prepare a backing transaction, publish,
and back an open market.
GET /v1/narratives/:id returns the object wrapped under a narrative key. Always
unwrap it (const n = data.narrative ?? data). GET /v1/narratives/:id/rules
likewise wraps under rules. A narrative score of exactly 0 means scoring is
pending — render it as a placeholder, not a real 0. See
Conventions.
Get feed
GET /v1/narratives/
| Query param | Type | Description |
|---|---|---|
filter | string | all | new | trending | backed. Default all. |
category | string | One of the 24 category enums (see below). Optional. |
sub_category | string | Sub-category filter. Optional. |
asset_tag | string | Asset tag filter. Optional. |
duration | string | Duration / deadline-tag filter. Optional. |
sort | string | Sort order. Optional. |
wallet | string | Required when filter=backed. |
limit | integer | 1–100 for the public feed; the broad listing accepts a large cap (up to 5000). Default 20. |
Categories (24): MARKET, ECOSYSTEM, SPORTS, ESPORTS, SOCIAL,
CULTURAL, LEGAL, POLITICAL, SCIENTIFIC, GEOPOLITICAL, CONVICTION,
ECONOMICS, TECHNOLOGY, HEALTH, CLIMATE, BUSINESS, ONCHAIN, SATIRE,
BUILDER, CAST, COMMODITIES, MACRO, EQUITIES, FOREX. See
Narrative categories for the full taxonomy.
curl 'https://api.magmaprotocol.xyz/v1/narratives/?filter=trending&limit=20'
{
"narratives": [
{
"id": "0b3f…",
"wallet_address": "7xKX…9fПb",
"title": "BTC above $120k by Q3 2026",
"thesis": "Will Bitcoin close above $120,000 on any day before September 30 2026 per CoinGecko?",
"status": "active",
"score": 72,
"sol_backed": 4.2,
"backers": 8,
"deadline_at": "2026-07-08T00:00:00Z",
"deadline_tag": "LONG",
"category": "MARKET",
"narrative_type": "MARKET",
"is_protocol_narrative": true,
"protocol_narrative_label": "MAGMA Protocol",
"uncertainty_score": 65,
"created_at": "2026-04-06T12:00:00Z"
}
]
}
Get single narrative
GET /v1/narratives/:id
Returns the narrative wrapped under a narrative key — you must unwrap it
(const n = data.narrative ?? data). A pre-market narrative carries
is_pre_market: true and an opens_at timestamp; gate backing on it (see
Back a narrative).
{ "narrative": { "id": "0b3f…", "title": "…", "score": 72, "is_pre_market": false, "opens_at": null } }
Get hero narratives
GET /v1/narratives/hero
Curated hero/featured narratives for the landing surface.
{ "narratives": [ { "id": "0b3f…", "title": "…" } ] }
Filter counts
GET /v1/narratives/filter-counts
Aggregate counts used to drive filter chips and a live "active markets" badge.
{
"total_active": 312,
"categories": { "MARKET": 88, "ECOSYSTEM": 41 },
"durations": { "SHORT": 120, "LONG": 192 },
"sub_categories": { "BTC": 30 }
}
Score history
GET /v1/narratives/:id/score-history
Time series of the narrative's score for charting.
Market history
GET /v1/narratives/:id/market-history
Market-event time series (volume/backing points). Returns a note of
market_event_unavailable with an empty points array when no events exist yet.
{ "points": [], "note": "market_event_unavailable" }
Rules
GET /v1/narratives/:id/rules
Resolution rules for the narrative, wrapped under a rules key. Returns 404
when the narrative has no rules attached.
{ "rules": { "resolution_source": "CoinGecko", "criteria": "…" } }
Generate (AI)
POST
AUTH /v1/narratives/generate
Kicks off async AI narrative generation and returns a jobId. Poll
GET /v1/narratives/generate/status/:jobId
for completion.
Check originality
POST /v1/narratives/check-originality
Scores a thesis for novelty before submission.
{ "thesis": "Will Bitcoin reach $200k before end of 2026?" }
{
"ok": true,
"similarity": 12,
"score": 74,
"suggested_category": "MARKET",
"message": "Your thesis appears original."
}
Polish text (AI)
POST
AUTH /v1/narratives/polish-text
Rewrites a rough thesis into a crisp, resolvable question. Rate-limited to 3 per wallet per day (rate limits); responds in the input's language.
{ "thesis": "bitcoin will hit 200k", "wallet_address": "7xKX…9fПb" }
{
"ok": true,
"polished": "Will Bitcoin reach $200,000 before December 31 2026 per CoinGecko?",
"original": "bitcoin will hit 200k"
}
Polish voice
POST
AUTH /v1/narratives/polish-voice
Transcribes/cleans a spoken thesis. Shares the daily polish pool (3/day).
{ "transcript": "um so i think bitcoin will like hit two hundred k before the year ends", "wallet_address": "7xKX…9fПb" }
{ "ok": true, "polished": "Will Bitcoin reach $200,000 before December 31 2026 per CoinGecko?" }
Prepare mint (build backing transaction)
POST
AUTH /v1/narratives/prepare-mint
Builds the unsigned backing transaction. Sign + send it, then call publish.
| Body field | Type | Description |
|---|---|---|
backer_wallet | string | Backer's wallet address. |
amount_lamports | integer | Backing amount in lamports. |
deadline_days | integer | Narrative resolution window in days. |
narrative_id | string | Target narrative UUID. |
{ "transaction": "AqwF…base64-unsigned-tx…", "narrativeId": "0b3f…", "deadlineTimestamp": 1789200000 }
Publish narrative
POST
AUTH /v1/narratives/publish
Submits the signed transaction and records the narrative on devnet. Publishing is gated
by an anti-spam publish fee of ~5 SOL (NARRATIVE_PUBLISH_FEE_SOL; ~80% becomes the
creator's own locked backing stake, ~20% treasury — see
YBNCM → publish fee) plus a Cloudflare Turnstile check.
| Body field | Type | Description |
|---|---|---|
walletAddress | string | Creator wallet. |
thesis | string | The resolvable question. |
category | string | Category enum. |
deadline_days | integer | Resolution window. |
signature | string | Transaction signature from the signed prepare-mint tx (pays the publish fee). |
cf_token | string | Cloudflare Turnstile token (required). |
{ "success": true, "narrativeId": "0b3f …", "message": "Narrative published to Solana Devnet" }
Common errors: 400 TURNSTILE_FAILED, 403 conviction_score_required,
422 narrative_too_obvious, 422 content_flagged, 429 daily_limit_reached.
Back a narrative
POST
AUTH /v1/narratives/:id/back
Backs an open market on one side. side selects the YES ('true') or NO
('false') outcome.
| Body field | Type | Description |
|---|---|---|
amount_sol | number | Backing amount in SOL (minimum 0.01). |
token_type | string | Backing token, e.g. SOL. |
side | string | 'true' (YES) | 'false' (NO). |
{ "amount_sol": 1.5, "token_type": "SOL", "side": "true" }
When the narrative is still pre-market (is_pre_market: true), backing is
rejected with 403:
{ "error": "market_not_open", "opens_at": "2026-07-01T00:00:00Z" }
Gate your UI on is_pre_market and surface opens_at rather than prompting a
signature that will be refused. See Conventions.
Narrative Groups
Prefix: /v1/narrative-groups. Grouped markets (a parent narrative with member
narratives) carrying live volume and backer aggregates.
List groups
GET /v1/narrative-groups
| Query param | Type | Description |
|---|---|---|
featured | boolean | Only featured groups. Optional. |
limit | integer | Page size. Optional. |
min_volume | number | Minimum total volume (USD) filter. Optional. |
min_backers | integer | Minimum total backers filter. Optional. |
total_volume_usd and total_backers are live aggregates. Member narratives
carry is_pre_market, opens_at, and pre_market_source so you can render the
pre-market gate per member.
{
"groups": [
{
"id": "g1a2…",
"title": "2026 Macro",
"total_volume_usd": 18420.0,
"total_backers": 64,
"narratives": [
{ "id": "0b3f…", "title": "…", "is_pre_market": true, "opens_at": "2026-07-01T00:00:00Z", "pre_market_source": "admin" }
]
}
]
}
Get group
GET /v1/narrative-groups/:id
Returns the group wrapped under a group key (with its narratives array).
Unwrap it (const g = data.group ?? data). See
Conventions.
{ "group": { "id": "g1a2…", "title": "2026 Macro", "narratives": [ /* … */ ] } }
Conviction
Prefix: /v1/conviction. A wallet's Conviction Score, tier, multipliers, fees,
streaks, and echo-pool preview. Tiers, low → high: ember → flare → magma → core
→ volcanic.
Get conviction profile
GET /v1/conviction/:wallet
curl 'https://api.magmaprotocol.xyz/v1/conviction/<wallet>'
{
"conviction_score": 420,
"conviction_tier": "magma",
"correct_backings": 42,
"incorrect_backings": 8,
"accuracy_rate": 84.0,
"current_streak": 5,
"longest_streak": 12,
"conviction_multiplier": 1.6,
"streak_multiplier": 1.1,
"combined_multiplier": 1.76,
"fee_pct": 1.5,
"terms_accepted": true,
"terms_version": "0.1",
"terms_accepted_at": "2026-04-01T10:00:00Z",
"per_category_stats": {
"MARKET": { "backed": 30, "correct": 26, "accuracy": 87 }
}
}
An unseen wallet returns a zeroed profile (conviction_tier: "ember",
multipliers 1.0, fee_pct: 2.0) rather than a 404.
Echo-pool preview
GET /v1/conviction/echo-pool/preview/:wallet
Estimated Echo Pool distribution for the wallet at the current epoch.
Echo-pool history
GET /v1/conviction/echo-pool/history/:wallet
Last 12 epochs of Echo Pool distributions for the wallet.
Creator profile
GET /v1/conviction/creator/:wallet
Creator score, tier, share percentage, and narrative counts.
{
"creator_score": 180,
"creator_tier": "flare",
"creator_share_pct": 5,
"total_creator_earnings_sol": 1.23,
"narratives_submitted": 14,
"narratives_resolved_true": 9,
"narratives_pending": 3
}
Epoch (Echo Pool)
GET /v1/conviction/epoch/current
The current Echo Pool epoch — number, window, time remaining, accumulated SOL, and per-pool breakdown.
{
"ok": true,
"epoch_number": 7,
"start_date": "2026-04-01T00:00:00Z",
"end_date": "2026-04-15T00:00:00Z",
"days_remaining": 5,
"total_accumulated_sol": 128.4,
"pools": { "conviction": 64.2, "creator": 32.1 }
}
GET /v1/conviction/epoch/history ·
GET /v1/conviction/epoch/preview/:wallet
Past epochs, and a per-wallet projection for the current epoch.
Eruption
GET /v1/conviction/eruption/:wallet
A wallet's Eruption (streak/burst) state.
Leaderboards
GET /v1/conviction/leaderboard/conviction ·
GET /v1/conviction/leaderboard/creators
Top wallets by conviction score and by creator score, respectively. Both accept
?limit= (default 50) and ?offset= for paging.
Missions
Prefix: /v1/missions. Per-wallet missions, completion checks, and a missions
leaderboard.
Get missions
GET /v1/missions/:wallet
The wallet's missions, typically grouped by category, with progress and completion state.
Check completion
POST /v1/missions/check/:wallet
Re-evaluates the wallet's missions and marks any newly satisfied ones complete.
Leaderboard
GET /v1/missions/leaderboard
| Query param | Type | Description |
|---|---|---|
sort | string | missions_completed | conviction_score | epoch_performance. |
limit | integer | Page size. Default 50. |
DeFi
Prefix: /v1/defi. Read protocol APYs and route principal into yield. The current
DeFi integration set is Kamino, Save, Jito, Marinade, Jupiter (Lend), Meteora,
Guardian, and Project 0 (P0).
Kamino and Save have devnet markets, so their deposits build and submit real
devnet transactions. Jito, Marinade, Jupiter Lend, Meteora, Guardian, and P0 are
mainnet-targeted: their endpoints return 503 coming_soon (or 503 p0_disabled)
until wired. Each protocol's status is reported in the protocols map of
GET /v1/defi/apys via testnet_available.
Get protocol APYs
GET /v1/defi/apys
Latest APYs (Redis-cached, falling back to defaults) plus per-protocol metadata.
curl 'https://api.magmaprotocol.xyz/v1/defi/apys'
{
"ok": true,
"source": "redis",
"polled_at": "2026-04-09T12:00:00Z",
"apys": {
"kamino": 9.2, "kamino_sol": 7.2, "kamino_usdc": 5.8,
"save": 7.1, "jito": 7.8, "marinade": 7.2,
"meteora": 18.4, "jupiter_lend": 4.8, "p0": 8.5
},
"protocols": {
"kamino": { "label": "Kamino Lend", "token": "SOL/USDC", "testnet_available": true, "coming_at": null },
"save": { "label": "Save Finance", "token": "SOL/USDC", "testnet_available": true, "coming_at": null },
"jito": { "label": "Jito Staking", "token": "SOL", "testnet_available": false, "coming_at": "mainnet" },
"marinade": { "label": "Marinade", "token": "SOL", "testnet_available": false, "coming_at": "mainnet" },
"p0": { "label": "Project 0", "token": "Multi", "testnet_available": false, "coming_at": "mainnet" }
},
"borrow_enabled": false
}
Generic deposit (prepare / confirm)
The protocol-agnostic flow auto-routes by token and returns an unsigned tx for client signing. Supports kamino, save, jupiter_lend, marinade, jito.
POST
AUTH /v1/defi/deposit/prepare
| Body field | Type | Description |
|---|---|---|
wallet | string | Depositor wallet. |
token_symbol | string | e.g. SOL, USDC. Drives auto-routing. |
amount | number | UI amount. Minimum 0.01 SOL. |
protocol | string | Optional explicit protocol override. |
narrative_id | string | Optional; direct for a standalone earn deposit. |
{
"ok": true,
"transaction": "AqwF…base64-unsigned-tx…",
"blockhash": "9xQe…",
"backing_id": "c1a2…",
"protocol": "kamino",
"amount_sol": 1.5,
"token_symbol": "SOL"
}
POST
AUTH /v1/defi/deposit/confirm
Verifies the signed tx on-chain and marks the backing confirmed.
Body: { backing_id, tx_signature, wallet }.
{ "ok": true, "backing_id": "c1a2…", "tx_signature": "5Hb…", "amount_sol": 1.5, "protocol": "kamino" }
Generic withdrawal (prepare / confirm)
POST
AUTH /v1/defi/withdrawal/prepare ·
POST
AUTH /v1/defi/withdrawal/confirm
Mirror of deposit. Body for prepare: { backing_id, wallet }; for confirm:
{ backing_id, tx_signature, wallet }. Supports kamino, save, jupiter_lend,
marinade. Jito liquid unstaking is not supported — swap jitoSOL on Jupiter
instead (503 jito_unstake_not_supported).
Per-protocol deposit endpoints
These build a protocol-specific transaction directly.
| Endpoint | Method | Body | Notes |
|---|---|---|---|
/v1/defi/kamino/deposit | POST | { wallet_address, amount_sol, narrative_id? } | Returns a receipt. Devnet-live. |
/v1/defi/kamino/withdraw | POST | { wallet_address, amount_sol, narrative_id, receipt } | Returns yield_earned_sol. |
/v1/defi/save/deposit | POST | { wallet_address, symbol, amount_base } | Multi-tx, ready_to_sign. Devnet-live. |
/v1/defi/save/withdraw | POST | { wallet_address, symbol, amount_base } | Multi-tx, ready_to_sign. |
/v1/defi/jito/deposit | POST | { wallet_address, amount_sol } | Returns jitosol_account. Mainnet. |
/v1/defi/marinade/deposit | POST | { wallet_address, amount_sol } | Returns msol_account. Mainnet. |
/v1/defi/marinade/withdraw | POST | { wallet_address, amount_sol } | Unstake. Mainnet. |
/v1/defi/jupiter-lend/deposit | POST | { wallet_address, symbol, amount_raw } | Versioned tx. Mainnet. |
/v1/defi/jupiter-lend/withdraw | POST | { wallet_address, symbol, amount_raw } | Mainnet. |
/v1/defi/meteora/deposit | POST | — | 503 coming_soon (pool config pending). |
curl -X POST 'https://api.magmaprotocol.xyz/v1/defi/jito/deposit' \
-H 'Content-Type: application/json' \
-d '{ "wallet_address": "7xKX…9fПb", "amount_sol": 2.0 }'
{ "ok": true, "protocol": "jito", "jitosol_account": "…", "status": "ready_to_sign" }
Project 0 (P0)
P0 is a unified-margin integration gated at Core tier (600+ Conviction Score)
for account/strategy reads, and behind a p0_enabled config flag for deposits.
| Endpoint | Method | Purpose |
|---|---|---|
/v1/defi/p0/deposit | POST AUTH | Build deposit tx(s). Body: { wallet_address, asset_mint, amount_ui, narrative_id? }. |
/v1/defi/p0/deposit/confirm | POST AUTH | Record confirmed deposit. |
/v1/defi/p0/withdraw | POST AUTH | Build withdraw tx(s). Body: { wallet_address, asset_mint, amount_ui?, withdraw_all? }. |
/v1/defi/p0/withdraw/confirm | POST AUTH | Close position. Body: { wallet_address, position_id }. |
/v1/defi/p0/health/:wallet | GET | Account health for a wallet. |
/v1/defi/p0/positions/:wallet | GET | Open P0 positions. |
/v1/defi/p0/account/:wallet | GET | Account summary. Core tier gated. |
/v1/defi/p0/strategies | GET | Available strategies (?wallet= gates at Core). |
{
"ok": true,
"protocol": "p0",
"account_address": "Hk9…",
"needs_account_creation": false,
"transactions": 2,
"status": "ready_to_sign",
"note": "Sign all transactions with MWA in order. Call /v1/defi/p0/deposit/confirm after signing."
}
When P0 is off: 503 { "error": "p0_disabled", "message": "Project Zero integration coming soon." }.
Allocation & yield
GET /v1/defi/allocation/:wallet
Active DeFi positions for a wallet, with per-position backing_id, protocol,
amount, percentage split, and can_withdraw.
{
"ok": true,
"wallet": "7xKX…9fПb",
"positions": [
{ "backing_id": "c1a2…", "protocol": "kamino", "token_symbol": "SOL", "amount_sol": 1.5, "yield_earned_sol": 0.012, "status": "confirmed", "can_withdraw": true }
],
"allocation": [ { "protocol": "kamino", "amount_sol": 1.5, "percentage": 100.0, "backing_id": "c1a2…" } ],
"total_sol": 1.5,
"empty": false
}
GET /v1/defi/yield/:wallet
Total yield earned across all DeFi positions plus an echo-pool breakdown.
{
"ok": true,
"wallet": "7xKX…9fПb",
"yield_earned_sol": 0.054,
"breakdown": { "narrative_yield_sol": 0.012, "echo_pool_sol": 0.042 }
}
Staking
Prefix: /v1/staking. A wallet's MAGMA staking position and tier.
MAGMA staking is currently in testing on devnet — the staking deposit flow is gated
off (coming_soon) until mainnet. The read below still returns the wallet's
position shape.
Get staking position
GET /v1/staking/:wallet
{
"wallet_address": "7xKX…9fПb",
"staked_amount": 0,
"tier": "ember",
"positions": []
}
Borrow
Prefix: /v1/borrow. Borrow against lending positions through Kamino and Save,
with LTV scaled by Conviction tier. Opening a position requires accepting borrow
terms; on devnet, borrow_enabled may be off (503 borrow_disabled).
Get borrow rates
GET /v1/borrow/rates
Current borrow APRs for Kamino and Save (60s cache), with the MAGMA spread applied (50 bps).
{
"ok": true,
"source": "redis",
"rates": {
"kamino": { "base": { "sol": 3.2, "usdc": 5.1 }, "with_spread": { "sol": 3.7, "usdc": 5.6 }, "magma_spread_bps": 50 },
"save": { "base": { "sol": 2.9, "usdc": 4.8 }, "with_spread": { "sol": 3.4, "usdc": 5.3 }, "magma_spread_bps": 50 },
"polled_at": "2026-04-09T12:00:00Z"
}
}
Get capacity
GET /v1/borrow/capacity/:wallet
Borrowing power from the wallet's tier and open positions.
{ "ok": true, "wallet": "7xKX…9fПb", "conviction_tier": "Magma", "max_ltv": 0.65, "total_borrowed_usd": 120.50, "open_positions": 1 }
Simulate borrow
GET /v1/borrow/simulate
| Query param | Type | Description |
|---|---|---|
wallet | string | Borrower wallet. |
protocol | string | kamino | save. |
asset | string | Borrow asset symbol, e.g. USDC. |
amount_usd | number | Requested borrow size in USD. |
{
"ok": true,
"simulation": {
"borrow_amount_usd": 500,
"max_ltv": 0.65,
"collateral_required_usd": 769.23,
"estimated_health_factor": 1.308,
"warning": null
}
}
Prepare / confirm borrow
POST
AUTH /v1/borrow/prepare
Validates capacity and returns borrow params for confirmation. Requires
borrow_terms_accepted = true (403 terms_not_accepted otherwise) and
borrow_enabled (503 borrow_disabled otherwise).
| Body field | Type | Description |
|---|---|---|
wallet | string | Borrower wallet. |
protocol | string | kamino | save. |
borrow_asset | string | Asset symbol. |
borrow_asset_mint | string | Asset mint (optional). |
amount_usd | number | Borrow size in USD. |
{
"ok": true,
"borrow_id": "b71f…",
"max_ltv": 0.65,
"borrow_apy": 5.1,
"collateral_required_usd": 769.23,
"estimated_health_factor": 1.308,
"status": "ready_to_confirm"
}
POST
AUTH /v1/borrow/confirm
Records the opened position.
{ "wallet": "7xKX…", "protocol": "kamino", "borrow_asset": "USDC", "amount_usd": 500, "borrow_apy": 5.1, "max_ltv_tier": "magma" }
Repay
POST
AUTH /v1/borrow/repay/prepare ·
POST
AUTH /v1/borrow/repay/confirm
Prepare returns principal + accrued interest + total repay for a position_id;
confirm closes the position. Body: { wallet, position_id }.
Health & positions
GET /v1/borrow/health/:wallet ·
GET /v1/borrow/positions/:wallet
Health factors and full details for all open borrow positions.
Accept borrow terms
POST /v1/borrow/accept-terms
{ "wallet": "7xKX…9fПb" }
Fast action
POST
AUTH /v1/borrow/fast-action
One-tap preset borrow. Requires Flare tier (100+ score) (403 flare_required
otherwise).
| Body field | Type | Description |
|---|---|---|
wallet | string | Borrower wallet. |
action | string | safe (30% of max LTV) | balanced (50%) | max (100%) | instant_sol (40%). |
protocol | string | Optional, default kamino. |
borrow_asset | string | Optional, default USDC. |
{ "ok": true, "action": "safe", "max_ltv": 0.65, "effective_ltv": 0.195, "ltv_pct_of_max": 0.3, "status": "ready_to_confirm" }
Verify
Prefix: /v1/verify. Identity verification across chains. Supported methods for
Solana wallets: Civic, Gitcoin (Passport), and SAS (Solana Attestation
Service). EVM wallets fall back to Gitcoin (+ Human Protocol, coming soon).
Get verification status
GET /v1/verify/status/:wallet
Detects the chain from the address and returns per-method state.
{
"ok": true,
"wallet": "7xKX…9fПb",
"chain": "solana",
"available_methods": ["civic", "gitcoin", "sas"],
"verification": {
"civic_verified": true,
"gitcoin_score": 24,
"gitcoin_verified": true,
"sas_verified": false
},
"fully_verified": true,
"recommended_method": "civic"
}
gitcoin_verified is true at score ≥ 10; the Passport check endpoint enforces a
passing threshold of 20.
Initiate verification
POST /v1/verify/initiate
Returns the flow config (provider URL, callback, type) for the chosen or chain-default method.
{ "wallet": "7xKX…9fПb", "preferred_method": "civic" }
{
"ok": true,
"chain": "solana",
"flow": {
"method": "civic",
"url": "https://getpass.civic.com",
"callback": "/v1/verify/civic",
"type": "oauth",
"description": "Civic Pass — biometric identity verification for Solana wallets"
}
}
Method endpoints
| Endpoint | Method | Body / params | Purpose |
|---|---|---|---|
/v1/verify/civic | POST | { token, wallet_address } | Validate a Civic Pass token. |
/v1/verify/passport/:wallet | GET | path wallet | Check Gitcoin Passport score (threshold 20). |
/v1/verify/sas | POST | { wallet_address, attestation_id? } | SAS attestation (records intent; coming_soon). |
/v1/verify/sas/attestations/:wallet | GET | path wallet | List SAS on-chain attestations. |
/v1/verify/confirm | POST | { wallet_address, method, verification_id?, chain? } | Provider callback writer. method ∈ civic | gitcoin | sas. |
/v1/verify/skr/:wallet | GET | path wallet | Verify SKR balance + 45-day hold; unlocks Echo Pool ticket boost & deposit-fee reduction. |
// GET /v1/verify/passport/<wallet>
{ "ok": true, "verified": true, "score": 24, "wallet_address": "7xKX…9fПb" }
KYC
Prefix: /v1/kyc. Persona-backed identity verification, KYC status / tier, and
wallet (OFAC) screening.
KYC currently runs against Persona in sandbox mode (template
itmpl_6gvRNu9U3r5NokYRF3XhXb2X7whj) ahead of mainnet. Treat verifications as
test-only until production is enabled.
Start verification
POST /v1/kyc/start
Opens a Persona inquiry and returns a hosted kyc_url to redirect the user to. If
the wallet is already verified it returns { already_verified: true, kyc_tier }.
| Body field | Type | Description |
|---|---|---|
wallet | string | Wallet to verify. |
tier | integer | Requested KYC tier 1 | 2. Optional. |
{ "inquiry_id": "inq_…", "session_token": "…", "kyc_url": "https://withpersona.com/verify?inquiry-id=inq_…" }
Get KYC status
GET /v1/kyc/status/:wallet
{
"wallet_address": "7xKX…9fПb",
"kyc_tier": 1,
"kyc_status": "approved",
"ofac_screened": true,
"kyc_completed_at": "2026-04-10T12:00:00Z",
"tier_limits_usd": { "daily": 1000, "monthly": 10000 }
}
kyc_tier is 0–4. kyc_status is one of: none, pending, approved,
declined, needs_review, expired, erased, watchlist_flagged.
Screen wallet
POST /v1/kyc/screen-wallet
Runs a blockchain-address (OFAC) screen, typically called after KYC completes.
| Body field | Type | Description |
|---|---|---|
wallet | string | MAGMA wallet. |
blockchain_address | string | Address to screen. |
{ "cleared": true, "status": "clear", "blockchain_address": "7xKX…9fПb" }
The flow is: POST /v1/kyc/start → redirect to kyc_url → GET /v1/kyc/status/:wallet
→ POST /v1/kyc/screen-wallet.
NEAR Intents
Prefix: /v1/intents. Cross-chain swaps routed through NEAR Intents. The asset
catalog covers ~156 tokens (cached ~1 hour).
Tokens have no icon field — resolve icons client-side (e.g. a CoinGecko map).
originAsset / destinationAsset must be the token assetId, not its symbol,
and amount / amountIn are strings, not numbers.
List tokens
GET /v1/intents/tokens
{
"tokens": [
{ "assetId": "nep141:…", "symbol": "SOL", "blockchain": "solana", "decimals": 9, "contractAddress": null, "price": 152.3 }
]
}
Quote
POST
AUTH /v1/intents/quote
| Body field | Type | Description |
|---|---|---|
originAsset | string | Source token assetId. |
destinationAsset | string | Destination token assetId. |
amount | string | Input amount as a string. |
recipient | string | Destination-chain address (see below). |
refundTo | string | Refund address — always the origin (Solana) wallet. |
walletAddress | string | The user's wallet. |
recipient must match the destination chain's address format: a Solana base58
address for solana (auto-filled from the wallet), a NEAR account ID (e.g.
alice.near) for near, or an EVM 0x… address for eth / base / arbitrum.
Confirm
POST
AUTH /v1/intents/confirm
Returns the depositAddress to send funds to.
| Body field | Type | Description |
|---|---|---|
depositAddress | string | Deposit address from the quote. |
walletAddress | string | The user's wallet. |
originAsset / destinationAsset | string | Token assetIds. |
originChain / destinationChain | string | Source / destination blockchains. |
amountIn | string | Input amount as a string. |
txHash | string | Optional source-chain tx hash. |
Status & history
GET /v1/intents/status/:depositAddress ·
GET /v1/intents/history/:wallet
Status terminal states are SUCCESS, REFUNDED, and FAILED — stop polling on
is_terminal: true.
{ "status": "SUCCESS", "is_terminal": true }
SideShift
Prefix: /v1/sideshift. A thin proxy over SideShift for cross-chain swaps, gated
by a configured affiliate ID.
SideShift currently returns ACCESS_DENIED because the upstream provider has
blocked the server's region. The endpoints below are wired and resume working once
the affiliate access is restored.
List coins
GET /v1/sideshift/coins
The full supported-coin list (no icon field — resolve icons client-side).
{ "ok": true, "coins": [ { "coin": "BTC", "name": "Bitcoin", "networks": ["bitcoin"], "hasMemo": false } ] }
Quote
POST /v1/sideshift/quote
Body: { fromCoin, toCoin, fromAmount }.
Shift & status
POST /v1/sideshift/shift ·
GET /v1/sideshift/shift/:id
Create a shift and poll it. Terminal statuses: settled, complete, failed,
refunded, expired.
TRON / Wormhole
Prefix: /v1/tron. TRON bridge configuration and Wormhole VAA status, used for the
USDT-TRC20 bridge path via Wormhole.
The TRON LockVault is not deployed yet: GET /v1/tron/config returns
vault_deployed: false and status: 'coming_soon'. Gate any TRON UI on
vault_deployed: true.
Get config
GET /v1/tron/config
{ "ok": true, "vault_deployed": false, "chain_id_wormhole": 9, "status": "coming_soon" }
VAA status
GET /v1/tron/vaa-status/:txHash
Wormhole VAA status for a TRON transaction. Poll on the returned interval (15s) and
stop when is_terminal: true.
{ "ok": true, "status": "pending", "is_terminal": false, "poll_again": true, "poll_interval_ms": 15000 }
status is one of pending, signed, or not_found.
Users
Prefix: /v1/users. Per-wallet profile, history, holdings, and aggregated
portfolio.
Transaction history
GET /v1/users/:wallet/transactions
| Query param | Type | Description |
|---|---|---|
type | string | backing | payout | creator_earn. Omit for all. |
limit | integer | Default 50, max 200. |
{
"ok": true,
"wallet": "7xKX…9fПb",
"transactions": [
{
"id": "c1a2…",
"type": "backing",
"amount_sol": 2.5,
"token_type": "SOL",
"yield_earned": 0.042,
"narrative": { "id": "0b3f…", "title": "…", "status": "graduated" },
"created_at": "2026-04-01T10:00:00Z",
"status": "confirmed"
}
],
"echo_pool_epochs": []
}
Other user endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/v1/users/:wallet/profile | GET | Public profile (username, tier, accuracy). |
/v1/users/:wallet/profile | PUT | Update profile (username uniqueness + NFT-ownership checks). |
/v1/users/:wallet/balance | GET | Scores, totals, active positions, whitelist flag. |
/v1/users/:wallet/backings | GET | Paginated backings (?page=, ?status=) with total. |
/v1/users/:wallet/backed | GET | All backed narratives + total_backed_sol. |
/v1/users/:wallet/payouts | GET | Payout history + total_earned. |
/v1/users/:wallet/narratives | GET | Narratives created by the wallet. |
/v1/users/:wallet/nfts | GET | Tier NFTs held by the wallet. |
/v1/users/:wallet/activity | GET | Unified activity feed for the wallet. |
/v1/users/:wallet/portfolio | GET | Full aggregation: conviction, ruffler, staking, yield pools. |
/v1/users/:wallet/yield-summary | GET | Total yield earned (total_yield_earned_sol, total_yield_earned_usd, by_narrative). Never 404 — returns zeroes when no yield. |
/v1/users/:wallet/creator-royalties | GET | Creator royalty history (total_royalties_sol, count, royalties). ?limit= (max 200, default 50). |
/v1/users/path-choice | POST | Onboarding path. |
/v1/users/verify-holdings | POST | Re-check SKR holding (24h cache). Body { wallet }. |
/v1/users/push-token | POST | Register a push token. |
Path choice
POST /v1/users/path-choice
{ "wallet_address": "7xKX…9fПb", "path_choice": "creator" }
Canonical paths: creator | backer | yield_farmer | explorer. Legacy
aliases predictor → backer, defi → yield_farmer, observer → explorer are
accepted.
SAS Attestations
Prefix: /v1/verify/sas. Solana Attestation Service (SAS) tier badges for a
wallet — read the on-chain attestations that back a wallet's KYC, conviction, and
creator status.
SAS attestations are registered on devnet; mainnet registration is pending before launch.
Get attestations
GET /v1/verify/sas/attestations/:wallet
{
"ok": true,
"wallet": "7xKX…9fПb",
"attestations": { "kyc_tier": 1, "conviction_tier": "magma", "creator": true }
}
To record SAS attestation intent, see
POST /v1/verify/sas in Verify.
Notifications
Prefix: /v1/notifications. The in-app notification feed, read state, and Web Push
subscription.
The notifications system is under construction — endpoints are wired but the feed is still being populated end-to-end. For the push-subscription and webhook integration view (including the full list of notification types), see Webhooks.
Feed & read state
| Endpoint | Method | Purpose |
|---|---|---|
/v1/notifications/:wallet | GET | Notification feed. ?limit= (default 50), ?offset=, ?unread_only= (default false). |
/v1/notifications/:wallet/unread-count | GET | Unread badge count. |
/v1/notifications/:wallet/mark-read | POST | Mark specific notifications read. |
/v1/notifications/:wallet/mark-all-read | POST | Mark all read. |
/v1/notifications/:wallet/:notification_id | DELETE | Delete one notification. |
Web Push
| Endpoint | Method | Purpose |
|---|---|---|
/v1/notifications/push/vapid-public-key | GET | VAPID public key for the push subscription. |
/v1/notifications/push/subscribe | POST | Register a Web Push subscription. |
/v1/notifications/push/preferences/:wallet | GET | Read per-type push preferences. |
/v1/notifications/push/preferences/:wallet | PUT | Update per-type push preferences. |
See Webhooks for the subscription flow and the 19 notification types.
Terms
Prefix: /v1/terms. Record and check Terms of Service acceptance. The accepting
IP is hashed (SHA-256), never stored raw.
Accept terms
POST /v1/terms/accept
| Body field | Type | Description |
|---|---|---|
wallet_address | string | Accepting wallet. |
terms_version | string | Defaults to 0.1. |
source | string | e.g. mobile, web. Default web. |
platform | string | e.g. ios, android, website. |
app_version | string | Optional client version. |
{ "success": true, "terms_version": "0.1", "accepted_at": "2026-04-01T10:00:00Z" }
Get terms status
GET /v1/terms/status/:wallet
{ "accepted": true, "latest": { "terms_version": "0.1", "accepted_at": "2026-04-01T10:00:00Z", "platform": "ios" } }
Waitlist
Prefix: /v1/waitlist. Public beta waitlist. Signup is protected by Cloudflare
Turnstile.
Join
POST /v1/waitlist/join
| Body field | Type | Description |
|---|---|---|
cf_token | string | Cloudflare Turnstile token (required). |
wallet_address | string | Wallet (wallet or email required). |
email | string | Email. |
discord_handle, twitter_handle | string | Optional socials. |
has_seeker, holds_skr | boolean | Priority signals. |
referral_code | string | Optional referral. |
{ "success": true, "referral_code": "MGMA-7K2", "priority_score": 25 }
A duplicate signup returns { "success": true, "already_registered": true, … }.
Human verification failure returns 400 TURNSTILE_FAILED.
Stats
GET /v1/waitlist/stats
{ "total": 18342 }
NFT
Prefix: /v1/nft. Tier NFTs map a wallet to a Conviction tier. Collections:
MLAVA (Flare), MGNSS (Volcanic), MSPEC (Magma).
Verify ownership
POST /v1/nft/verify
Verifies on-chain ownership (Helius DAS), updates the wallet's tier.
{ "wallet_address": "7xKX…9fПb", "mint_address": "Mint…" }
{ "success": true, "wallet_address": "7xKX…9fПb", "mint_address": "Mint…", "tier": "flare", "conviction_multiplier": 1.25, "narrative_score": 0 }
Ownership that can't be verified returns 403.
Mint (prepare / confirm)
POST
AUTH /v1/nft/mint
Prepares a Metaplex Core mint. Body: { wallet_address, collection, recipient_wallet? }
where collection ∈ mlava | mgnss | mspec.
{
"ok": true,
"collection": "mlava",
"tier": "flare",
"recipient_wallet": "7xKX…9fПb",
"collection_address": "Coll…",
"metadata": { "name": "MAGMA MLAVA", "symbol": "MLAVA", "uri": "https://metadata.magmaprotocol.xyz/nft/mlava/metadata.json" },
"status": "ready_to_mint"
}
Errors: 503 collection_not_deployed, 409 already_minted.
POST
AUTH /v1/nft/mint/confirm
Records the confirmed mint and sets the wallet tier. Body:
{ wallet_address, mint_address, collection, tx_signature? }.
Read & webhooks
| Endpoint | Method | Purpose |
|---|---|---|
/v1/nft/wallet/:wallet | GET | Full NFT ownership state for a wallet. |
/v1/nft/score/:mintAddress | GET | Current narrative score for a mint (for marketplaces). |
/v1/nft/webhook/helius | POST | Helius webhook for transfer events. Requires x-webhook-secret. |
/v1/nft/webhook/transfer | POST | MLAVA/MGNSS transfer webhook. Requires x-webhook-secret. |
Shield
Prefix: /v1/shield. Shield is MAGMA's protocol-cover layer — back coverage on a
DeFi protocol and earn yield, with payouts on a verified FALSE (exploit)
resolution. It also exposes abuse-probe logging used by gated surfaces.
Read & participate
| Endpoint | Method | Purpose |
|---|---|---|
/v1/shield/protocols | GET | Covered protocols and current scores. |
/v1/shield/protocols/:id | GET | One protocol's detail. |
/v1/shield/protocols/:id/score-history | GET | Score history. |
/v1/shield/protocols/:id/oracle-verdicts | GET | Oracle verdicts. |
/v1/shield/protocols/:id/rules | GET | Coverage rules (also …/rules.pdf). |
/v1/shield/apys | GET | Shield coverage APYs. |
/v1/shield/leaderboard | GET | Coverage backer leaderboard. |
/v1/shield/back | POST AUTH | Back protocol coverage. |
/v1/shield/positions/:wallet | GET | A wallet's coverage positions. |
/v1/shield/build-claim-tx | POST AUTH | Build a claim transaction. |
/v1/shield/terms-ack | POST | Acknowledge Shield terms (…/terms-ack/:wallet to read). |
/v1/shield/partner-apply | POST | Apply as a partner protocol. |
/v1/shield/portal/access | GET | Partner portal access (?wallet=). |
Abuse-probe logging
POST /v1/shield/probe-log
Logs a suspicious access attempt (called client-side on gated pages).
{ "ip_hash": "sha256_hex", "path": "/shield", "method": "GATE_ATTEMPT", "user_agent": "Mozilla/5.0…" }
GET
AUTH /v1/shield/blocked — list blocked IP
hashes. Admin auth required.
DELETE
AUTH /v1/shield/blocked/:ip_hash — unblock
a flagged IP hash. Admin auth required.
Binary Markets
Prefix: /v1/binary. The YES/NO binary-markets REST surface is scaffolded and
gated — every /v1/binary/* route returns 503 (coming post-TGE).
The binary-markets concept ("back against narratives / the short side") is being
delivered on-chain first. GET /v1/binary/status returns
{ "feature": "coming_soon" }; integrate against the on-chain program until these
endpoints ship. Full program and SDK details are in
Binary Markets — Program & API.
POST /v1/markets (MAGMA-native binary-market creation, distinct from the gated
/v1/binary/* surface) now requires an anti-spam fee — BINARY_MARKET_FEE_SOL
(defaults to the ~5 SOL narrative publish fee) — paid via a verified treasury
fee-payment tx, alongside a Cloudflare Turnstile token (cf_token) and the creator's
signature. Previously this path was ungated. Reject codes: 400 TURNSTILE_FAILED,
400 market_fee_missing_treasury, 401 invalid_signature. See
Program & API → market creation.
System
Prefix: /v1/system. Operational status probe.
Get status
GET /v1/system/status
Reports overall API/operational status. Use it for liveness and a basic health signal.
curl 'https://api.magmaprotocol.xyz/v1/system/status'
See also
- Agents API — machine-readable feed and automation endpoints.
- Tiers — access tiers and elevated-access requests.
- TypeScript SDK — typed client over this reference.