AI-Migration
BTCPay Server migration
Use an AI agent to replace BTCPay Server invoices, checkout links, modal checkout, Greenfield webhooks, and status handling with MakePay APIs and SDKs.
Overview
This AI compatibility guide gives a senior developer or coding agent a direct
path for replacing BTCPay Server invoice creation, checkout links, modal
checkout, Greenfield webhooks, legacy BitPay-compatible invoice flows, invoice
status polling, and refund hooks with MakePay. It covers store-scoped API keys,
POST /api/v1/stores/{storeId}/invoices, checkoutLink, invoiceId, webhook
events, BTCPay-Sig HMAC-SHA256 verification, invoice status and
additionalStatus, and SDK installation.
Use it when the existing codebase calls a self-hosted or third-party BTCPay
Server instance, uses BTCPay Server plugins, stores BTCPay invoice IDs on
orders, loads btcpay.js, or verifies Greenfield webhooks before fulfilling
orders. BTCPay Server documents the current integration model in the
eCommerce Integration Guide,
Greenfield API docs,
Greenfield PHP examples,
Custom Integration guide,
Invoices guide,
and
General FAQ.
Migration map
BTCPay Server integrations usually create a store-scoped invoice, store the
invoice ID beside the order, redirect the buyer to checkoutLink or open the
BTCPay modal, and reconcile InvoiceProcessing, InvoiceSettled, InvoiceExpired,
and InvoiceInvalid webhooks. In MakePay, use payment links, signed webhooks,
and SDK helpers for the same order flow.
| BTCPay Server surface | MakePay replacement |
|---|---|
| User-provided BTCPay Server base URL | MakeCrypto company/API credential configuration |
Authorization: token API_KEY and store-scoped permissions | X-MakeCrypto-Key-Id and X-MakeCrypto-Key-Secret headers or SDK credentials |
storeId and store-scoped invoice permissions | MakeCrypto company/API credential configuration |
POST /api/v1/stores/{storeId}/invoices | POST /api/partner/v1/makepay/payment-links or SDK create-payment-link helper |
Legacy BitPay-compatible POST /invoices | MakePay payment-link creation |
Invoice id / webhook invoiceId | paymentLink.uid; keep a legacy alias during cutover |
Invoice checkoutLink | paymentLink.publicUrl |
Invoice amount, currency, metadata.orderId, and buyer metadata | payload.amount, payload.currency or exact payload.asset, and metadata |
Invoice checkout.redirectURL or legacy redirectURL | MakePay hosted-page return URL or host-page redirect handling |
btcpay.js, window.btcpay.showInvoice, and modal status messages | MakePay hosted checkout, embedded checkout route, or modal script |
| Greenfield webhooks registered under Store Settings or webhook API | MakePay webhook endpoint configured in MakeCrypto |
BTCPay-Sig HMAC-SHA256 over raw webhook payload | x-makepay-signature HMAC verification over the raw request body |
Webhook types InvoiceProcessing, InvoiceSettled, InvoiceExpired | makepay.payment.status_changed and normalized order states |
Webhook types InvoiceCreated, InvoiceReceivedPayment, InvoicePaymentSettled, InvoiceInvalid | MakePay payment events or legacy BTCPay handling during cutover |
Invoice status: New, Processing, Settled, Expired, Invalid | MakePay normalized pending, paid, expired, failed, and manual-review states |
Invoice additionalStatus: None, PaidLate, PaidOver, PaidPartial, Marked, Invalid | Explicit late, overpaid, partial, marked, invalid, and manual-review handling |
GET /api/v1/stores/{storeId}/invoices/{invoiceId} reconciliation | MakePay payment-link lookup and webhook replay/reconciliation tooling |
| Refund links from invoice refund or pull-payment endpoints | MakePay refund or manual support workflow |
For a clean migration, keep provider-specific IDs separate. Existing BTCPay Server invoices should continue to reconcile until they are settled, expired, invalid, partially paid, overpaid, paid late, refunded, or manually closed by current business rules, while new orders use MakePay.
SDK install commands
Pick the SDK that matches the service being migrated. These are the same quick commands shown on the MakePay SDK cards.
npm install @makecrypto/makepay
composer require makepay/makepay-php
go get github.com/makecryptoio/makepay-go
pip install makepay
cargo add makepay
implementation("io.makecrypto:makepay:0.3.0")
.package(url: "https://github.com/makecryptoio/makepay-swift-sdk.git", from: "0.3.0")
Use the SDK for payment-link creation and webhook verification whenever the language supports it. If a service has a custom HTTP client layer, call the payment-links API directly and keep the provider adapter small.
Agent prompts
Inventory BTCPay Server usage
You are migrating this repository from BTCPay Server to MakePay. Search for
BTCPay Server API clients, btcpayserver, btcpay.js, window.btcpay,
showInvoice, onModalReceiveMessage, /api/v1/stores, /api/v1/stores/*/invoices,
/api/v1/stores/*/webhooks, /api-keys/authorize, Authorization: token,
API_KEY, storeId, STORE_ID, checkoutLink, invoiceId, invoice.id, metadata.orderId,
orderId, buyerEmail, checkout.redirectURL, redirectURL, notificationUrl,
BTCPay-Sig, webhook secret, InvoiceCreated, InvoiceReceivedPayment,
InvoicePaymentSettled, InvoiceProcessing, InvoiceExpired, InvoiceSettled,
InvoiceInvalid, status, additionalStatus, Expired, Invalid, New, Processing,
Settled, Marked, None, PaidLate, PaidOver, PaidPartial, BitPay-compatible
/invoices calls, and refund/pull-payment endpoints.
Return a file-by-file migration plan with the exact functions that create
BTCPay invoices, store invoice IDs, redirect or open modal checkout, verify
webhooks, fetch invoice status, process late/partial/overpaid invoices, issue
refund links, and reconcile order status. Do not edit files yet.
Replace invoice creation
Implement MakePay payment-link creation in the existing BTCPay Server invoice
creation path. Use the official MakePay SDK for this stack when available;
otherwise call POST /api/partner/v1/makepay/payment-links.
Remove BTCPay Server API key and storeId usage from the new-order path. Map
BTCPay invoice amount to payload.amount, currency to payload.currency or
payload.asset, metadata.orderId or orderId to merchantOrderId, item description
to label or description, buyer email to clientEmail, and checkout.redirectURL or
redirectURL to MakePay redirect handling.
Store paymentLink.uid and paymentLink.publicUrl, and keep nullable legacy BTCPay
invoice ID fields for historical records.
Replace hosted and modal checkout
Replace BTCPay checkoutLink redirects with MakePay paymentLink.publicUrl. For
BTCPay modal checkout, remove btcpay.js, window.btcpay.showInvoice, and
onModalReceiveMessage for new MakePay orders. Use MakePay hosted checkout,
embedded checkout route, or modal script depending on the existing UX.
Do not carry forward BTCPay checkout QR codes, Lightning invoice strings,
on-chain addresses, payment method IDs, or modal status messages as the primary
order URL for new MakePay orders; those are provider-specific checkout
artifacts.
Replace webhook verification
Replace BTCPay Server webhook handling with MakePay webhook verification. For
legacy BTCPay invoices, keep BTCPay-Sig validation by reading the exact raw
request body, computing HMAC-SHA256 with the BTCPay webhook secret, and
comparing against the BTCPay-Sig header using a timing-safe compare. Keep legacy
webhook routing by invoiceId until all open BTCPay invoices are closed.
For new MakePay events, read the exact raw request body before JSON parsing,
parse x-makepay-signature, verify timestamp tolerance and HMAC digest with the
MakePay webhook secret, then process only trusted events.
Treat makepay.payment.status_changed as the primary order reconciliation event
and make updates idempotent by delivery ID and payment-link UID. For legacy
BTCPay webhooks, use the BTCPay event ID when present plus invoiceId and event
type for idempotency.
Normalize statuses
Map legacy BTCPay Server statuses explicitly during cutover. New should not
grant goods. Processing means the full invoice payment has been seen in the
mempool and should remain pending or on hold until settlement policy is met.
Settled can complete the order. Expired should close the payment unless
additionalStatus indicates PaidLate or PaidPartial. Invalid should close the
payment or route to manual review. PaidPartial should go to underpayment/manual
review. PaidOver should go to overpayment/manual review. PaidLate should follow
the existing late-payment policy. Marked should only complete the order if the
current business already treats manually marked invoices as paid.
Dual-run cutover
Add a migration flag so newly created orders use MakePay while existing BTCPay
Server invoices can still receive webhooks and invoice-status polling until they
are settled, expired, invalid, partially paid, overpaid, paid late, refunded, or
manually closed through the current business rules. Route callbacks by provider,
keep provider-specific IDs separate, and add logs that include provider, order
ID, payment UID, delivery ID, legacy BTCPay invoiceId, event type, status,
additionalStatus, transaction/payment method data, and normalized status.
Remove BTCPay API keys, store IDs, webhook secrets, btcpay.js modal code,
checkoutLink handling, BTCPay-Sig validation, invoice polling, and refund-link
code only after there are no open legacy BTCPay invoices.
Write tests
Add or update tests for MakePay payment-link creation, failed authentication,
webhook signature rejection, successful makepay.payment.status_changed handling,
duplicate webhook delivery idempotency, legacy BTCPay webhook routing during
cutover, BTCPay-Sig rejection, checkoutLink replacement, btcpay.js modal
removal, New not granting goods, Processing pending behavior, Settled
completion, Expired closure, Invalid closure/manual review, PaidLate policy,
PaidPartial underpayment handling, PaidOver overpayment handling, Marked policy,
legacy invoice polling fallback, and buyer redirect URL generation.
Use mocked MakePay SDK/API responses. Do not hit production APIs in tests.
Copy migration Markdown
The block below is a compact agent-ready brief for repository migrations. Copy it into Codex, Claude Code, Cursor, or another codebase-aware assistant when you want the model to perform the migration against a real project.
# Migrate BTCPay Server to MakePay
Use this as the working brief for an AI coding agent. Replace BTCPay Server invoice creation, checkout links, modal checkout, Greenfield webhooks, legacy BitPay-compatible invoice flows, invoice status polling, refund hooks, status reconciliation, and provider API usage with MakePay payment links, signed webhooks, and the SDK that matches the codebase.
## Target MakePay SDK
Choose one install command for the stack being migrated:
```bash
npm install @makecrypto/makepay
composer require makepay/makepay-php
go get github.com/makecryptoio/makepay-go
pip install makepay
cargo add makepay
```
For JVM services use:
```kotlin
implementation("io.makecrypto:makepay:0.1.0")
```
For Swift Package Manager use:
```swift
.package(url: "https://github.com/makecryptoio/makepay-swift-sdk.git", from: "0.3.0")
```
## Migration map
- BTCPay Server base URL -> MakeCrypto company/API credential configuration.
- BTCPay `Authorization: token API_KEY`, store-scoped permissions, and `storeId` -> MakePay `X-MakeCrypto-Key-Id` and `X-MakeCrypto-Key-Secret` headers or SDK credentials.
- BTCPay `POST /api/v1/stores/{storeId}/invoices` -> MakePay `POST /api/partner/v1/makepay/payment-links` or the SDK create-payment-link helper.
- Legacy BTCPay BitPay-compatible `POST /invoices` -> MakePay payment-link creation.
- BTCPay invoice `id` and webhook `invoiceId` -> MakePay `paymentLink.uid`; keep the old invoice ID in a migration alias table while orders are in flight.
- BTCPay invoice `checkoutLink` -> MakePay `paymentLink.publicUrl`.
- BTCPay invoice `amount`, `currency`, `metadata.orderId`, buyer metadata, and item description -> MakePay `payload.amount`, `payload.currency` or exact `payload.asset`, `merchantOrderId`, `clientEmail`, `label`, and `description`.
- BTCPay `checkout.redirectURL`, legacy `redirectURL`, and notification URLs -> MakePay hosted-page return URL, host-page redirect handling, and webhook endpoint.
- BTCPay `btcpay.js`, `window.btcpay.showInvoice`, and `onModalReceiveMessage` -> MakePay hosted checkout, embedded checkout route, or modal script.
- BTCPay Greenfield webhooks -> MakePay webhook endpoint configured in MakeCrypto.
- BTCPay `BTCPay-Sig` HMAC-SHA256 over the raw payload -> MakePay `x-makepay-signature` HMAC verification over the raw request body.
- BTCPay events `InvoiceCreated`, `InvoiceReceivedPayment`, `InvoicePaymentSettled`, `InvoiceProcessing`, `InvoiceExpired`, `InvoiceSettled`, and `InvoiceInvalid` -> MakePay payment events or legacy BTCPay handling during cutover.
- BTCPay statuses `New`, `Processing`, `Settled`, `Expired`, and `Invalid` -> MakePay normalized pending, paid, expired, failed, and manual-review states.
- BTCPay `additionalStatus` values `None`, `PaidLate`, `PaidOver`, `PaidPartial`, `Marked`, and `Invalid` -> explicit late, overpaid, partial, marked, invalid, and manual-review handling.
- BTCPay `GET /api/v1/stores/{storeId}/invoices/{invoiceId}` reconciliation -> MakePay payment-link lookup and webhook replay/reconciliation tooling.
- BTCPay refund links or pull-payment endpoints -> MakePay refund or manual support workflow.
## Agent prompt: inventory
You are migrating this repository from BTCPay Server to MakePay. Search for BTCPay Server API clients, `btcpayserver`, `btcpay.js`, `window.btcpay`, `showInvoice`, `onModalReceiveMessage`, `/api/v1/stores`, `/api/v1/stores/*/invoices`, `/api/v1/stores/*/webhooks`, `/api-keys/authorize`, `Authorization: token`, `API_KEY`, `storeId`, `STORE_ID`, `checkoutLink`, `invoiceId`, `invoice.id`, `metadata.orderId`, `orderId`, `buyerEmail`, `checkout.redirectURL`, `redirectURL`, `notificationUrl`, `BTCPay-Sig`, webhook secret, `InvoiceCreated`, `InvoiceReceivedPayment`, `InvoicePaymentSettled`, `InvoiceProcessing`, `InvoiceExpired`, `InvoiceSettled`, `InvoiceInvalid`, `status`, `additionalStatus`, `Expired`, `Invalid`, `New`, `Processing`, `Settled`, `Marked`, `None`, `PaidLate`, `PaidOver`, `PaidPartial`, legacy BitPay-compatible `/invoices` calls, and refund/pull-payment endpoints. Return a file-by-file migration plan with the exact functions that create BTCPay invoices, store invoice IDs, redirect or open modal checkout, verify webhooks, fetch invoice status, process late/partial/overpaid invoices, issue refund links, and reconcile order status. Do not edit files yet.
## Agent prompt: replace invoice creation
Implement MakePay payment-link creation in the existing BTCPay Server invoice creation path. Use the official MakePay SDK for this stack when available; otherwise call `POST /api/partner/v1/makepay/payment-links`. Remove BTCPay Server API key and `storeId` usage from the new-order path. Map BTCPay invoice `amount` to `payload.amount`, `currency` to `payload.currency` or `payload.asset`, `metadata.orderId` or `orderId` to `merchantOrderId`, item description to `label` or `description`, buyer email to `clientEmail`, and `checkout.redirectURL` or `redirectURL` to MakePay redirect handling. Store `paymentLink.uid` and `paymentLink.publicUrl`, and keep nullable legacy BTCPay invoice ID fields for historical records.
## Agent prompt: replace hosted and modal checkout
Replace BTCPay `checkoutLink` redirects with MakePay `paymentLink.publicUrl`. For BTCPay modal checkout, remove `btcpay.js`, `window.btcpay.showInvoice`, and `onModalReceiveMessage` for new MakePay orders. Use MakePay hosted checkout, embedded checkout route, or modal script depending on the existing UX. Do not carry forward BTCPay checkout QR codes, Lightning invoice strings, on-chain addresses, payment method IDs, or modal status messages as the primary order URL for new MakePay orders; those are provider-specific checkout artifacts.
## Agent prompt: replace webhook verification
Replace BTCPay Server webhook handling with MakePay webhook verification. For legacy BTCPay invoices, keep `BTCPay-Sig` validation by reading the exact raw request body, computing HMAC-SHA256 with the BTCPay webhook secret, and comparing against the `BTCPay-Sig` header using a timing-safe compare. Keep legacy webhook routing by `invoiceId` until all open BTCPay invoices are closed. For new MakePay events, read the exact raw request body before JSON parsing, parse `x-makepay-signature`, verify timestamp tolerance and HMAC digest with the MakePay webhook secret, then process only trusted events. Treat `makepay.payment.status_changed` as the primary order reconciliation event and make updates idempotent by delivery ID and payment-link UID. For legacy BTCPay webhooks, use the BTCPay event ID when present plus `invoiceId` and event type for idempotency.
## Agent prompt: normalize statuses
Map legacy BTCPay Server statuses explicitly during cutover. `New` should not grant goods. `Processing` means the full invoice payment has been seen in the mempool and should remain pending or on hold until settlement policy is met. `Settled` can complete the order. `Expired` should close the payment unless `additionalStatus` indicates `PaidLate` or `PaidPartial`. `Invalid` should close the payment or route to manual review. `PaidPartial` should go to underpayment/manual review. `PaidOver` should go to overpayment/manual review. `PaidLate` should follow the existing late-payment policy. `Marked` should only complete the order if the current business already treats manually marked invoices as paid.
## Agent prompt: dual-run cutover
Add a migration flag so newly created orders use MakePay while existing BTCPay Server invoices can still receive webhooks and invoice-status polling until they are settled, expired, invalid, partially paid, overpaid, paid late, refunded, or manually closed through the current business rules. Route callbacks by provider, keep provider-specific IDs separate, and add logs that include provider, order ID, payment UID, delivery ID, legacy BTCPay `invoiceId`, event type, status, `additionalStatus`, transaction/payment method data, and normalized status. Remove BTCPay API keys, store IDs, webhook secrets, `btcpay.js` modal code, `checkoutLink` handling, `BTCPay-Sig` validation, invoice polling, and refund-link code only after there are no open legacy BTCPay invoices.
## Agent prompt: tests
Add or update tests for MakePay payment-link creation, failed authentication, webhook signature rejection, successful `makepay.payment.status_changed` handling, duplicate webhook delivery idempotency, legacy BTCPay webhook routing during cutover, `BTCPay-Sig` rejection, `checkoutLink` replacement, `btcpay.js` modal removal, `New` not granting goods, `Processing` pending behavior, `Settled` completion, `Expired` closure, `Invalid` closure/manual review, `PaidLate` policy, `PaidPartial` underpayment handling, `PaidOver` overpayment handling, `Marked` policy, legacy invoice polling fallback, and buyer redirect URL generation. Use mocked MakePay SDK/API responses; do not hit production APIs in tests.
## Verification checklist
- A new order creates exactly one MakePay payment link and stores `paymentLink.uid`.
- The buyer redirect uses `paymentLink.publicUrl` instead of BTCPay `checkoutLink`.
- New-order code no longer sends BTCPay `Authorization: token API_KEY` requests or requires `storeId`.
- New MakePay orders do not load `btcpay.js` or depend on BTCPay modal status messages.
- Webhook verification fails closed when `x-makepay-signature` is missing, stale, or invalid.
- `makepay.payment.status_changed` handling is idempotent by delivery ID.
- Completed orders cannot be regressed by delayed provider events.
- Legacy BTCPay Server webhooks keep `BTCPay-Sig` validation until cutover is complete.
- New, processing, settled, expired, invalid, paid late, paid partial, paid over, and marked paths are explicitly tested.
- Existing BTCPay Server invoices still reconcile until the migration flag is removed.Verification checklist
- A new order creates exactly one MakePay payment link and stores
paymentLink.uid. - The buyer redirect uses
paymentLink.publicUrlinstead of BTCPaycheckoutLink. - New-order code no longer sends BTCPay
Authorization: token API_KEYrequests or requiresstoreId. - New MakePay orders do not load
btcpay.jsor depend on BTCPay modal status messages. - Webhook verification fails closed when
x-makepay-signatureis missing, stale, or invalid. makepay.payment.status_changedhandling is idempotent by delivery ID.- Completed orders cannot be regressed by delayed provider events.
- Legacy BTCPay Server webhooks keep
BTCPay-Sigvalidation until cutover is complete. - New, processing, settled, expired, invalid, paid late, paid partial, paid over, and marked paths are explicitly tested.
- Existing BTCPay Server invoices still reconcile until the migration flag is removed.
- Production logs include provider, order ID, payment UID, delivery ID, legacy invoice ID, event type, status, additional status, transaction/payment method data, and normalized status.