nora

Onramp intent

Move BRL into BRS tokens minted to a Solana wallet. Your backend creates the intent, Nora returns PIX deposit info, your user pays by PIX, and the tokens land.

An onramp intent is a single BRL → BRS mint. Your backend posts the amount, the destination Solana wallet, and the chain; Nora resolves the party from the wallet binding on file and returns PIX deposit info you surface to your user. Once the PIX lands, Nora mints BRS to the wallet and the intent reaches completed.

Prerequisite

You need a party with a connected Solana wallet first. See Parties setup — the address you pass as destinationWallet must match the profile.solanaWallet on a party you created earlier.

Flow

Loading diagram…

Create the intent

POST /v2/intents/onramp

FieldTypeRequiredNotes
amountCentsintegerYesBRL amount in cents, not decimals. 100.00 BRL → 10000. Must be > 0.
destinationWalletstringYesSolana address that will receive the minted BRS. Must match the profile.solanaWallet of a party you've created. 1–255 chars.
chainIdstringYes"solana" or "polygon" is accepted on request, but today responses only emit "solana" — Polygon is not yet live on the response side.
clientReferencestringNoYour own correlation ID, up to 255 chars. Echoed on the intent.

Headers:

HeaderValue
X-API-KeyYour API key. See Authentication.
idempotency-keyRecommended. A UUID you pick (format-validated). Reuse on retries, regenerate on new user intents. See Idempotency.

The intent body does not take a partyId. Nora resolves the party from destinationWallet.

Example:

curl -X POST https://staging.api.nora.finance/v2/intents/onramp \
  -H "X-API-Key: $NORA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "idempotency-key: $(uuidgen)" \
  -d '{
    "amountCents": 10000,
    "destinationWallet": "So11111111111111111111111111111111111111112",
    "chainId": "solana",
    "clientReference": "ord_123"
  }'

Response:

{
  "id": "8f2a...",
  "instanceId": "4e0b...",
  "partyId": "2f1b...",
  "intentType": "onramp",
  "flowVersion": 1,
  "adapter": null,
  "status": "awaiting_fiat_payment",
  "statusReason": null,
  "clientReference": "ord_123",
  "metadata": null,
  "expiresAt": "2026-04-22T12:30:00Z",
  "createdAt": "2026-04-22T12:00:00Z",
  "updatedAt": "2026-04-22T12:00:00Z",
  "pixInfo": {
    "keyType": "cnpj",
    "keyValue": "00000000000000",
    "recipientName": "Nora Financeira",
    "bank": "Banco XYZ",
    "description": "Nora onramp ord_123",
    "amountCents": 10000
  },
  "depositInstructions": null,
  "party": {
    "displayName": "João da Silva",
    "documentMasked": "***.***.***-01",
    "solanaWallet": "So11111111111111111111111111111111111111112"
  },
  "chainId": "solana"
}

Notable response fields:

  • partyId — resolved by Nora from destinationWallet.
  • intentType"onramp" here.
  • flowVersion — integer; pin on at least the version your code was written against.
  • adapter"squads", "cuiaba", or null while the intent is still being routed.
  • status — see the lifecycle table below for the full enum.

Render the PIX instructions

Surface pixInfo to the user. Today the only supported pixInfo.keyType is "cnpj" — surface keyValue as a copy button, and recipientName / bank / description / amountCents as display fields. PIX deposits expire — expiresAt on the intent is the hard deadline. If the user hasn't paid by then, the intent transitions to expired and you need a new intent (with a fresh idempotency-key) to retry.

Track completion

Poll GET /v2/intents/:id or subscribe to webhooks. The full intent status enum:

StatusTerminal?Notes
creatednoAccepted server-side, not yet routed.
requires_compliancenoHeld for compliance review.
awaiting_fiat_paymentnoWaiting for the user's PIX.
fiat_receivednoPIX confirmed by the rail.
mintingnoBRS being minted on-chain.
awaiting_onchain_transferno
awaiting_burn_approvalno(offramp) — not seen on onramp.
burn_approvedno(offramp).
onchain_receivedno
burningno(offramp).
paying_outno(offramp).
completedyesTerminal success.
expiredyesPIX window closed before payment.
canceledyes
failedyes
refundedyes

Gotchas

  • amountCents, not amount. Integer cents, not decimal BRL.
  • No partyId in the body. Nora resolves the party from destinationWallet. If the wallet isn't bound to any party in your org, the create call fails with 400.
  • Idempotency keys scope to "this user intent," not "this retry." Regenerate on a new form submission, reuse across network-level retries. See Idempotency.
  • Response chainId is "solana" today. Even though the request accepts "polygon", the response-side chain enum is Solana-only for now.

See also

On this page