Slipstream API integration guide

avonpool betanet · 1 October 2026

Slipstream takes a signed raw transaction over HTTPS, checks it against the avonpool betanet node and a fee rule, and broadcasts it so the pool mines it. Base URL: https://slipstream.beta.avonpool.xyz. No API key, JSON responses, CORS open to any origin.

Endpoints

All paths are relative to https://slipstream.beta.avonpool.xyz. Plain HTTP redirects to HTTPS with a 301.

MethodPathReturns
POST/api/tx (alias /tx)Submits one raw transaction. {accepted, txid, status, ...} or {accepted: false, reject_reason}
GET/api/tx/{txid}{tx, events}: current state plus every status change. 404 for an unknown txid
GET/api/txs?status=&limit={txs: [...]}, newest first. limit 1–500, default 50
GET/api/fees{min_submission_rate, mineable_rate, required_rate, template_height, template_weight, updated_at}
GET/info.json (alias /api/info)The pool description. Also served at https://pool.beta.avonpool.xyz/info.json
GET/healthz{ok, template_age_s, enforcer_error}. 200 when healthy, 503 when the node's template source is down
GET/The list of endpoints

Submitting a transaction

Send the fully signed transaction as hex in one POST. The service runs testmempoolaccept first, so nothing is broadcast unless the node and the fee rule both accept it. Two body formats are accepted:

curl -s -X POST --data-binary "$RAW_TX_HEX" \
  https://slipstream.beta.avonpool.xyz/api/tx
const BASE = 'https://slipstream.beta.avonpool.xyz';

async function submitTx(hex) {
  const res = await fetch(`${BASE}/api/tx`, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ hex }),
  });
  const body = await res.json();
  if (res.status === 429) throw new Error('rate-limited: retry next minute');
  if (res.status >= 500) throw new Error(`slipstream unavailable: ${body.reject_reason ?? res.status}`);
  return body; // check body.accepted, then body.reject_reason
}

An accepted response carries the stored record, abridged here (the full field list is under Tracking a transaction):

{
  "accepted": true,
  "txid": "3f1c...",
  "wtxid": "9a2e...",
  "status": "pending",
  "vsize": 141,
  "weight": 561,
  "fee_sats": 282,
  "fee_rate": 2,
  "required_fee_rate": 1,
  "submitted_height": 970802
}

Submitting the same transaction again is safe. It returns accepted: true with already_tracked: true and the current record, instead of an error.

Responses and reject reasons

Always read accepted from the body: a rejection by the node or the fee rule comes back as HTTP 200 with accepted: false. Only malformed input, rate limiting and outages use other status codes.

HTTPreject_reasonMeaningCaller should
200(none, accepted: true)Broadcast and trackedStore the txid, start polling
200fee-rate-too-lowBelow the required rate. Body adds fee_rate and required_fee_rateRebuild at or above required_fee_rate
200already-confirmedAlready in a blockTreat as done
200node reason, e.g. missing-inputs, bad-txns-inputs-missingorspent, insufficient fee, scriptpubkey, mandatory-script-verify-flag-failed (...)The node refused it as it standsFix the transaction; do not retry unchanged
400invalid-hexEmpty, odd length or non-hex bodyFix the encoding
400tx-decode-failedHex that is not a transactionFix the serialization
400 / 413tx-sizeOver 1 MB of transaction (2 MB of hex)Split or shrink it
400invalid-bodyJSON that does not parseFix the request
429rate-limitedOver 30 submissions per minute from this IPBack off until the next minute
502node-unavailableThe pool's node did not answerRetry later with backoff

Tracking a transaction

Poll GET /api/tx/{txid} until tx.status is confirmed or dropped. The service rechecks every transaction on each new block template, so polling every 30–60 seconds is enough.

statusMeaningFinal?
pendingIn the node's mempool, not in the pool's current templateNo
in_templateIn the template the pool's miners are working on nowNo
minedIn a block, fewer than 6 confirmations. mined_by_pool is 1 if avonpool mined it, 0 if another pool didNo
confirmed6 or more confirmationsYes
droppedLeft the mempool unmined and the node refused it on resend. status_reason gives the node's reasonYes, unless resubmitted

The usual path is pending → in_template → mined → confirmed. Two moves go backwards: a block that is orphaned returns its transaction to pending, and a transaction that leaves the mempool is resent automatically, ending in pending or dropped. A dropped transaction can be submitted again once it is valid.

curl -s https://slipstream.beta.avonpool.xyz/api/tx/$TXID

The tx object has these fields: txid, wtxid, vsize, weight, fee_sats, fee_rate, required_fee_rate, submitted_at, submitted_height, submitter, status, status_reason, status_at, first_in_template_at, last_in_template_at, mined_block_hash, mined_height, mined_at, mined_by_pool, confirmations, confirmed_at, resubmissions. Times are Unix seconds; rates are sat/vB. events is the history as [{ts, event, detail}], oldest first.

GET /api/txs?status=in_template&limit=100 lists recent transactions across all submitters, without submitter.

Fees

Build the transaction at or above required_rate from GET /api/fees, or it is refused with fee-rate-too-low. The required rate is the higher of the pool's floor (1 sat/vB) and the current mineable rate. The mineable rate equals the floor while the block template has room, and becomes the cheapest included transaction's rate once the template is full.

curl -s https://slipstream.beta.avonpool.xyz/api/fees
{"min_submission_rate":1,"mineable_rate":1,"required_rate":1,"template_height":970802,"template_weight":3766,"updated_at":1790866502}

The fee rate is checked as fee in sats divided by virtual size, so read it just before signing and add a margin if blocks are filling up.

info.json

GET /info.json describes the pool for pool directories and is cached for 60 seconds. Mode, fee, coinbase tag and addresses are read from the running pool, so they always match what the coinbase pays. The same document is served at https://pool.beta.avonpool.xyz/info.json.

{
  "name": "avonpool_beta",
  "operator": "avonpool",
  "chain": "betanet",
  "mode": "solo",
  "fee_bps": 100,
  "coinbase_tag": "/avonpool/",
  "stratum_url": "stratum+tcp://pool.beta.avonpool.xyz:3334",
  "dashboard_url": "https://pool.beta.avonpool.xyz",
  "status_url": "https://pool.beta.avonpool.xyz/api/status",
  "slipstream_url": "https://slipstream.beta.avonpool.xyz",
  "operator_address": "bc1qljvzxk0tp6qtrunt590z5rtdhs8jhkkn4ny4rm",
  "pool_btc_address": null,
  "payout": "The stratum username is your BTC address; each block's coinbase pays the miner who found it.",
  "software": "simplepool",
  "version": "0.1.0",
  "logo": null,
  "contact": "pool@ecash.com"
}

fee_bps is in basis points (100 = 1%). status_url returns live pool statistics (hashrate, workers, blocks).

Limits and caveats