Skip to main content

Authentication

MAGMA has three authentication models, applied per route class:

Route classAuth modelCredential
Public readsNone
Wallet-signed writes (money movement)Client-signed Solana transactionUser's wallet signature
Agent automationAPI keyx-api-key header
Admin / operationsHeader credentialsx-admin-wallet + x-admin-secret

There is no session, bearer token, or OAuth flow for end users. Identity for a state-changing action is proven on-chain: the user signs the exact transaction that moves their funds, and the backend verifies that signature landed.

Public reads

Most GET endpoints — the narrative feed, conviction profiles, DeFi APYs, borrow rates, verification status, leaderboards — require no credentials. They are rate-limited by IP (see Rate limits).

curl 'https://api.magmaprotocol.xyz/v1/conviction/<wallet>'

Wallet-signed writes

AUTH Any operation that moves SOL or opens an on-chain position uses a prepare → sign → confirm handshake. The server never holds your keys; it builds an unsigned transaction, you sign it with the user's wallet, you broadcast it, and you tell the server the resulting signature so it can verify on-chain before recording state.

The same two-step shape appears across the API under different names:

ResourceBuild stepSubmit step
DeFi depositPOST /v1/defi/deposit/preparePOST /v1/defi/deposit/confirm
DeFi withdrawalPOST /v1/defi/withdrawal/preparePOST /v1/defi/withdrawal/confirm
P0 depositPOST /v1/defi/p0/depositPOST /v1/defi/p0/deposit/confirm
Narrative backingPOST /v1/narratives/prepare-mintPOST /v1/narratives/publish
BorrowPOST /v1/borrow/preparePOST /v1/borrow/confirm
RepayPOST /v1/borrow/repay/preparePOST /v1/borrow/repay/confirm
NFT mintPOST /v1/nft/mintPOST /v1/nft/mint/confirm
Signing libraries

The unsigned transaction is a base64-encoded Solana transaction with the fee payer set to the user's wallet. Sign it with whatever wallet stack you use — Mobile Wallet Adapter (signAndSendTransactions), Privy, or @solana/wallet-adapter. Some flows (P0, Save) return multiple transactions that must be signed and sent in order; those responses include a transactions count and a status of ready_to_sign.

Worked example — back a narrative

# 1. Build the unsigned backing transaction
curl -X POST 'https://api.magmaprotocol.xyz/v1/narratives/prepare-mint' \
-H 'Content-Type: application/json' \
-d '{
"backer_wallet": "7xKX…9fПb",
"amount_lamports": 1000000000,
"deadline_days": 90,
"narrative_id": "0b3f…"
}'
{
"transaction": "AqwF…base64-unsigned-tx…",
"narrativeId": "0b3f…",
"deadlineTimestamp": 1789200000
}
// 2. Sign + send with the user's wallet (Mobile Wallet Adapter shown)
import { VersionedTransaction } from '@solana/web3.js';

const tx = VersionedTransaction.deserialize(
Buffer.from(prepared.transaction, 'base64'),
);
const [signature] = await wallet.signAndSendTransactions({ transactions: [tx] });
# 3. Submit the signature so MAGMA verifies + records the backing
curl -X POST 'https://api.magmaprotocol.xyz/v1/narratives/publish' \
-H 'Content-Type: application/json' \
-d '{
"walletAddress": "7xKX…9fПb",
"thesis": "Will Bitcoin close above $200,000 before December 31 2026 per CoinGecko?",
"category": "MARKET",
"deadline_days": 90,
"signature": "<signature-from-step-2>"
}'
{ "success": true, "narrativeId": "0b3f…", "message": "Narrative published to Solana Devnet" }
Gating on writes

A wallet-signed write can still be rejected by protocol policy before any signing occurs — for example 403 terms_not_accepted, 403 conviction_score_required, 403 flare_required, or 503 borrow_disabled / 503 p0_disabled. Check the relevant status endpoint (e.g. GET /v1/terms/status/:wallet, GET /v1/conviction/:wallet) before prompting the user to sign. See Errors.

Agent API keys

AUTH The Agents API is for bots and automated systems. An agent registers once to receive an API key, then passes it on every authenticated agent call:

curl 'https://api.magmaprotocol.xyz/v1/agent/feed' \
-H 'x-api-key: <agent-api-key>'

Missing or invalid keys return 401. Agent registration is itself rate-limited; see Agents and, for machine-payable access, the x402 payments guide.

Admin & operations credentials

AUTH Operational routes under /admin and /v1/admin require two headers identifying an authorized operator wallet:

x-admin-wallet: <operator-wallet-address>
x-admin-secret: <admin-secret>
curl 'https://api.magmaprotocol.xyz/v1/shield/blocked' \
-H 'x-admin-wallet: <operator-wallet-address>' \
-H 'x-admin-secret: <admin-secret>'

These credentials gate sensitive operations — resolving Shield protocol cover, listing and unblocking flagged IP hashes, score recalculation, and the admin dashboard. A missing or wrong pair returns 401 Unauthorized. The BullMQ queue monitor at /admin/queues is additionally protected by HTTP Basic auth.

Never ship admin secrets to clients

Admin credentials grant protocol-level control. Keep them server-side only. They are not interchangeable with end-user wallet signatures and must never be embedded in a mobile or web bundle.

CORS

Browser clients are served permissive CORS for the MAGMA web origins (app.magmaprotocol.xyz, magmaprotocol.xyz, admin.magmaprotocol.xyz) and for local development. Native apps send no Origin header and are allowed through. The allowed request headers include Content-Type, Authorization, x-admin-wallet, and x-admin-secret.