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
| Field | Type | Required | Description |
|---|---|---|---|
sourceReq.ccy | string | ✅ | "BTC" |
sourceReq.method | string | ✅ | "on-chain" |
sourceReq.reqDetails | object | ✅ | Empty object {} |
destReq.ccy | string | ✅ | "BTC" |
destReq.method | string | ✅ | "neutronpay" (into your wallet) |
destReq.amtRequested | number | ✅ | Amount in BTC (e.g., 0.001 = 100,000 sats) |
destReq.reqDetails | object | ✅ | Empty object {} |
extRefId | string | ❌ | Your 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 —addressisnull. 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"
TheContent-Type: application/jsonheader 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:
| Field | Description |
|---|---|
reqDetails.address | Bitcoin address for the sender to pay |
reqDetails.amount | Expected amount in BTC |
reqDetails.invoice | BIP21 URI — opens the sender's wallet with address and amount pre-filled |
reqDetails.invoicePageUrl | Hosted payment page with QR code |
reqDetails.expiredAt | Expiration 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
| Method | Best 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
| State | Meaning |
|---|---|
quoted | Transaction created — address not yet generated |
srcintent | Confirmed — Bitcoin address generated, waiting for payment ⏳ |
srccreated | On-chain payment detected (awaiting confirmations) |
completed | Payment confirmed on-chain — funds in your wallet ✅ |
expired | Address expired before payment |
failed | Transaction 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:
| Fee | Description |
|---|---|
| Neutron fee | Service fee (often zero for receives) |
| Network fee | None — 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
extRefIdto attach your own order/reference ID for easy matching in webhooks. - Amounts are always in BTC, not satoshis (100 sats =
0.00000100).
Related
- Send Bitcoin On-Chain — Send BTC from your wallet
- Transaction Status Types — Complete state reference
- Webhook Guide — Real-time payment notifications
