An agency launches crypto payments for three merchant clients.
The first client uses WooCommerce and only needs a standard checkout plugin.
The second runs a custom SaaS product and needs payment-triggered account activation.
The third wants a branded payment interface, customer status page, support timeline, and finance export.
The agency treats all three projects as the same integration.
It installs some code, confirms that an invoice can be created, and marks the work complete.
Then production problems begin.
One merchant cannot explain a paying payment to a customer.
Another receives duplicate callbacks and fulfills the same order twice.
A third has no idea who owns the API credentials or who should investigate a missed payment.
The payment integration technically exists.
The delivery system does not.
A Merchant Crypto Launch Kit gives agencies a repeatable way to scope, build, verify, document, hand off, and support crypto payment projects for merchant clients.
It is not only reusable code.
It is an agency operating system for crypto payment delivery.
This article uses OxaPay as the payment infrastructure reference, but the agency model is provider-agnostic.
This article is part of 10 Crypto Payment Products Developers Can Build for Merchants.
What the agency is selling
A weak agency offer is:
We can integrate a crypto payment gateway into your website.
That sounds like a one-time technical task.
A stronger offer is:
We launch a complete crypto payment workflow for your business, including checkout, verified payment updates, order activation, support procedures, recovery, testing, and team handoff.
The merchant is not only buying an API connection.
The merchant is buying a controlled launch.
The agency is buying repeatability.
The developer building the Launch Kit creates the reusable system behind both.
What a Launch Kit actually contains
A Merchant Crypto Launch Kit should include four categories of assets.
Delivery assets
These are used to implement the payment workflow:
- plugin deployment guides
- hosted invoice module
- white-label checkout module
- static address module
- webhook receiver
- payment state mapping
- fulfillment adapters
- Payment Information lookup
- Payment History recovery
- dashboard starter
Decision assets
These help the agency choose the correct architecture:
- discovery questionnaire
- integration decision tree
- scope calculator
- risk classification
- supported-platform matrix
- responsibility matrix
Verification assets
These prove that the implementation works:
- acceptance-test plan
- test data
- duplicate-event tests
- payment-state tests
- fulfillment tests
- recovery tests
- security checklist
- signed launch report
Handoff assets
These allow the merchant to operate the integration:
- payment-flow overview
- support procedures
- escalation contacts
- credential ownership record
- customer-response templates
- dashboard instructions
- incident checklist
- post-launch monitoring agreement
A GitHub repository may contain part of the kit.
It is not the complete product.
Where this product fits
A Crypto PaymentOps Service provides the operational foundation for an individual merchant.
The Launch Kit packages repeatable parts of that foundation so an agency can deploy them across several clients.
The difference is ownership and distribution.
PaymentOps product
-> Operates one merchant payment environment
Agency Launch Kit
-> Standardizes how several merchant environments are delivered
The Launch Kit must answer questions that a normal integration article does not:
Which implementation path fits this client?
What is included in scope?
Who owns each system?
What evidence proves launch readiness?
What does the merchant operate after handoff?
What remains the agency's responsibility?
How are future changes deployed safely?
The launch lifecycle
The kit should standardize seven stages.
Qualification
-> Discovery
-> Architecture
-> Implementation
-> Verification
-> Handoff
-> Post-launch operations
Each stage produces a specific output.
| Stage | Required output |
|---|---|
| Qualification | Client fit decision |
| Discovery | Approved requirements |
| Architecture | Selected integration track |
| Implementation | Configured payment workflow |
| Verification | Acceptance-test evidence |
| Handoff | Merchant operations package |
| Post-launch | Monitoring and ownership plan |
A project should not move to the next stage because someone says it “looks ready.”
It should move because the required output exists.
Qualify the merchant first
Not every merchant request should become a custom crypto payment project.
The agency should first determine whether the client:
- already sells online
- has a defined order or billing system
- has a real customer demand for crypto
- knows what should happen after payment
- has someone responsible for payment support
- can provide an HTTPS callback endpoint or use a managed service
- can define refund and late-payment policies
- can identify who owns production credentials
- can participate in acceptance testing
A client that says:
Just add a wallet address to the checkout.
may not yet understand the operational requirements.
The agency should not turn an unclear request into an unclear implementation.
The discovery questionnaire
The Launch Kit should include a structured discovery form.
Business model
What does the merchant sell?
Is the purchase one-time, renewable, prepaid, or account-based?
Does successful payment trigger immediate fulfillment?
Can fulfillment be reversed?
Does the merchant sell digital or physical products?
Does the merchant have international customers?
Current platform
Which ecommerce, billing, CMS, or application platform is used?
Is there an existing OxaPay plugin for that platform?
Is the application custom-built?
Which backend language and database are used?
Who controls deployment?
Checkout requirements
Can the customer leave the merchant website?
Is a branded payment interface required?
Does the merchant need asset or network selection?
Is a reusable deposit address required?
Does the checkout need localization?
Operational requirements
Who investigates payment incidents?
Who receives payment alerts?
Does the merchant need a customer status page?
Does finance require CSV or accounting exports?
How should underpayments and late payments be handled?
What happens when payment succeeds but fulfillment fails?
Security and ownership
Who owns the OxaPay account?
Who generates the Merchant API Key?
Where will credentials be stored?
Which agency staff can access production?
Who rotates credentials after handoff?
Who approves manual payment decisions?
The completed discovery document becomes part of the project record.
Do not rely on meeting memory.
Choose one implementation track
The Launch Kit should provide clear delivery tracks.
Track one: Plugin deployment
Use a supported plugin when:
- the merchant uses a compatible platform
- standard checkout behavior is sufficient
- no custom fulfillment layer is required
- the merchant prefers lower implementation complexity
- the plugin supports the required order states
Possible platform categories include ecommerce, hosting billing, memberships, digital downloads, forms, and other supported systems.
The agency still needs to provide:
- plugin compatibility review
- installation
- API credential configuration
- status mapping verification
- test payment
- customer checkout review
- support procedure
- handoff documentation
- launch monitoring
Installing the plugin is not the whole service.
Track two: Hosted invoice
Use OxaPay Generate Invoice when:
- fast implementation matters
- the customer can use a hosted payment page
- the important workflow happens after payment
- the merchant does not need full checkout UI ownership
The flow is:
Merchant order
-> Local payment session
-> OxaPay hosted invoice
-> Customer payment
-> Signed callback
-> Merchant order update
-> Fulfillment
This is usually the best custom-development starting point.
Track three: White-label checkout
Use a white-label payment when:
- payment must remain inside the client interface
- the client requires branded checkout
- network-specific instructions are important
- the merchant needs a custom payment status experience
- checkout design is part of the commercial value
The agency becomes responsible for displaying:
- payment asset
- network
- amount
- payment address
- QR code
- expiration
- payment state
- late-payment warnings
- customer instructions
White-label checkout is not only a different API endpoint.
It is a larger UX and support scope.
Track four: Static address account funding
Use static addresses for account-based deposits such as:
- prepaid hosting balance
- customer wallet balance
- reseller credit
- usage credits
- repeated account funding
Do not use static addresses merely because the merchant wants customers to “pay anytime.”
The implementation also needs:
- customer-to-address ownership
- deposit deduplication
- internal balance ledger
- callback processing
- address lifecycle management
- reconciliation
- support search
- crediting policy
Static address projects should usually be scoped separately from ordinary checkout.
The decision matrix
| Requirement | Recommended track |
|---|---|
| Supported platform and standard checkout | Plugin |
| Fast custom payment launch | Hosted invoice |
| Branded embedded payment UX | White-label |
| Reusable customer funding address | Static address |
| Payment-triggered business workflows | Invoice or white-label plus webhook |
| Historical recovery and reports | Payment Information and Payment History |
| Contractor or partner payouts | Separate payout module |
The decision should be recorded in the client architecture document.
It should not remain an undocumented developer preference.
Define the project boundary
Agency projects often fail because the word “integration” hides several responsibilities.
A Launch Kit should convert the project into explicit deliverables.
Example scope:
Included:
- OxaPay hosted invoice creation
- payment-to-order mapping
- HMAC-validated webhook endpoint
- paid-order activation
- customer payment status page
- support search by order ID and track_id
- Payment History recovery
- launch testing
- merchant handoff
Not included:
- refunds
- accounting
- tax calculation
- automatic payouts
- custom treasury management
- legal review
- 24/7 operational support
The client should approve this boundary before implementation.
Use an implementation manifest
Every client deployment should have a machine-readable manifest.
client:
id: merchant_acme
name: Acme Software
platform: custom_node
environment: production
integration:
provider: oxapay
mode: hosted_invoice
payment_owner: merchant
credential_owner: merchant
deployment_owner: agency
payment:
pricing_currency: USD
allowed_assets:
- USDT
- LTC
callback_endpoint_id: cb_acme_7f21
fulfill_on:
- paid
order:
external_id_field: order_id
fulfillment_adapter: license_delivery
operations:
payment_information_refresh: true
payment_history_backfill_minutes: 10
customer_status_page: true
support_search: true
handoff:
merchant_admin: ops@acme.example
agency_support: support@agency.example
monitoring_days: 14
This manifest can be used to:
- generate configuration
- validate required fields
- produce handoff documents
- build test cases
- track differences between clients
- audit configuration changes
Do not hide critical client configuration in developer notes or chat history.
Organize the Launch Kit repository
A useful repository structure could look like:
merchant-crypto-launch-kit/
├── discovery/
│ ├── questionnaire.md
│ ├── qualification-scorecard.md
│ └── scope-template.md
├── architecture/
│ ├── decision-tree.md
│ ├── responsibility-matrix.md
│ └── threat-model.md
├── runtime/
│ ├── invoice/
│ ├── white-label/
│ ├── static-address/
│ ├── webhook/
│ ├── recovery/
│ └── fulfillment/
├── adapters/
│ ├── woocommerce/
│ ├── whmcs/
│ ├── node/
│ └── laravel/
├── qa/
│ ├── acceptance-tests.md
│ ├── security-tests.md
│ └── launch-report-template.md
├── handoff/
│ ├── merchant-guide.md
│ ├── support-sop.md
│ ├── incident-template.md
│ └── credential-register.md
└── examples/
├── plugin-client/
├── hosted-invoice-client/
└── white-label-client/
This communicates that the product includes more than runtime code.
Keep merchant environments isolated
An agency may manage several clients.
Do not reuse one Merchant API Key across unrelated merchants.
Each merchant deployment should have:
- its own OxaPay merchant configuration
- its own public webhook endpoint identifier
- separate encrypted credentials
- tenant-isolated records
- separate dashboards or filtered access
- independent test and production environments
- documented credential owner
A shared agency platform may route callbacks through:
/webhooks/oxapay/{endpoint_id}
The endpoint ID identifies the merchant configuration before the request body is trusted.
It must not contain the actual API key or provide administrative access.
A practical data model
CREATE TABLE agencies (
id UUID PRIMARY KEY,
name TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE merchants (
id UUID PRIMARY KEY,
agency_id UUID NOT NULL REFERENCES agencies(id),
name TEXT NOT NULL,
platform TEXT NOT NULL,
environment TEXT NOT NULL,
webhook_endpoint_id TEXT NOT NULL UNIQUE,
oxapay_merchant_api_key_encrypted TEXT NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE deployment_manifests (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
version INTEGER NOT NULL,
manifest JSONB NOT NULL,
approved_by TEXT,
approved_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (merchant_id, version)
);
CREATE TABLE payment_sessions (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
provider TEXT NOT NULL DEFAULT 'oxapay',
provider_order_id TEXT NOT NULL,
provider_track_id TEXT,
integration_mode TEXT NOT NULL,
requested_amount NUMERIC(20, 8) NOT NULL,
pricing_currency TEXT NOT NULL,
provider_status TEXT,
internal_status TEXT NOT NULL DEFAULT 'created',
payment_url TEXT,
expires_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (merchant_id, provider_order_id),
UNIQUE (provider, provider_track_id)
);
CREATE TABLE payment_events (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
payment_session_id UUID REFERENCES payment_sessions(id),
payload_hash TEXT NOT NULL,
provider_status TEXT,
raw_payload JSONB NOT NULL,
signature_valid BOOLEAN NOT NULL,
source TEXT NOT NULL,
received_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (merchant_id, payload_hash)
);
CREATE TABLE fulfillment_actions (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
payment_session_id UUID NOT NULL REFERENCES payment_sessions(id),
action_type TEXT NOT NULL,
idempotency_key TEXT NOT NULL UNIQUE,
status TEXT NOT NULL,
attempt_count INTEGER NOT NULL DEFAULT 0,
last_error TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
completed_at TIMESTAMP
);
CREATE TABLE launch_checks (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
check_key TEXT NOT NULL,
status TEXT NOT NULL,
evidence JSONB,
checked_by TEXT,
checked_at TIMESTAMP,
UNIQUE (merchant_id, check_key)
);
CREATE TABLE operational_cases (
id UUID PRIMARY KEY,
merchant_id UUID NOT NULL REFERENCES merchants(id),
payment_session_id UUID REFERENCES payment_sessions(id),
case_type TEXT NOT NULL,
severity TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
owner_type TEXT NOT NULL,
summary TEXT NOT NULL,
resolution_note TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
resolved_at TIMESTAMP
);
The deployment manifest and launch checks are agency-specific additions.
They are not normally part of a basic merchant integration.
Create the local payment session first
The agency implementation should create an authoritative local session before calling OxaPay.
import crypto from "node:crypto";
const OXAPAY_API = "https://api.oxapay.com/v1";
export async function createMerchantInvoice({
merchant,
order,
}) {
const providerOrderId =
`order_${merchant.id}_${order.id}`;
const session =
await db.paymentSession.create({
data: {
merchantId: merchant.id,
provider: "oxapay",
providerOrderId,
integrationMode: "hosted_invoice",
requestedAmount: order.amount,
pricingCurrency: order.currency,
internalStatus: "created",
},
});
try {
const merchantApiKey = await decryptSecret(
merchant.oxapayMerchantApiKeyEncrypted,
);
const response = await fetch(
`${OXAPAY_API}/payment/invoice`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
merchant_api_key: merchantApiKey,
},
body: JSON.stringify({
amount: order.amount,
currency: order.currency,
order_id: providerOrderId,
email: order.customerEmail,
description: `Payment for order ${order.number}`,
callback_url:
`${process.env.APP_URL}/webhooks/oxapay/${merchant.webhookEndpointId}`,
return_url:
`${order.merchantBaseUrl}/orders/${order.id}/status`,
lifetime: 60,
sandbox:
merchant.environment !== "production",
}),
},
);
const payload = await response.json();
if (!response.ok) {
throw new Error(
payload?.error?.message ??
`Invoice creation failed with ${response.status}`,
);
}
const payment = payload.data;
return db.paymentSession.update({
where: {
id: session.id,
},
data: {
providerTrackId: String(payment.track_id),
providerStatus: "new",
internalStatus: "invoice_created",
paymentUrl: payment.payment_url,
expiresAt: payment.expired_at
? new Date(Number(payment.expired_at) * 1000)
: null,
},
});
} catch (error) {
await db.paymentSession.update({
where: {
id: session.id,
},
data: {
internalStatus: "creation_failed",
},
});
throw error;
}
}
The agency should adapt the order adapter to the merchant platform.
The core payment module should remain consistent.
Use a standard webhook module
OxaPay signs payment callbacks with HMAC SHA-512 over the raw request body using the Merchant API Key.
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post(
"/webhooks/oxapay/:endpointId",
express.raw({
type: "application/json",
}),
async (req, res) => {
const merchant = await db.merchant.findUnique({
where: {
webhookEndpointId: req.params.endpointId,
},
});
if (!merchant || !merchant.active) {
return res.status(404).send("unknown endpoint");
}
const rawBody = req.body;
const receivedHmac = req.get("HMAC");
const merchantApiKey = await decryptSecret(
merchant.oxapayMerchantApiKeyEncrypted,
);
const expectedHmac = crypto
.createHmac("sha512", merchantApiKey)
.update(rawBody)
.digest("hex");
if (!safeEqualSha512(receivedHmac, expectedHmac)) {
await recordRejectedCallback({
merchantId: merchant.id,
reason: "invalid_hmac",
});
return res.status(401).send("invalid signature");
}
let payload;
try {
payload = JSON.parse(
rawBody.toString("utf8"),
);
} catch {
return res.status(400).send("invalid json");
}
const payloadHash = crypto
.createHash("sha256")
.update(rawBody)
.digest("hex");
try {
const stored = await persistEventAndOutboxOnce({
merchant,
payload,
payloadHash,
});
if (!stored) {
return res.status(200).send("ok");
}
return res.status(200).send("ok");
} catch (error) {
console.error(
"Webhook persistence failed",
error,
);
return res.status(500).send("failed");
}
},
);
function safeEqualSha512(received, expected) {
const sha512Hex = /^[a-f0-9]{128}$/i;
if (
!received ||
!expected ||
!sha512Hex.test(received) ||
!sha512Hex.test(expected)
) {
return false;
}
return crypto.timingSafeEqual(
Buffer.from(received, "hex"),
Buffer.from(expected, "hex"),
);
}
persistEventAndOutboxOnce should use one database transaction:
Insert payment event
+
Insert processing job
+
Commit
If the event already exists, return successfully without creating another job.
The callback endpoint should not call the merchant fulfillment system directly.
Standardize payment status mapping
const PAYMENT_STATUS_MAP = {
new: "created",
waiting: "waiting",
paying: "confirming",
paid: "paid",
manual_accept: "manual_review",
underpaid: "underpaid",
expired: "expired",
refunding: "refund_in_progress",
refunded: "refunded",
};
export function mapPaymentStatus(status) {
const normalized = String(status ?? "")
.trim()
.toLowerCase();
return PAYMENT_STATUS_MAP[normalized] ?? "unknown";
}
The merchant workflow should normally fulfill on:
paid
not:
paying
The agency acceptance test should explicitly verify this behavior.
Use merchant adapters
Do not copy the full webhook handler for every platform.
Build adapters behind a shared contract.
type MerchantAdapter = {
findOrder(
externalOrderId: string
): Promise<MerchantOrder | null>;
markPaymentDetected(
order: MerchantOrder
): Promise<void>;
markPaid(
order: MerchantOrder
): Promise<void>;
fulfill(
order: MerchantOrder,
idempotencyKey: string
): Promise<FulfillmentResult>;
verifyFulfillment(
order: MerchantOrder
): Promise<boolean>;
};
Possible adapters include:
WooCommerce
WHMCS
Laravel application
Node.js application
Digital download store
SaaS billing system
Telegram membership system
The payment runtime stays stable.
The adapter translates provider events into platform-specific actions.
Make fulfillment idempotent
A stable fulfillment key can include:
merchant_id
+ provider_track_id
+ fulfillment_action
async function fulfillOrderOnce({
merchant,
session,
adapter,
}) {
const idempotencyKey = [
merchant.id,
session.providerTrackId,
"fulfill_order",
].join(":");
const existing =
await db.fulfillmentAction.findUnique({
where: {
idempotencyKey,
},
});
if (existing?.status === "completed") {
return existing;
}
const order = await adapter.findOrder(
session.providerOrderId,
);
if (!order) {
throw new PermanentLaunchError(
"Merchant order not found",
);
}
const action =
existing ??
(await db.fulfillmentAction.create({
data: {
merchantId: merchant.id,
paymentSessionId: session.id,
actionType: "fulfill_order",
idempotencyKey,
status: "running",
attemptCount: 1,
},
}));
try {
await adapter.markPaid(order);
const result = await adapter.fulfill(
order,
idempotencyKey,
);
const verified =
await adapter.verifyFulfillment(order);
if (!verified) {
throw new TransientLaunchError(
"Fulfillment outcome could not be verified",
);
}
await db.fulfillmentAction.update({
where: {
id: action.id,
},
data: {
status: "completed",
completedAt: new Date(),
},
});
return result;
} catch (error) {
await recordFulfillmentFailure({
actionId: action.id,
error,
});
throw error;
}
}
A callback duplicate should not create a second product delivery or service extension.
Add recovery by default
The Launch Kit should not offer Payment History recovery as an optional afterthought.
A production deployment should include it by default.
A scheduled task can:
Retrieve recent OxaPay payments
-> Match by track_id or order_id
-> Update local provider state
-> Detect missed callbacks
-> Detect paid but unfulfilled orders
-> Create operational cases
OxaPay Payment History is currently available through:
GET /v1/payment
Payment Information retrieves one payment through:
GET /v1/payment/{track_id}
A practical schedule is:
Every 10 minutes:
- query an overlapping recent time window
- upsert provider records
- identify missing local events
- retry safe processing
Every night:
- compare paid payments with merchant fulfillment
- generate unresolved-case report
The recovery job should identify its source:
source = payment_history_backfill
Do not make recovered records look like original callbacks.
The agency acceptance-test matrix
Testing should cover more than one successful payment.
| Test | Expected result |
|---|---|
| Invoice creation | Local session and provider track_id stored |
| Invalid HMAC | Request rejected and no business state changed |
paying callback |
Payment detected, fulfillment not started |
paid callback |
Fulfillment queued once |
Duplicate paid callback |
No duplicate fulfillment |
Unknown track_id
|
Operational case created |
| Provider timeout | Local failure visible and retry policy applied |
| Fulfillment failure | Payment remains paid and case is opened |
| Missed callback | Payment History recovery finds payment |
| Expired invoice | Order remains unresolved under merchant policy |
| Customer status page | Displays correct business state |
| Merchant export | Includes expected identifiers and amounts |
| Credential rotation | New key works and old access is removed |
Each result should have evidence.
Evidence can include:
- screenshot
- database record
- event ID
- test order
- sanitized API response
- log reference
- fulfillment record
“Tested successfully” without evidence is not a professional launch report.
Generate a launch report
The kit should generate a client-specific report.
launch:
merchant: Acme Software
environment: production
completed_at: 2026-07-28T09:30:00Z
integration:
mode: hosted_invoice
webhook_endpoint: configured
hmac_validation: passed
payment_history_recovery: enabled
acceptance_tests:
invoice_creation: passed
paying_does_not_fulfill: passed
paid_fulfills_once: passed
duplicate_callback: passed
recovery_job: passed
customer_status_page: passed
credentials:
owner: merchant
stored_in: managed_secret_vault
agency_access_expires: 2026-08-11
handoff:
merchant_admin_trained: true
support_sop_delivered: true
escalation_contacts_confirmed: true
This report protects both the merchant and the agency.
Build the handoff package
The merchant should receive a package containing:
Payment-flow summary
Customer creates order
-> OxaPay invoice created
-> Customer pays
-> Payment callback verified
-> Order marked paid
-> Fulfillment begins
Dashboard guide
Explain:
- how to find an order
- how to search by
track_id - how to identify
paying,paid, andexpired - how to find a failed fulfillment
- how to export records
Support SOP
Cover at least:
- customer says payment was sent
- payment is still confirming
- invoice expired
- payment is underpaid
- payment is paid but order is pending
- fulfillment failed
- customer paid twice
- payment cannot be found
Credential register
Record:
- account owner
- Merchant API Key owner
- storage location
- agency access
- rotation process
- emergency revocation process
Do not include raw credentials in the handoff document.
Responsibility matrix
| Activity | Merchant | Agency | Payment provider |
|---|---|---|---|
| OxaPay account ownership | Responsible | Consulted | Support |
| Merchant API Key creation | Responsible | Consulted | Provides system |
| Integration deployment | Consulted | Responsible | Not responsible |
| Customer-order support | Responsible | Escalation support | Payment evidence |
| Application fulfillment | Accountable | Implementation support | Not responsible |
| Callback delivery | Informed | Monitors endpoint | Responsible for sending |
| Recovery job | Informed | Responsible during contract | Provides API |
| Refund policy | Responsible | Not legal owner | Executes supported operations |
Ownership should be agreed before launch.
Define post-launch support
Every launch should have a monitoring window.
For example:
Launch day:
Review real transaction and callback health
First 72 hours:
Daily unresolved-case review
First 14 days:
Monitor webhook errors, fulfillment failures, and support issues
After monitoring period:
Move to merchant operation or maintenance plan
The agency contract should state:
- monitoring duration
- support hours
- incident channels
- response targets
- included changes
- excluded changes
- credential-access expiry
- maintenance price
Without this boundary, a one-time launch project can become unlimited operational support.
Version client configurations
Merchant requirements change.
A client may:
- add another currency
- change checkout mode
- add a new fulfillment adapter
- rotate credentials
- change callback domains
- update support ownership
Do not edit production configuration without version history.
Manifest version 1
-> Hosted invoice and email delivery
Manifest version 2
-> Add customer status page
Manifest version 3
-> Add white-label checkout
Every change should record:
- requester
- approver
- implementation date
- test evidence
- rollback plan
The Launch Kit should standardize change management, not only initial deployment.
Build the agency portal later
The first version can be a repository, templates, and a managed implementation process.
An agency portal becomes useful after several deployments share the same needs.
Possible portal features:
- merchant onboarding
- manifest management
- encrypted credential storage
- integration-track selection
- launch-check progress
- webhook-health monitoring
- client-specific dashboards
- support-case routing
- report generation
- handoff-package generation
- configuration versioning
- agency staff permissions
Do not build the portal before the delivery process is proven manually.
Software should automate a stable process, not hide an undefined one.
Product packaging
Plugin Launch
For merchants using supported platforms.
Includes:
- compatibility review
- plugin installation
- API configuration
- checkout test
- order-status test
- support guide
- handoff
- short monitoring period
Custom Invoice Launch
For custom stores, SaaS apps, and client portals.
Includes:
- local payment session
- hosted invoice
- signed webhook processing
- order adapter
- Payment Information refresh
- Payment History recovery
- status page
- acceptance testing
White-Label Launch
For premium branded checkout.
Includes everything in Custom Invoice Launch plus:
- embedded payment UI
- network instructions
- QR and address display
- expiry handling
- custom payment states
- UX testing
Agency Platform
For agencies with several merchant clients.
Includes:
- multi-client configuration
- tenant isolation
- webhook monitoring
- reusable adapters
- launch reports
- handoff generation
- role-based access
- maintenance workflow
The commercial value increases with operational responsibility, not only code quantity.
The MVP
The first version of the Launch Kit should support two tracks:
Plugin deployment
Hosted invoice deployment
Build:
- client qualification scorecard
- discovery questionnaire
- decision tree
- implementation manifest
- one plugin deployment guide
- one custom invoice module
- merchant-specific webhook endpoint
- HMAC validation
- payment-event storage
- idempotent fulfillment adapter
- Payment Information refresh
- Payment History recovery
- acceptance-test matrix
- launch report
- support SOP
- merchant handoff template
- 14-day monitoring plan
Do not include initially:
- every OxaPay plugin
- every programming framework
- custom payout systems
- full agency SaaS portal
- advanced accounting
- legal or tax automation
- unlimited merchant customization
- dozens of dashboard roles
Prove that the same delivery system can launch two similar clients successfully.
Common mistakes
Selling only code
Agencies need scope, testing, documentation, and support boundaries.
Rebuilding a plugin unnecessarily
Use an existing plugin when it fully satisfies the merchant workflow.
Treating every merchant the same
Hosted checkout, white-label checkout, and account funding have different risks and scopes.
Starting implementation before discovery
Undefined fulfillment and support ownership create production incidents later.
Fulfilling inside the callback request
Persist the event and execute business actions asynchronously.
Returning success before durable storage
Do not acknowledge a callback that can disappear before processing.
Testing only the happy path
Duplicate events, invalid signatures, missed callbacks, and fulfillment failures are normal production concerns.
Giving the agency permanent credential access
Define who owns credentials and when agency access should end.
Handing over without support procedures
The merchant will otherwise send every payment question back to the agency.
Offering unlimited customization
Keep the core stable and charge separately for client-specific adapters.
Security baseline
Every custom deployment should include:
- HTTPS callbacks
- raw-body HMAC validation
- timing-safe comparison
- merchant-specific credentials
- encrypted secret storage
- tenant isolation
- test and production separation
- payment-event deduplication
- fulfillment idempotency
- transactional outbox
- Payment Information verification
- Payment History recovery
- role-based dashboard access
- manual-action audit logs
- credential-rotation process
- secret masking
- post-handoff access review
- incident alerting
The agency should be able to prove these controls were tested.
What makes this a real developer product?
A normal integration project says:
Connect API
-> Create payment
-> Receive webhook
-> Update order
A Merchant Crypto Launch Kit says:
Qualify merchant
-> Discover operational requirements
-> Select correct implementation track
-> Approve project boundary
-> Configure versioned deployment manifest
-> Deploy reusable runtime
-> Test payment and failure paths
-> Capture launch evidence
-> Train merchant team
-> Transfer ownership
-> Monitor production
-> Manage future changes safely
That is the difference between performing integrations and building an agency delivery product.
Final takeaway
Agencies do not need another collection of payment snippets.
They need a repeatable system for delivering crypto payment projects without recreating decisions, code, testing, documentation, and support processes for every client.
OxaPay provides the payment primitives:
- hosted invoices
- white-label payments
- static addresses
- unique
track_idreferences - signed callbacks
- Payment Information
- Payment History
- plugins
- SDKs
- automation integrations
- optional payout APIs
The Launch Kit provides the agency layer:
- qualification
- discovery
- architecture selection
- reusable implementation
- merchant adapters
- acceptance testing
- launch evidence
- handoff
- responsibility assignment
- production monitoring
- change management
Start with one agency type.
Support two implementation tracks.
Launch one client through a plugin.
Launch another through a custom hosted invoice.
Document every decision.
Test every failure path.
Make ownership explicit.
That is how one-off crypto payment work becomes a repeatable agency product.
Which agency would you build for first: ecommerce, hosting, SaaS, digital products, or creator communities?
Related articles
- 10 Crypto Payment Products Developers Can Build for Merchants
- Build a Crypto PaymentOps Service for Merchants
- Build a Vertical Crypto Checkout for Hosting Providers
- Build a Telegram Paid Access System with Crypto Payments
- Build a Crypto Revenue Split and Payout System for Merchants
- Build a Crypto Payment Reconciliation Tool for Merchants
- Build a Payment Automation Studio for Crypto Merchants
- Build a Crypto Payment Module for SaaS Apps
- Build a Crypto Payment Support Desk
- Build a Cross-Border Crypto Payment Stack for Digital Sellers
References
OxaPay API
- OxaPay Generate Invoice
- OxaPay Generate White Label
- OxaPay Generate Static Address
- OxaPay Payment Information
- OxaPay Payment History
- OxaPay Payment Status Table
- OxaPay Webhook
Top comments (0)