Skip to main content

Stablecoin invoice matching

What is stablecoin invoice matching?

Stablecoin invoice matching is the job of tying each incoming stablecoin payment to the invoice or customer it pays, also called crypto cash application or payment attribution.

Payment service providers, fintechs that keep their own ledger and stablecoin payment rails run it so receivables close when the money lands, and so a payment nobody can place gets looked at the same day.

Goldsky can read each payment, and its memo where the token carries one, and land it in your database next to your invoices; the match itself is a join your team writes and owns.

You can match stablecoin payments to invoices two ways: stream every payment, memo included, into your database with Turbo Pipelines, or pull each receiving wallet’s transfers from the Feeds transfers API.

Who uses stablecoin invoice matching?

Payment service providers, B2B payment platforms and fintechs that keep their own ledger and invoice customers in stablecoins.

How stablecoin invoice matching works

The diagram follows one invoice from the moment you issue it to the cash applied against it, and shows who does each step. Your setup may differ.

Your business, step 1: Issue the invoiceIts reference goes on your open list
Goldsky, step 2: TurboKeep open referencesReady for the payment check
Blockchains, step 3: Customer paysStablecoins, quoting the reference where possible
Goldsky, step 4: TurboRead what was paidThe transfer, and its memo if any
Goldsky, step 5: TurboLand beside your ledgerEvery payment, next to your invoices
Goldsky, step 6: TurboFlag unknown referencesA webhook when no open invoice matches
Your business, step 7: BankReceive bank paymentsWires and ACH against the same invoices
Your business, step 8: Match and apply cashJoin on reference, close paid invoices
  • Goldsky
  • Your provider

Ways to match stablecoin payments to invoices

Streaming pushes each payment beside your invoices with its memo and can flag unknown references as they arrive; the transfers API returns incoming transfers when your app calls it, without memos.

Best for
Many payments, matched on a reference in your own database
Products
Turbo
What you run
The destination: your database, queue or bucket, or a Postgres database Goldsky hosts
What you write
Pipeline YAML and SQL; TypeScript transforms when needed
Where your data lives
In your own database or systems
How results reach you
Pushed to you
Best for
A few receiving wallets, checked from your app
Products
Feeds
What you run
Nothing; you call an endpoint and keep what you need
What you write
REST requests
Where your data lives
Hosted by Goldsky
How results reach you
Returned when you call

Option 1: Match stablecoin payments to invoices by streaming to your database

A pipeline decodes each payment to your receiving addresses, including its memo where the token supports one, and writes it to your database next to your invoices. Payments whose reference matches no open invoice also go to a webhook.

When to stream payments next to your invoices

Payments carry a reference you can join on, or you receive many payments a day and want each one in your database as it lands.

What you’ll need

  • Goldsky Turbo
  • An invoicing or receivables system that issues a reference per invoice
  • A database next to your ledger for payment rows and open references
  • An endpoint or queue for unmatched payments, if you want them flagged as they arrive
  1. Issue the invoice with a payment reference

    A payment can only be applied to an invoice if something on the payment points back to it.

    Give each invoice a reference the payer can include, or a receiving address used for that invoice alone, and keep the reference on your list of open invoices. Without one, matching falls back to amount and date, and two invoices for the same amount can’t be told apart.

  2. Keep the open references where the payment check can see them

    Handled by Goldsky Turbo

    To flag a payment nobody expected, you need the current list of references you are expecting.

    Add a reference when an invoice opens and remove it when it’s paid or canceled. A stale list either flags good payments or lets unknown ones through.

    Goldsky’s Turbo Pipelines can hold the open references in a dynamic table, a Postgres table your invoicing system inserts into and deletes from while the pipeline runs.

    Learn about dynamic tables (opens in a new tab)
  3. Receive the customer’s payment

    The customer pays in stablecoins from their own wallet or an exchange.

    Some tokens let the payer attach a memo carrying your reference; many don’t, and some payers leave it out. A payment can also arrive short, early or split in two, so matching has to expect more than one payment per invoice.

  4. Read what was paid, and the reference with it

    Handled by Goldsky Turbo

    Matching needs the payer, the amount, the token and, where there is one, the memo.

    Decode every payment to your receiving addresses with its transaction hash, so each row can be traced to the chain. A memo left encoded as raw bytes can’t be compared with the reference on your invoice.

    In Turbo Pipelines, _gs_log_decode decodes each transfer event with the token’s ABI, so a memo field such as the one on TransferWithMemo lands as its own column.

    Decode event logs in SQL (opens in a new tab)
  5. Land every payment beside your invoices

    Handled by Goldsky Turbo

    Matching is a join, and a join is easiest when payments and invoices sit in the same database.

    Write each payment as a row keyed on a stable ID, so a repeat delivery overwrites the same row. A reorg can remove a payment you already wrote, and the table has to follow the chain.

    With Goldsky, the pipeline writes each payment to a database table with a primary_key, so repeats overwrite the same row and reorg corrections update or delete it.

    How reorgs reach your sinks (opens in a new tab)
  6. Flag payments with an unknown reference

    Handled by Goldsky Turbo

    A payment that matches no open invoice needs a person, and the sooner they hear, the easier the payer is to reach.

    Send the payment to your operations queue the moment it arrives with a reference you weren’t expecting. Rules about something missing, such as an invoice still unpaid past its due date, run on a schedule against your database.

    A SQL transform can keep payments where dynamic_table_check() finds no open reference and send them to a webhook sink. The webhook fires when the payment is seen, so your receiver also applies any correction that follows.

    Set up the webhook sink (opens in a new tab)
  7. Take bank payments against the same invoices

    Most customers still pay invoices by bank transfer, so open invoices are settled from two places.

    Your bank reports each incoming wire or ACH payment with the payer’s reference. Close an invoice from whichever rail paid it, and check both before chasing a customer, or someone who paid by wire gets a reminder.

  8. Match payments and apply cash

    Cash application is the accounting step: the invoice closes and the receivable comes off the books.

    Join each payment to its open invoice on the reference, or on address and amount where there’s no reference, then mark the invoice paid, short-paid or overpaid. Anything left over goes to someone who can contact the payer, before it ages into an unexplained balance.

What to know about streaming payments into your database

  • The match is a SQL join you write and run on your data, so short payments and split payments follow your rules.
  • Memos exist only where the token carries one; other payments are matched on address and amount.
  • Database rows are corrected after a reorg; the webhook for unmatched payments receives corrections that your receiver applies.
  • Goldsky runs the pipeline; you own the database, the open-invoice list and the matching SQL.

Option 2: Match stablecoin payments to invoices with a transfers API

Your app calls the Feeds transfers endpoint for each receiving wallet and gets back incoming transfers with token details and the USD value at transfer time. There are no memos, so each invoice gets its own receiving address or a distinct amount.

When to match invoices with a wallet transfers API

You issue each invoice its own receiving address, or receive few enough payments that matching on amount is reliable, and don’t want a pipeline or database to run.

What you’ll need

  • Goldsky Feeds
  • An invoicing or receivables system
  • A receiving address per invoice, or amounts distinct enough to match on
  • A store for transfers you’ve already applied
  1. Issue the invoice with a payment reference

    A payment can only be applied to an invoice if something on the payment points back to it.

    Give each invoice a reference the payer can include, or a receiving address used for that invoice alone, and keep the reference on your list of open invoices. Without one, matching falls back to amount and date, and two invoices for the same amount can’t be told apart.

  2. Receive the customer’s payment

    The customer pays in stablecoins from their own wallet or an exchange.

    Some tokens let the payer attach a memo carrying your reference; many don’t, and some payers leave it out. A payment can also arrive short, early or split in two, so matching has to expect more than one payment per invoice.

  3. Look up each receiving wallet’s incoming transfers

    Handled by Goldsky Feeds

    Your app checks for payments by requesting each receiving wallet’s recent incoming transfers.

    Request every token you accept, for the window since your last check. Transfers have no ID, and one transaction can contain two identical transfers, so your record of applied payments can’t rely on amount and address alone.

    Feeds returns a wallet’s native and ERC-20 transfers from its transfers endpoint, newest first, with direction=in for receipts and the USD value at transfer time on each row.

    Read the transfers endpoint reference (opens in a new tab)
  4. Wait until each payment is final

    A payment you saw can still be undone by a reorg, when the chain replaces its newest blocks.

    Hold each payment until enough blocks sit on top of it, by a rule you set per chain, and check it again before applying it. An invoice closed on a payment that later vanishes reopens as a break.

  5. Flag payments that match no invoice

    A payment nobody can place needs a person to contact the payer.

    Your code sends any final payment with no matching address or amount to your operations queue. A short payment matches its invoice but leaves a balance, which is a different case from an unknown payment.

  6. Take bank payments against the same invoices

    Most customers still pay invoices by bank transfer, so open invoices are settled from two places.

    Your bank reports each incoming wire or ACH payment with the payer’s reference. Close an invoice from whichever rail paid it, and check both before chasing a customer, or someone who paid by wire gets a reminder.

  7. Match payments and apply cash

    Cash application is the accounting step: the invoice closes and the receivable comes off the books.

    Join each payment to its open invoice on the reference, or on address and amount where there’s no reference, then mark the invoice paid, short-paid or overpaid. Anything left over goes to someone who can contact the payer, before it ages into an unexplained balance.

What to know about matching invoices with a transfers API

  • The API has no memos, so the reference has to be the address or the amount.
  • Your app pulls, so a payment shows up when you call, and flagging unknown payments is code you write.
  • A transfer undone by a reorg stops appearing in responses with no flag; wait for finality before applying cash.
  • The API values each transfer when you request it, so store the USD value when you apply the payment.

What you control

Your team
  • Issue the invoice with a payment reference
  • Match payments and apply cash
Your providers
  • Bank

Security and deployment

  • SOC 2 Type IIIndependently audited security controls.
  • Dedicated infrastructureSingle-tenant options for production workloads.
  • Data residencyCloud, on-premises or co-located.

Match stablecoin payments to invoices with Goldsky

We’ll map it to your systems and show you what Goldsky runs, so your team builds the product, not the pipelines underneath it.

© Endless Sky Inc. All rights reserved.

PrivacyTermsSecurity

System status