All articles
blacksheeppaymentsstablecoinsfiatapiaustraliasolanafx

Blacksheep: regulated fiat ↔ crypto payments API (AU/NZ)

Blacksheep public API for builders: Ed25519-signed tRPC-style endpoints, quotes, swaps, withdrawals to bank or wallet (incl. Solana address family), webhooks, and money amount encoding.

Share
devrels.xyz/a/200short link

Blacksheep is a regulated stablecoin / multicurrency payments product (Australia AUSTRAC + New Zealand FSP) with a public API so you can quote, swap, and withdraw between fiat and crypto programmatically — bank rails on one side, self-custody wallets on the other.

Product: blacksheep.money. Docs: docs.blacksheep.money/docs. App: my.blacksheep.money. API base: https://api.blacksheep.money. X: @Blacksheepmoney.

Related: crypto cards · Solana neobank how-to · RedotPay.

What the API is for

Docs pitch: move money between fiat and crypto programmatically — manage external bank and wallet destinations, and receive webhooks for state changes. Marketing emphasizes local rails (e.g. NPP for AUD, ACH for USD), direct bank ↔ wallet paths, and keeping a model where users can maintain custody of funds outside the platform when withdrawing to wallets.

This is a regulated payments / FX API, not a Solana DEX aggregator. Solana shows up as a wallet address family (sol) for crypto withdrawals when the asset/chain pair supports it.

Domain model

ResourceMeaning
AccountOrganisation or individual owning the API key; scopes all balances, txs, destinations, webhooks
BalanceCurrency held under the account (accrues from deposits/swaps; spent by withdrawals/swaps) — not created directly
TransactionUnit of movement (deposit, withdraw, buy/sell, swap)
External accountBank account (fiat) or wallet address (crypto); created once, reused by id
QuoteIndicative rate before initiateSwap
WebhookHTTPS URL for signed transaction.created / transaction.updated

Transaction types and states

TypeDirectionAPI
depositExternal → Blacksheep balanceIncoming (no initiate call)
withdrawBalance → external accounttransaction.submitWithdraw
buy / sellFiat ↔ cryptotransaction.initiateSwap
swapHeld currency A → Btransaction.initiateSwap
StatusMeaning
PENDINGAccepted and queued
COMPLETEDSettled
FAILEDCould not complete
CANCELLEDCancelled before settlement

Prefer webhooks over polling. No client idempotency key on mutations — a retry is a new transaction; guard duplicates on your side.

HTTP shape

ItemDetail
Base URLhttps://api.blacksheep.money
MethodAll public endpoints POST + JSON (empty body when no input)
Path styletRPC-style names, e.g. POST /v1/transaction.initiateSwap
Success{ "data": ... }
Error{ "error": { "code", "message" } } (auth failures may be flat 401)
Groupsaccount.*, quote.*, transaction.*

Money encoding

Amounts are never floats. Wire format:

json
{
  "value": "1500000",
  "code": "USDC",
  "decimals": 6,
  "chain": "ethereum"
}

value is a string-encoded integer in the smallest unit; crypto also carries chain. Responses may add a metadata string field. Use BigInt / decimal libs — not Number.

Authentication (Ed25519)

No bearer tokens. Dashboard (Settings → Dev space) creates an Ed25519 keypair in-browser, registers the public key, and shows once:

EnvRole
BSK_KEY_IDPublic id → Bs-Key-Id header
BSK_SIGNING_KEYPKCS#8 DER private key, standard base64 — local only, never sent
HeaderValue
Bs-Key-IdKey id
Bs-TimestampUnix seconds
Bs-Nonce16 random bytes, standard base64
Bs-SignatureBase64 Ed25519 over the signing string
Content-Digestsha-256=:<b64>: when body present; omit if no body

Signing string joins length-prefixed fields with : (length first prevents delimiter injection):

text
{len(keyId)}:{keyId}:{len(ts)}:{ts}:{len(nonce)}:{nonce}:{METHOD}:{len(path)}:{path}:{Content-Digest}

Docs ship a Node.js signRequest helper. First call example: POST https://api.blacksheep.money/v1/account.balance.getMany. Use standard base64 (not base64url) for nonce, signature, and digest.

Core flows

Swap

text
quote.get → (show user) → transaction.initiateSwap
         → webhook transaction.updated (COMPLETED | FAILED | …)
json
// POST /quote.get — currency_out.value "0" means "price the output"
{
  "currency_in":  { "value": "100000000", "code": "USDC", "decimals": 6, "chain": "ethereum" },
  "currency_out": { "value": "0", "code": "AUD", "decimals": 2 }
}

// POST /transaction.initiateSwap — both sides non-zero; out from quote ask
{
  "currency_in":  { "value": "100000000", "code": "USDC", "decimals": 6, "chain": "ethereum" },
  "currency_out": { "value": "154700", "code": "AUD", "decimals": 2 },
  "external_accounts": { "from": null, "to": null }
}
// → { "data": "<transaction-uuid>" }

Refresh quotes every 5–10s on a confirmation UI. Engine validates implied rate vs market then re-quotes at execution. Native crypto↔crypto direct pairs are rejected — bridge via USDC/USDT. Minimum sizes and unsupported codes return BAD_REQUEST.

Withdraw to bank or wallet

Register external accounts once; withdraw with transaction.submitWithdraw + external_account_id. Wallet list: account.external.web3.getAll. Wallet metadata.type is one of:

TypeAddress family
evmEVM
tvmTVM
solSolana
btcBitcoin

Match wallet family to currency_out.chain. Network fees come out of the requested amount. On-chain refs appear on the transaction when available (external_reference).

Webhooks

TypeWhenPayload
transaction.createdNew tx{ object }
transaction.updatedStatus/fields change{ object, previous_attributes }

Register HTTPS URLs in the dashboard (not via API key endpoints). Deliveries carry webhook-id, webhook-timestamp, webhook-signature (v1a,<b64>). Signature covers id.timestamp.rawBody with the webhook’s Ed25519 public key. Respond 2xx within 20s; verify, apply ~5 minute timestamp window, and dedupe on webhook-id.

Builder checklist

StepAction
1Create account + KYC on my.blacksheep.money
2Create API key; store BSK_KEY_ID + BSK_SIGNING_KEY securely
3Implement signRequest (length-prefixed Ed25519 string)
4account.balance.getMany as smoke test
5Register webhook URL; verify signatures
6Fund balances; run quote → initiateSwap; then withdraw guides
7For Solana wallets: register WEB3 external account with type: sol; match chain on withdraw

Resources

Bottom line

Blacksheep gives ANZ-regulated fiat rails plus a clean public API: Ed25519-signed POSTs, strict money objects, quote → swap → webhook, and withdrawals to banks or multi-family wallets including Solana. For builders shipping AUD/NZD ↔ stablecoin product paths, start at auth + balances, then swap and withdraw guides — treat live chain/asset support as dashboard/docs truth, not assumptions from this summary.

Keep reading

Get new articles in your inbox

Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.

Blacksheep: regulated fiat ↔ crypto payments API (AU/NZ) | devrels.xyz