Receive Bitcoin On-Chain

Receive Bitcoin via an on-chain transaction into your Neutron wallet. You can either use your static deposit address or create a transaction-specific address for tracking individual payments.

Overview

Sender's Wallet  ──BTC on-chain──►  Neutron  ──►  Your Neutron Wallet

Use case: Accepting Bitcoin payments from external wallets, exchanges, or any source that doesn't support Lightning.

📘

Prefer Lightning? On-chain transactions require blockchain confirmations (10-60 min). For instant settlement, use Lightning receive instead.

Option 1: Static Deposit Address

Every Neutron account has a static Bitcoin address — a permanent, reusable address that deposits directly into your wallet. No transaction creation needed.

Get Your Address

curl -X GET https://api.neutron.me/api/v2/account/onchain-address \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
  "staticOnchainAddress": "3M5A4DZX8zcybTrH3ebR9ys2jYJZ8BzBBz"
}

Share this address with anyone who wants to send you Bitcoin. Funds are automatically credited to your wallet after blockchain confirmations.

📘

This address is permanent and reusable. You don't need to generate a new one for each payment.

Best for: Simple deposits, wallet-to-wallet transfers, receiving from exchanges.

Option 2: Transaction-Specific Address

For tracking individual payments (e.g., e-commerce orders), create a transaction that generates a unique address tied to a specific amount.

Step 1: Create Transaction

curl -X POST https://api.neutron.me/api/v2/transaction \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "sourceReq": {
      "ccy": "BTC",
      "method": "on-chain",
      "reqDetails": {}
    },
    "destReq": {
      "ccy": "BTC",
      "method": "neutronpay",
      "amtRequested": 0.001,
      "reqDetails": {}
    },
    "extRefId": "order-1234"
  }'

Request Fields

FieldTypeRequiredDescription
sourceReq.ccystring"BTC"
sourceReq.methodstring"on-chain"
sourceReq.reqDetailsobjectEmpty object {}
destReq.ccystring"BTC"
destReq.methodstring"neutronpay" (into your wallet)
destReq.amtRequestednumberAmount in BTC (e.g., 0.001 = 100,000 sats)
destReq.reqDetailsobjectEmpty object {}
extRefIdstringYour reference ID (e.g., order number) — returned in webhooks
⚠️

Amounts are in BTC, not satoshis. 0.00000100 = 100 sats.

⚠️

Set the amount on one side only (source OR dest), not both.

Response

{
  "txnId": "7c5d9b60-e47f-41ef-859b-d77b2aa43f74",
  "accountId": "ne01-abc123def456",
  "txnState": "quoted",
  "sourceReq": {
    "ccy": "BTC",
    "method": "on-chain",
    "amtRequested": 0.001,
    "reqStatus": "0",
    "reqDetails": {
      "address": null,
      "invoicePageUrl": null
    }
  },
  "destReq": {
    "ccy": "BTC",
    "method": "neutronpay",
    "amtRequested": 0.001,
    "reqStatus": "0"
  },
  "fxRate": 1,
  "createdAt": 1770342000000
}
📘

The Bitcoin address is not generated yet at this stage — address is null. You must confirm the transaction first.

Step 2: Confirm Transaction

Confirm to generate the payment address:

curl -X PUT https://api.neutron.me/api/v2/transaction/7c5d9b60-e47f-41ef-859b-d77b2aa43f74/confirm \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
⚠️

The Content-Type: application/json header is required on PUT requests, even with no request body.

Response

{
  "txnId": "7c5d9b60-e47f-41ef-859b-d77b2aa43f74",
  "accountId": "ne01-abc123def456",
  "txnState": "srcintent",
  "sourceReq": {
    "ccy": "BTC",
    "method": "on-chain",
    "amtRequested": 0.001,
    "reqStatus": "0",
    "reqDetails": {
      "address": "3LPV8RBJT7NcSgb4y38ofzPHKQ68WGKbPM",
      "amount": 0.001,
      "invoice": "bitcoin:3LPV8RBJT7NcSgb4y38ofzPHKQ68WGKbPM?amount=0.00100000&message=",
      "invoicePageUrl": "https://endash.npay.live/payment-invoice/7c5d9b60-...?token=...",
      "expiredAt": "2026-02-12T06:54:45.931Z"
    }
  },
  "destReq": {
    "ccy": "BTC",
    "method": "neutronpay",
    "amtRequested": 0.001,
    "reqStatus": "0"
  },
  "fxRate": 1,
  "createdAt": 1770342000000
}

After confirmation, the response includes:

FieldDescription
reqDetails.addressBitcoin address for the sender to pay
reqDetails.amountExpected amount in BTC
reqDetails.invoiceBIP21 URI — opens the sender's wallet with address and amount pre-filled
reqDetails.invoicePageUrlHosted payment page with QR code
reqDetails.expiredAtExpiration time — the sender must pay before this

Step 3: Share with Sender

Share one of these with the sender:

  • Bitcoin address — sender enters the address and amount manually
  • BIP21 URI (bitcoin:3LPV...?amount=0.001) — opens their wallet app with details pre-filled
  • Invoice page URL — a hosted page with a QR code for easy scanning

Integration Example

Customer selects "Pay with Bitcoin"
        │
        ▼
Your server: POST /api/v2/transaction  (create)
        │
        ▼
Your server: PUT /api/v2/transaction/{txnId}/confirm
        │
        ▼
Display BIP21 QR code or link to invoicePageUrl
        │
        ▼
Customer sends BTC from their wallet
        │
        ▼
Neutron detects on-chain payment + confirmations
        │
        ▼
Webhook → Your server marks order as paid

Polling vs Webhooks

MethodBest for
Webhooks (recommended)Production apps — notified when payment confirms
Polling GET /api/v2/transaction/{txnId}Prototypes — check periodically until completed

See Webhook Guide for setup instructions.

SDK Examples

TypeScript (neutron-sdk)

import { Neutron } from "neutron-sdk";

const neutron = new Neutron({
  apiKey: process.env.NEUTRON_API_KEY,
  apiSecret: process.env.NEUTRON_API_SECRET,
});

// Get your static deposit address
const { address } = await neutron.account.btcAddress();
console.log("Deposit to:", address);

// Or create a transaction-specific address
const txn = await neutron.transactions.create({
  sourceReq: { ccy: "BTC", method: "on-chain", reqDetails: {} },
  destReq: { ccy: "BTC", method: "neutronpay", amtRequested: 0.001, reqDetails: {} },
  extRefId: "order-1234",
});
const confirmed = await neutron.transactions.confirm(txn.txnId);
console.log("Pay to:", confirmed.sourceReq.reqDetails.address);

Python (neutron-python)

from neutron import Neutron

client = Neutron(api_key="...", api_secret="...")

# Get your static deposit address
addr = client.account.btc_address()
print("Deposit to:", addr["address"])

# Or create a transaction-specific address
txn = client.transactions.create({
    "sourceReq": {"ccy": "BTC", "method": "on-chain", "reqDetails": {}},
    "destReq": {"ccy": "BTC", "method": "neutronpay", "amtRequested": 0.001, "reqDetails": {}},
    "extRefId": "order-1234",
})
confirmed = client.transactions.confirm(txn["txnId"])
print("Pay to:", confirmed["sourceReq"]["reqDetails"]["address"])

Transaction States

StateMeaning
quotedTransaction created — address not yet generated
srcintentConfirmed — Bitcoin address generated, waiting for payment ⏳
srccreatedOn-chain payment detected (awaiting confirmations)
completedPayment confirmed on-chain — funds in your wallet ✅
expiredAddress expired before payment
failedTransaction failed

On-chain transactions typically require 1-6 blockchain confirmations (10-60 minutes).

See Transaction Status Types for the complete state reference.

Fees

Receiving on-chain Bitcoin has minimal or zero fees:

FeeDescription
Neutron feeService fee (often zero for receives)
Network feeNone — the sender pays the mining fee

Notes

  • No KYC required for Bitcoin on-chain transactions. KYC is only needed for fiat payouts.
  • The transaction-specific address has an expiration time — share it with the sender promptly.
  • The static address has no expiration — it's always valid.
  • Use extRefId to attach your own order/reference ID for easy matching in webhooks.
  • Amounts are always in BTC, not satoshis (100 sats = 0.00000100).

Related