# API keys and scopes Source: https://docs.meum.io/api-reference/api-keys-and-scopes Bearer authentication and scopes for Public Merchant API v1. ## Authentication ``` Authorization: Bearer sk_live_... ``` * Store-scoped: one store per key * Hashed at rest (SHA-256); prefix `sk_live_` with first 12 chars shown in dashboard * Cannot access Merchant Admin session APIs Create keys in [Get API credentials](/getting-started/get-api-credentials). ## Default developer scopes | Scope | Access | | -------------------------------------------- | ---------------------------------- | | `invoices:read` | List and read invoices | | `invoices:write` | Create and cancel invoices | | `transactions:read` | Read on-chain payment transactions | | `payment_links:read` / `payment_links:write` | Payment links | | `webhooks:read` / `webhooks:write` | Webhook endpoints and deliveries | Use `transactions:read` (not legacy `payments:read`). ## WooCommerce keys | Key | Scopes | Use | | --------- | ---------------------------------------------- | ---------------------------- | | Bootstrap | `woocommerce:bootstrap` | Connect only (24h) | | Dedicated | `invoices:create`, `invoices:read`, Woo scopes | Plugin runtime (auto-issued) | Dedicated keys cannot access payment links, transaction list, or developer webhook management. ## Scope errors HTTP `403`: ```json theme={null} { "error": { "type": "permission_error", "code": "INSUFFICIENT_SCOPE", "message": "Missing transactions:read scope" } } ``` ## Related pages * [API key security](/security/api-key-security) * [Authentication errors](/api-reference/errors) # Customers Source: https://docs.meum.io/api-reference/customers Customer domain status for Public Merchant API v1. ## Public Customer API (not available) Meum does **not** expose `/v1/customers` in Public Merchant API v1. ### What to use instead * Pass customer context in invoice `metadata` or Woo `external_order_id`. * Use **Merchant Admin** for wallet-based customer analytics (dashboard session only). ### Planned domain (not in v1) A future Customer API may support store-scoped external customer IDs, separate from payer wallet addresses. # Errors Source: https://docs.meum.io/api-reference/errors HTTP error codes and error response format. ## Error response format ```json theme={null} { "error": "Human-readable message", "code": "MACHINE_READABLE_CODE" } ``` The `code` field is present for structured errors but may be omitted for simple validation failures. ## Common HTTP status codes | Status | Meaning | | ------ | --------------------------------------------------------- | | 400 | Validation error, missing payout wallet, bad request body | | 401 | Missing or invalid API key | | 403 | Insufficient scope or store mismatch | | 404 | Resource not found | | 409 | External order ID conflict | | 429 | Rate limit exceeded | | 500 | Internal server error | ## Error codes | Code | Description | | ------------------------------------- | ------------------------------------------ | | `BOOTSTRAP_KEY_INVOICE_FORBIDDEN` | Connection key used for invoice creation | | `EXTERNAL_ORDER_INTEGRATION_CONFLICT` | Order ID belongs to another integration | | `INSUFFICIENT_SCOPE` | API key lacks required scope | | `SITE_ALREADY_CONNECTED` | Woo site bound to another store | | `INTEGRATION_NOT_FOUND` | Woo integration not found on disconnect | | `CURRENCY_NOT_ALLOWED` | Invoice currency not in merchant allowlist | ## Related pages * [Common API errors](/troubleshooting/common-api-errors) # Health check Source: https://docs.meum.io/api-reference/health/health-check /openapi.yaml get /health # Idempotency Source: https://docs.meum.io/api-reference/idempotency Idempotent invoice creation behavior. ## Invoice creation `POST /v1/invoices` is idempotent on `(store_id, external_order_id)`: * Existing match → returns the same invoice with HTTP `201` * Same `external_order_id` on a **different** Woo integration → HTTP `409` (`EXTERNAL_ORDER_INTEGRATION_CONFLICT`) ## Webhook deliveries Dedupe on `X-Meum-Event-Id`. See [Webhooks overview](/webhooks/overview). # Connect WooCommerce Source: https://docs.meum.io/api-reference/integrations/connect-woocommerce /openapi.yaml post /v1/integration/woocommerce/connect Registers or reconnects a WooCommerce store. Returns a dedicated API key and webhook secret. Uses legacy error shape on some failures. # Disconnect WooCommerce Source: https://docs.meum.io/api-reference/integrations/disconnect-woocommerce /openapi.yaml post /v1/integration/woocommerce/disconnect Requires a WooCommerce dedicated API key. # Get WooCommerce integration status Source: https://docs.meum.io/api-reference/integrations/get-woocommerce-integration-status /openapi.yaml get /v1/integration/woocommerce/status # Overview Source: https://docs.meum.io/api-reference/invoices Create, list, retrieve, poll status, and cancel invoices via Public Merchant API v1. All invoice IDs use opaque `inv_` tokens. Internal UUIDs are never returned. ## Authentication ``` Authorization: Bearer sk_live_... ``` ## Create invoice `POST /v1/invoices` | | | | --------------- | --------------------------- | | **Scope** | `invoices:write` | | **Idempotency** | Not supported on this route | | **Rate limit** | Write bucket (`enforce`) | ### Request body | Field | Required | Validation | | ------------------- | -------- | ------------------------------------------------- | | `amount` | Yes | Decimal string, settlement amount | | `currency` | Yes | ISO currency code | | `external_order_id` | No | Merchant reference | | `callback_url` | No | HTTPS webhook target (developer keys) | | `return_url` | No | Buyer redirect after payment | | `metadata` | No | JSON object; sensitive keys stripped in responses | ### Response `201` Returns `id` (`inv_...`), `status`, `checkout_url`, `amount`, `currency`, `output_asset`, `expires_at`. ### Errors | Code | HTTP | When | | ------------------------------ | ---- | ----------------------------- | | `INSUFFICIENT_SCOPE` | 403 | Missing `invoices:write` | | `payout_wallet_not_configured` | 400 | Store payout not set | | `store_mismatch` | 403 | `store_id` does not match key | ### Webhooks `invoice.created` when the invoice is persisted. ### Examples ```bash theme={null} curl -X POST https://api.meum.io/v1/invoices \ -H "Authorization: Bearer sk_live_EXAMPLE" \ -H "Content-Type: application/json" \ -d '{"amount":"99.00","currency":"USD","external_order_id":"order-1001"}' ``` ```javascript theme={null} const res = await fetch("https://api.meum.io/v1/invoices", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount: "99.00", currency: "USD" }), }); ``` ```php theme={null} $ch = curl_init("https://api.meum.io/v1/invoices"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer sk_live_EXAMPLE", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["amount" => "99.00", "currency" => "USD"]), CURLOPT_RETURNTRANSFER => true, ]); ``` ### Security Never log full API keys. `checkout_url` is buyer-facing; do not embed secrets in metadata. *** ## List invoices `GET /v1/invoices` | | | | -------------- | --------------------------------------------------- | | **Scope** | `invoices:read` | | **Pagination** | Cursor (`limit`, `starting_after`, `ending_before`) | | **Rate limit** | Read bucket (`observe`) | Query: `status`, `external_order_id`, `payment_link_id` (`plink_...`). *** ## Retrieve invoice `GET /v1/invoices/{id}` | | | | ------------- | ---------------------- | | **Scope** | `invoices:read` | | **Path `id`** | `inv_...` public token | Response uses snake\_case. Money fields are strings. *** ## Poll status `GET /v1/invoices/{id}/status` Lightweight status for hosted checkout polling. May include `deposit_address`, `swap_status`, and `return_url` when applicable. *** ## Cancel invoice `POST /v1/invoices/{id}/cancel` | | | | --------- | ---------------- | | **Scope** | `invoices:write` | Only open invoices (`awaiting_payment`, `quoted`, etc.) can be cancelled. Emits `invoice.cancelled` webhook. # Cancel invoice Source: https://docs.meum.io/api-reference/invoices/cancel-invoice /openapi.yaml post /v1/invoices/{id}/cancel Cancels an open invoice. Not available for WooCommerce dedicated keys. # Create invoice Source: https://docs.meum.io/api-reference/invoices/create-invoice /openapi.yaml post /v1/invoices Creates a new checkout invoice for the authenticated store. Returns a legacy error shape on some validation failures for backward compatibility. # Get invoice Source: https://docs.meum.io/api-reference/invoices/get-invoice /openapi.yaml get /v1/invoices/{id} # Get invoice status Source: https://docs.meum.io/api-reference/invoices/get-invoice-status /openapi.yaml get /v1/invoices/{id}/status Lightweight status poll including deposit details and swap processing state. # List invoice transactions Source: https://docs.meum.io/api-reference/invoices/list-invoice-transactions /openapi.yaml get /v1/invoices/{id}/transactions # List invoices Source: https://docs.meum.io/api-reference/invoices/list-invoices /openapi.yaml get /v1/invoices Returns invoices for the authenticated store with cursor pagination. Results are ordered by creation time descending (newest first). Date filters default to a 90-day window when not specified. # API overview Source: https://docs.meum.io/api-reference/overview Public Meum Merchant API v1. Integrate without the Dashboard. ## Base URL ``` https://api.meum.io ``` ## Authentication Store-scoped API key: `Authorization: Bearer sk_live_...` See [API keys and scopes](/api-reference/api-keys-and-scopes). List endpoints use cursor pagination (`cursor`, `limit`). See OpenAPI per route. ## Public resource IDs Merchant API responses use prefixed opaque IDs, never internal UUIDs: | Prefix | Resource | | ----------------------- | -------------------------------------- | | `inv_` | Invoice | | `txn_` | Payment transaction | | `plink_` | Payment link (merchant API) | | `plpub_` | Payment link buyer URL / public routes | | `wh_` / `whd_` / `evt_` | Webhook endpoint / delivery / event | | `int_` | Integration | Tokens are **32 lowercase hex characters** after the prefix (128-bit). See [Payment Links API](/api-reference/payment-links) for `plink_` vs `plpub_`. ## Domains | Domain | Prefix | Description | | ------------- | ----------------------------- | --------------------------------------- | | Invoices | `/v1/invoices` | Create, list, read, cancel, poll status | | Transactions | `/v1/transactions` | Read-only on-chain payment ledger | | Payment Links | `/v1/payment-links` | Create and manage pay links (API key) | | Webhooks | `/v1/webhook-endpoints` | Developer webhook endpoint management | | Integrations | `/v1/integration/woocommerce` | WooCommerce connect, disconnect, status | ## Public merchant endpoints (summary) | Method | Path | Scope | | --------------------- | ---------------------------------------- | ------------------------ | | GET | `/health` | None | | GET | `/v1/invoices` | `invoices:read` | | POST | `/v1/invoices` | `invoices:write` | | GET | `/v1/invoices/{id}` | `invoices:read` | | GET | `/v1/invoices/{id}/status` | `invoices:read` | | POST | `/v1/invoices/{id}/cancel` | `invoices:write` | | GET | `/v1/invoices/{id}/transactions` | `transactions:read` | | GET | `/v1/transactions` | `transactions:read` | | GET | `/v1/transactions/{id}` | `transactions:read` | | GET | `/v1/transactions/by-hash/{hash}` | `transactions:read` | | POST | `/v1/payment-links` | `payment_links:write` | | GET | `/v1/payment-links` | `payment_links:read` | | GET/PATCH | `/v1/payment-links/{id}` | read/write | | POST | `/v1/payment-links/{id}/activate` | `payment_links:write` | | POST | `/v1/payment-links/{id}/deactivate` | `payment_links:write` | | POST | `/v1/integration/woocommerce/connect` | `woocommerce:connect` | | POST | `/v1/integration/woocommerce/disconnect` | `woocommerce:disconnect` | | GET | `/v1/integration/woocommerce/status` | API key (store) | | POST/GET/PATCH/DELETE | `/v1/webhook-endpoints` | `webhooks:*` | Full schemas: OpenAPI reference generated from `openapi.yaml`. ## Browser-facing (not API key management) These routes are for checkout UIs, not server integration: * `/v1/checkout/*`: Hosted checkout session * `/v1/public/payment-links/*`: Buyer pay-link page and checkout ## Not in public API * Merchant Admin session APIs (JWT login at app.meum.io) * `/v1/customers`: **Not available** (see [Customers](/api-reference/customers)) ## Examples ### List invoices (cURL) ```bash theme={null} curl "https://api.meum.io/v1/invoices?status=paid&limit=20" \ -H "Authorization: Bearer sk_live_EXAMPLE_DO_NOT_USE" ``` ### Create payment link with idempotency (Node.js) ```javascript theme={null} const response = await fetch("https://api.meum.io/v1/payment-links", { method: "POST", headers: { Authorization: "Bearer sk_live_EXAMPLE_DO_NOT_USE", "Content-Type": "application/json", "Idempotency-Key": "plink-create-order-1048-v1", }, body: JSON.stringify({ title: "Consulting fee", amount_mode: "fixed_amount", amount: "250.00", allow_multiple_payments: false, }), }); ``` ### WooCommerce status (PHP) ```php theme={null} $response = wp_remote_get('https://api.meum.io/v1/integration/woocommerce/status', [ 'headers' => ['Authorization' => 'Bearer ' . $api_key], 'timeout' => 15, ]); $status = json_decode(wp_remote_retrieve_body($response), true); ``` # Overview Source: https://docs.meum.io/api-reference/payment-links Merchant `plink_` management and buyer `plpub_` checkout routes. Payment links use two ID namespaces: | Prefix | Use | | -------- | -------------------------------------- | | `plink_` | Merchant API resource id | | `plpub_` | Buyer-facing URL token (public routes) | ### Public ID format All public resource IDs use opaque prefixes plus a **32-character lowercase hex** token (128-bit entropy): | Prefix | Example | | -------- | ---------------------------------------- | | `inv_` | `inv_cb1e73f508a2abf4ea639f100de14cef` | | `plink_` | `plink_961544395accbc1e00c56bbdaa4f07da` | | `plpub_` | `plpub_c9a9bb730611077574c828af5af5fed1` | Legacy **12-character** `plpub_` URLs (issued before June 2026) still resolve; the API returns the current 32-char `public_id` in responses. Buyer responses omit internal UUIDs, settlement wallets, and webhook configuration. ## Authentication (merchant routes) ``` Authorization: Bearer sk_live_... ``` Buyer routes under `/v1/public/payment-links/*` require **no API key**. *** ## Create payment link `POST /v1/payment-links` | | | | --------------- | ---------------------------------- | | **Scope** | `payment_links:write` | | **Idempotency** | `Idempotency-Key` header supported | | **Rate limit** | Write bucket | ### Request | Field | Notes | | --------------------------- | ------------------------------------------- | | `amount_mode` | `fixed_amount` or `customer_defined_amount` | | `amount` | Required for fixed mode (string) | | `min_amount` / `max_amount` | Customer-defined mode | | `allow_multiple_payments` | `true` = reusable; `false` = single-use | ### Response `201` `id` (`plink_...`), `public_id` (`plpub_...`), `public_url`, pricing fields, `usage` (`reusable` / `single_use`). *** ## Retrieve / update `GET` / `PATCH /v1/payment-links/{id}` Path id must be `plink_...`. PATCH cannot change pricing after checkout has started. *** ## Activate / deactivate `POST /v1/payment-links/{id}/activate`\ `POST /v1/payment-links/{id}/deactivate` Scope: `payment_links:write`. *** ## Public buyer link `GET /v1/public/payment-links/{public_id}` | | | | -------- | --------------------- | | **Auth** | None (`security: []`) | | **Path** | `plpub_...` | Returns buyer-safe fields only: title, amounts, `store_name`, `merchant_name`. **Does not** expose store UUID, organization id, settlement wallet, webhooks, merchant email, or `store_logo_url` (CDN paths may embed org ids). ### cURL ```bash theme={null} curl "https://api.meum.io/v1/public/payment-links/plpub_c9a9bb730611077574c828af5af5fed1" ``` *** ## Start checkout `POST /v1/public/payment-links/{public_id}/checkout` | | | | -------------- | ------------------ | | **Auth** | None | | **Rate limit** | Per `plpub_` token | ### Request ```json theme={null} { "amount": "42.50", "origin_asset": "usdc.near", "refund_to": "alice.near" } ``` * **Fixed amount:** omit `amount`. * **Customer-defined:** `amount` required within min/max. * **Single-use:** reuses open invoice when present; returns `403` when already paid. ### Response `201` ```json theme={null} { "invoice_id": "inv_...", "checkout_url": "https://pay.meum.io/...", "reused": false } ``` ### Security Buyer routes are unauthenticated; rely on rate limits and opaque `plpub_` tokens. Never embed `plink_` merchant ids in public pages. # Activate payment link Source: https://docs.meum.io/api-reference/payment-links/activate-payment-link /openapi.yaml post /v1/payment-links/{id}/activate # Create payment link Source: https://docs.meum.io/api-reference/payment-links/create-payment-link /openapi.yaml post /v1/payment-links # Deactivate payment link Source: https://docs.meum.io/api-reference/payment-links/deactivate-payment-link /openapi.yaml post /v1/payment-links/{id}/deactivate # Get buyer-facing payment link Source: https://docs.meum.io/api-reference/payment-links/get-buyer-facing-payment-link /openapi.yaml get /v1/public/payment-links/{public_id} Public endpoint for hosted pay-link pages. No API key required. Use the `plpub_` token from the merchant payment link `public_id` field. # Get payment link Source: https://docs.meum.io/api-reference/payment-links/get-payment-link /openapi.yaml get /v1/payment-links/{id} # List payment link invoices Source: https://docs.meum.io/api-reference/payment-links/list-payment-link-invoices /openapi.yaml get /v1/payment-links/{id}/invoices # List payment link transactions Source: https://docs.meum.io/api-reference/payment-links/list-payment-link-transactions /openapi.yaml get /v1/payment-links/{id}/transactions # List payment links Source: https://docs.meum.io/api-reference/payment-links/list-payment-links /openapi.yaml get /v1/payment-links # Start payment link checkout Source: https://docs.meum.io/api-reference/payment-links/start-payment-link-checkout /openapi.yaml post /v1/public/payment-links/{public_id}/checkout Creates or reuses an invoice for this payment link and returns a hosted checkout URL. No API key required. Rate limited per buyer token. **Fixed amount:** omit `amount` when the link uses `fixed_amount` mode. **Customer-defined amount:** send `amount` as a decimal string within the link min/max. **Single-use links:** a second checkout reuses the open invoice when one exists; paid single-use links return `403`. # Update payment link Source: https://docs.meum.io/api-reference/payment-links/update-payment-link /openapi.yaml patch /v1/payment-links/{id} Pricing fields cannot be changed after a checkout has started. # Rate limits Source: https://docs.meum.io/api-reference/rate-limits API rate limiting for public endpoints. ## Overview Rate limits vary by endpoint and account. When a limit is exceeded, the API returns HTTP **429** with a `Retry-After` header (seconds). Meum may apply different limits to authentication, checkout, invoice creation, integrations, and dashboard operations. Exact thresholds are not published as a fixed contract while limits are being calibrated on some routes. ## Rate limit response When a limit is enforced: ```http theme={null} HTTP/1.1 429 Too Many Requests Retry-After: 60 Content-Type: application/json ``` ```json theme={null} { "error": "too_many_requests", "message": "Too many requests. Please try again later.", "retry_after_seconds": 60 } ``` Some routes may still be in observe-only mode during calibration and will not return 429 until limits are finalized. ## Integration guidance * Retry idempotent reads with exponential backoff when you receive 429. * Use `Idempotency-Key` on dashboard payment link creation where supported. * WooCommerce invoice creation is deduplicated by `external_order_id` per store. Retries with the same order ID return the existing invoice when possible. * If multiple integrations share one egress IP, coordinate request volume; per-API-key accounting may apply on some routes. ## Related pages * [Common API errors](/troubleshooting/common-api-errors) * [Idempotency](/api-reference/idempotency) (if documented) # Overview Source: https://docs.meum.io/api-reference/transactions Read-only access to on-chain payment transactions. Transaction IDs use `txn_...` opaque tokens. ## Authentication ``` Authorization: Bearer sk_live_... ``` **Scope:** `transactions:read` (legacy `payments:read` is no longer accepted). *** ## List transactions `GET /v1/transactions` Cursor pagination. Optional filters: `invoice_id` (`inv_...`), `type`, `status`. Rate limit: read bucket (`observe`). *** ## Retrieve transaction `GET /v1/transactions/{id}` Path id: `txn_...`. *** ## Lookup by hash `GET /v1/transactions/by-hash/{transactionHash}` On-chain hash lookup within the store scope. *** ## Invoice transactions `GET /v1/invoices/{id}/transactions` Lists transactions linked to invoice `inv_...`. Requires `transactions:read`. ### Example (Node.js) ```javascript theme={null} const res = await fetch( `https://api.meum.io/v1/invoices/${invoiceId}/transactions`, { headers: { Authorization: `Bearer ${apiKey}` } } ); ``` Money fields (`amount`) are always strings in JSON responses. # Get transaction Source: https://docs.meum.io/api-reference/transactions/get-transaction /openapi.yaml get /v1/transactions/{id} # Get transaction by hash Source: https://docs.meum.io/api-reference/transactions/get-transaction-by-hash /openapi.yaml get /v1/transactions/by-hash/{transactionHash} # List transactions Source: https://docs.meum.io/api-reference/transactions/list-transactions /openapi.yaml get /v1/transactions Returns payment transactions for the authenticated store with cursor pagination. # Overview Source: https://docs.meum.io/api-reference/webhooks-api Developer webhook endpoints, deliveries, and signature verification. Scopes: `webhooks:read`, `webhooks:write`. ## Create endpoint `POST /v1/webhook-endpoints`: returns `wh_...` and a **one-time** `secret`. * HTTPS URL required * Default events: `invoice.created`, `invoice.paid`, `invoice.expired`, `invoice.failed` ## Deliveries * `GET /v1/webhook-endpoints/{id}/deliveries`: `whd_...` attempts * `GET /v1/webhook-deliveries/{id}`: detail Retries, ordering, and deduplication: [Webhooks overview](/webhooks/overview). ## Verify inbound webhooks See [Verify signatures](/webhooks/verify-signatures). Payload IDs use `inv_...` and `evt_...`: [Event reference](/webhooks/event-reference). # Create webhook endpoint Source: https://docs.meum.io/api-reference/webhooks/create-webhook-endpoint /openapi.yaml post /v1/webhook-endpoints Creates a developer-managed webhook endpoint. The signing secret is returned once in the response and cannot be retrieved again. # Delete webhook endpoint Source: https://docs.meum.io/api-reference/webhooks/delete-webhook-endpoint /openapi.yaml delete /v1/webhook-endpoints/{id} Soft-deletes (archives) the endpoint. Managed webhooks cannot be deleted. # Get webhook delivery Source: https://docs.meum.io/api-reference/webhooks/get-webhook-delivery /openapi.yaml get /v1/webhook-deliveries/{id} # Get webhook endpoint Source: https://docs.meum.io/api-reference/webhooks/get-webhook-endpoint /openapi.yaml get /v1/webhook-endpoints/{id} # List webhook deliveries Source: https://docs.meum.io/api-reference/webhooks/list-webhook-deliveries /openapi.yaml get /v1/webhook-endpoints/{id}/deliveries # List webhook endpoints Source: https://docs.meum.io/api-reference/webhooks/list-webhook-endpoints /openapi.yaml get /v1/webhook-endpoints # Send test webhook Source: https://docs.meum.io/api-reference/webhooks/send-test-webhook /openapi.yaml post /v1/webhook-endpoints/{id}/test Dispatches a `webhook.test` event to the endpoint. Rate limited. # Update webhook endpoint Source: https://docs.meum.io/api-reference/webhooks/update-webhook-endpoint /openapi.yaml patch /v1/webhook-endpoints/{id} Managed (integration-owned) webhooks cannot be modified via this API. # Overview Source: https://docs.meum.io/api-reference/woocommerce-api Connect, disconnect, status, and invoice → webhook → order completion flow. ## Authentication WooCommerce connect uses a bootstrap or reconnect key. After connect, the plugin uses a **dedicated integration key** with Woo-only scopes. *** ## Connect `POST /v1/integration/woocommerce/connect` | | | | --------- | ------------------------------------------------ | | **Scope** | `woocommerce:connect` (bootstrap/reconnect keys) | Returns dedicated `api_key`, `webhook_secret`, and `integration_public_id` (`int_...`). ### Security Store webhook secret in WordPress options only. Never expose in frontend. *** ## Disconnect `POST /v1/integration/woocommerce/disconnect` Scope: `woocommerce:disconnect`. *** ## Status `GET /v1/integration/woocommerce/status` Returns connection state, payout readiness, and `integration_public_id` (`int_...`). *** ## Invoice → webhook → `payment_complete()` flow 1. Woo plugin creates invoice via dedicated key (`invoices:create`). 2. Buyer pays on hosted checkout. 3. Meum delivers `invoice.paid` with `X-Meum-*` headers. 4. Plugin verifies signature, `X-Meum-Integration-Id` (`int_...`), and timestamp. 5. Handler calls `$order->payment_complete()` once per `X-Meum-Event-Id`. 6. Duplicate events return `{ "duplicate": true }` without re-running payment actions. ### Security notes * Reject webhooks when integration id does not match stored `int_...` * Do not replay production webhook payloads in test environments without proper isolation # Accept your first payment Source: https://docs.meum.io/getting-started/accept-first-payment Create an invoice and complete a test payment. ## Prerequisites * Settlement wallet configured * Store-scoped API key with `invoices:write` scope (default for developer keys) ## Steps 1. Create an invoice: ```bash theme={null} curl -X POST https://api.meum.io/v1/invoices \ -H "Authorization: Bearer sk_live_EXAMPLE_DO_NOT_USE" \ -H "Content-Type: application/json" \ -d '{ "external_order_id": "demo_order_001", "amount": "10.00", "currency": "USD", "return_url": "https://example.com/thank-you" }' ``` 2. Open the `checkout_url` from the response (e.g. `https://pay.meum.io/inv_a1b2c3d4…`) 3. Select a payment token and enter a refund address 4. Complete the on-chain payment (or use dev simulation if available in your environment) 5. Poll status or wait for webhook: ```bash theme={null} curl https://api.meum.io/v1/invoices/inv_a1b2c3d4…/status \ -H "Authorization: Bearer sk_live_EXAMPLE_DO_NOT_USE" ``` ## Expected result Invoice status transitions to `paid`. Webhook `invoice.paid` is delivered if configured. ## Related pages * [Invoices API](/api-reference/invoices) * [Webhooks overview](/webhooks/overview) # Configure settlement wallet Source: https://docs.meum.io/getting-started/configure-settlement-wallet Set the wallet where Meum sends settled stablecoin payments. Invoice creation returns HTTP 400 `payout_wallet_not_configured` until a settlement wallet is set. Never share seed phrases or private keys. Meum only needs your **public wallet address**. ## Steps 1. **Dashboard → Account → Organization settlement** (org default), or 2. **Dashboard → Stores → \[Store] → Settings** (per-store override) 3. Set payout address and output asset (USDC/USDT) 4. Save **Tips:** Verify the address carefully; use a dedicated settlement wallet; test with a small payment first. ## Settlement logs View per-invoice settlement status in **Dashboard → invoice detail**. Settlement retry is handled by Meum operations: not available via public API. Email alerts: **Dashboard → Notifications**. ## Troubleshooting * [Invalid settlement wallet](/troubleshooting/invalid-settlement-wallet) # Create an account Source: https://docs.meum.io/getting-started/create-account Register and set up your Meum organization. ## Steps 1. Go to [app.meum.io/register](https://app.meum.io/register) 2. Sign up with email/password or Google OAuth (Google requires a verified email) 3. A default **organization** and **store** are created automatically 4. Log in at [app.meum.io](https://app.meum.io) Every new organization starts on the **Free** plan. Upgrade anytime from **Dashboard → Account → Plan & Billing**. See [Subscription plans](/getting-started/subscription-plans). Registration may require reCAPTCHA when enabled on the platform. ## Organization settings Manage at **Dashboard → Account → Organization**: * Default settlement wallet and output asset * Organization webhook (optional) * Team members Organizations with `SUSPENDED` platform access cannot use the dashboard or API. ## Next steps * [Create a store](/getting-started/create-store) if you need an additional sales channel * [Configure settlement wallet](/getting-started/configure-settlement-wallet) # Create a store Source: https://docs.meum.io/getting-started/create-store Create a Meum store for payments and integrations. A **store** represents a merchant storefront or sales channel. API keys, integrations, and invoices are scoped to a store. ## Prerequisites * Active Meum organization * Logged in to [app.meum.io](https://app.meum.io) ## Steps 1. Open **Dashboard → Stores** 2. Click **New store** 3. Enter store name and optional slug (public profile at `meum.io/@{slug}`) 4. Save the store ## Expected result A new store appears in your store list. You can switch between stores using the store selector in the dashboard header. Configure per-store **Checkout** settings (fee payer, timeout), **Storefront** branding (`meum.io/@{slug}`), and settlement wallet under **Dashboard → Stores → \[Store] → Settings**. ## Related pages * [Subscription plans](/getting-started/subscription-plans) * [Configure settlement wallet](/getting-started/configure-settlement-wallet) * [Get API credentials](/getting-started/get-api-credentials) # Get API credentials Source: https://docs.meum.io/getting-started/get-api-credentials Create store-scoped API keys and WooCommerce connection keys. ## Developer API key 1. Go to **Dashboard → API keys** (store-scoped) 2. Click **Create API key** 3. Copy the key immediately (shown only once (`sk_live_...`) Default scopes: `invoices:read`, `invoices:write`, `transactions:read`, `payment_links:read`, `payment_links:write`, `webhooks:read`, `webhooks:write`. | Key type | Scopes | Use | | ------------- | ---------------------------------------------- | ----------------------------- | | Developer key | See above | Custom integrations | | Woo bootstrap | `woocommerce:bootstrap` | Plugin connect only (24h TTL) | | Woo dedicated | `invoices:create`, `invoices:read`, Woo scopes | Auto-issued after connect | Use in requests: `Authorization: Bearer sk_live_...` against `https://api.meum.io`. ## WooCommerce connection key 1. **Dashboard → Integrations → WooCommerce** → generate connection key 2. Paste in the plugin connect flow, then see [WooCommerce configuration](/woocommerce/configuration) Bootstrap keys cannot create invoices. The plugin uses the dedicated key issued after connect. ## Related pages * [API keys and scopes](/api-reference/api-keys-and-scopes) * [API key security](/security/api-key-security) # Subscription plans Source: https://docs.meum.io/getting-started/subscription-plans Free, Growth, and Business plans — limits, platform fees, and billing. Meum offers three self-service plans. Limits and platform fee rates scale with your tier. View live pricing at **[meum.io/pricing](https://meum.io/pricing)**. ## Plans at a glance | Plan | Monthly price | Platform fee | Stores | Pay links / store | Staff | | ------------ | ------------- | ------------ | ------ | ----------------- | ---------- | | **Free** | \$0 | 1.80% | 1 | Plan limit | Owner only | | **Growth** | \$19 | 1.20% | 3 | Plan limit | Up to 5 | | **Business** | \$49 | 0.80% | 10 | Plan limit | Up to 15 | Exact limits are configured in platform settings and shown live on the pricing page and in **Dashboard → Account → Plan & Billing**. ## What's included on every plan * Hosted checkout on `pay.meum.io` * Multi-chain tokens and networks at checkout * USD-priced orders and invoices * USDC / USDT settlement to your configured wallet * Transparent platform and network fee quotes at checkout * Pay Links, WooCommerce plugin, REST API, and signed webhooks * Multi-store merchant workspace ## Platform fee payer Configure per store under **Dashboard → Stores → \[Store] → Settings → Checkout**: | Setting | Free | Growth / Business | | ----------------- | ------------- | --------------------------------- | | **Merchant pays** | Yes (default) | Yes | | **Customer pays** | No | Yes — fee added to checkout total | Network fees are always shown in the live checkout quote regardless of plan. ## Upgrade and billing 1. Open **Dashboard → Account → Plan & Billing** 2. Compare plans and choose Growth or Business 3. Pay with crypto via the same hosted checkout flow used for customer payments Annual prepay discounts may be available — shown in Plan & Billing when enabled. ## Related pages * [Create an account](/getting-started/create-account) * [Create a store](/getting-started/create-store) * [How Meum payments work](/introduction/how-payments-work) # How Meum payments work Source: https://docs.meum.io/introduction/how-payments-work End-to-end flow from invoice creation to merchant settlement. 1. **Merchant creates an invoice** via API, WooCommerce, or Pay Link 2. **Customer opens hosted checkout** at `pay.meum.io/inv_{publicId}` 3. **Customer selects origin token** and provides a refund address 4. **Checkout quote** shows order total, platform fee, network cost, and deposit address 5. **Customer confirms** and sends crypto to the deposit address 6. **Meum detects and validates** the payment 7. **Invoice status updates**: `paid`, `underpaid`, `failed`, or `expired` 8. **Webhook delivered** to your integration endpoint 9. **Settlement** sends USDC or USDT to your configured wallet ## Related pages * [Checkout fees](/payments/checkout-fees) * [Payment statuses](/payments/payment-statuses) * [Webhooks overview](/webhooks/overview) # Overview Source: https://docs.meum.io/introduction/introduction Accept crypto payments globally and receive settlement in USDC or USDT. Meum integrates into your store, Pay Links, and custom apps. Customers pay with BTC, ETH, SOL, and other supported tokens.
Meum crypto payments documentation Meum crypto payments documentation
## Start here Create a store, Pay Links, and WooCommerce checkout with no custom code required. Build with the merchant API, webhooks, and programmatic invoice creation. ## Products Shareable links to accept crypto payments anywhere. Customers pay at pay.meum.io and select a token at checkout. WordPress plugin with hosted checkout and automatic order updates. Signed invoice events for your backend or store integration. Free, Growth, and Business — limits, platform fees, and upgrades. # Create a Pay Link Source: https://docs.meum.io/payment-links/create-payment-link Create reusable or one-time Pay Links in Merchant Admin. Pay Links let customers pay without a full e-commerce integration. ## Prerequisites * Active store with settlement wallet configured * Logged in to [app.meum.io](https://app.meum.io) ## Steps 1. Go to **Dashboard → Pay Links** 2. Click **New Pay Link** 3. Configure: * **Title** and description * **Amount mode**: `fixed` or `customer` (customer enters amount) * **Fixed amount** and currency (if fixed mode) 4. Save ## Expected result A Pay Link with public URL `https://pay.meum.io/plpub_{publicId}` is created (`plpub_` followed by a 32-character hex token). ## Related pages * [Share Pay Links and storefront](/payment-links/share-and-storefront) * [Payment links API](/api-reference/payment-links) * [How Meum payments work](/introduction/how-payments-work) # Share Pay Links and storefront Source: https://docs.meum.io/payment-links/share-and-storefront URL, QR, embeds, and public storefront at meum.io/@your-store. Every Pay Link includes share tools in **Dashboard → Pay Links → \[Link] → Share**. ## Share methods | Method | Use case | | ----------------- | ----------------------------------------------- | | **Shareable URL** | Paste into email, chat, or social | | **QR code** | Download SVG for print, menus, or events | | **Embed button** | HTML snippet — primary, light, or dark variants | | **Amount widget** | iframe for customer-entered amount links | ## Public storefront Mark a Pay Link **public** to list it on your storefront at: ``` https://meum.io/@{store-slug} ``` Configure storefront branding under **Dashboard → Stores → \[Store] → Settings → Storefront**: * Logo and cover banner * Social links * Featured links and sort order ## Link modes | Mode | Behavior | | -------------- | ------------------------------------------- | | **Reusable** | Stays active for ongoing sales or donations | | **Single-use** | Closes after the first successful payment | ## Related pages * [Create a Pay Link](/payment-links/create-payment-link) * [Create a store](/getting-started/create-store) # Checkout fees Source: https://docs.meum.io/payments/checkout-fees Platform fees, network costs, and who pays at checkout. Before a customer confirms payment, hosted checkout on `pay.meum.io` shows a **live quote** with: * Order total (USD) * **Platform fee** — percentage on successful payment, based on your plan * **Network cost** — depends on token and network the customer selects There are no hidden fees after pay-in. ## Platform fee payer Set the default per store in **Dashboard → Stores → \[Store] → Settings → Checkout**: | Mode | Customer sees | Settlement | | ----------------- | ----------------------------- | ----------------------------------------------------------- | | **Merchant pays** | Listed order amount only | Platform fee deducted from settlement | | **Customer pays** | Order + platform fee in total | Customer pays listed amount; fee included in checkout total | **Free plan:** platform fee is paid by the merchant only. **Growth and Business** can pass the platform fee to the customer. ## Network fees Blockchain routing costs vary by origin token and network. Meum surfaces them in the quote before the customer confirms — not as a surprise after payment. ## Related pages * [Subscription plans](/getting-started/subscription-plans) * [How Meum payments work](/introduction/how-payments-work) * [Configure settlement wallet](/getting-started/configure-settlement-wallet) # Payment statuses Source: https://docs.meum.io/payments/payment-statuses Invoice and payment row status enums. See [How Meum payments work](/introduction/how-payments-work) for the end-to-end flow. ## Invoice statuses ``` pending | quoted | awaiting_payment | paid | underpaid | expired | failed | refunded | cancelled ``` **Open** (can still receive payment): `awaiting_payment`, `quoted`, `pending` **Terminal** (no further payment updates): `paid`, `underpaid`, `failed`, `expired`, `refunded`, `cancelled` ## Payment row statuses Tracks the on-chain payment record (separate from invoice status): | Status | Description | | ----------- | ------------------------------- | | `pending` | Detected, awaiting confirmation | | `completed` | Fully confirmed | | `underpaid` | Less than expected | | `overpaid` | More than expected | | `failed` | Payment failed | ## Webhook mapping | Invoice status | Event | Default subscription | | -------------- | ------------------- | ------------------------- | | (on create) | `invoice.created` | Yes | | `paid` | `invoice.paid` | Yes | | `underpaid` | `invoice.underpaid` | Yes | | `failed` | `invoice.failed` | Yes | | `expired` | `invoice.expired` | Yes | | `cancelled` | `invoice.cancelled` | Yes (Woo managed) | | `refunded` | `invoice.refunded` | No: platform polling only | ## Related pages * [Event reference](/webhooks/event-reference) * [Underpayment and overpayment](/payments/underpayment-and-overpayment) # Underpayment and overpayment Source: https://docs.meum.io/payments/underpayment-and-overpayment How Meum handles partial and excess payments. ## Underpayment When received amount is less than expected: * Invoice status → `underpaid` * Webhook → `invoice.underpaid` * WooCommerce order → `on-hold` with order note ## Overpayment Payment row status may be `overpaid` when received amount exceeds expected. Invoice handling depends on platform validation logic at detection time. Always verify webhook `received_amount`, `expected_amount`, and `difference_amount` fields rather than assuming full payment. ## Related pages * [Payment statuses](/payments/payment-statuses) * [Payment remains pending](/troubleshooting/payment-remains-pending) # API status Source: https://docs.meum.io/resources/api-status Check Meum API health and availability. ## Health endpoint ```bash theme={null} curl https://api.meum.io/health ``` Example response: ```json theme={null} { "status": "ok", "worker_heartbeat": { "status": "ok", "last_at": "2024-06-24T12:05:00.000Z" } } ``` ## Related pages * [API overview](/api-reference/overview) * [Contact support](/resources/contact-support) # Changelog Source: https://docs.meum.io/resources/changelog Updates to the Meum documentation site. ## July 2026 * Added [Subscription plans](/getting-started/subscription-plans) — Free, Growth, Business limits and billing * Added [Checkout fees](/payments/checkout-fees) — platform fee payer and transparent quotes * Added [Share Pay Links and storefront](/payment-links/share-and-storefront) * Fixed WooCommerce plugin ZIP filename (`meum-crypto-payments-for-woocommerce.zip`) * Redirects for removed URLs: `/introduction/supported-payment-flow`, `/woocommerce/troubleshooting` * Contact email: **[support@meum.io](mailto:support@meum.io)** ## Earlier Documentation migrated to Mintlify at [docs.meum.io](https://docs.meum.io). # Contact support Source: https://docs.meum.io/resources/contact-support Get help with Meum integration and account issues. ## Email [support@meum.io](mailto:support@meum.io) ## Before contacting support Include (never include secrets): * Organization name and store slug * Invoice ID or external order ID * Timestamp of the issue * Error message or HTTP status code * Integration type (WooCommerce, API, Pay Link) Never email API keys, webhook secrets, seed phrases, or private keys. ## Related pages * [Troubleshooting](/troubleshooting/payment-remains-pending) * [WooCommerce configuration](/woocommerce/configuration) # Glossary Source: https://docs.meum.io/resources/glossary Meum terminology reference. | Term | Definition | | --------------------- | ------------------------------------------------------------------------ | | **Invoice** | Payment request with hosted checkout URL (`inv_...`) | | **Payment** | On-chain transaction record linked to an invoice | | **Settlement** | Conversion and transfer to merchant stablecoin wallet | | **Settlement wallet** | Merchant payout address | | **Output asset** | Settlement stablecoin (e.g. USDC) | | **Origin asset** | Token the customer pays with | | **Pay Link** | Shareable URL at `pay.meum.io/plpub_{token}` | | **Storefront** | Public catalog at `meum.io/@{store-slug}` | | **Platform fee** | Percentage on successful payment; payer configurable per store (Growth+) | | **Connection key** | Bootstrap key for WooCommerce connect | | **Dedicated key** | Runtime key issued after WooCommerce connect | # Api Key Security Source: https://docs.meum.io/security/api-key-security Best practices for API key handling. * Never commit keys to source control: use environment variables or a secret manager * Rotate immediately if compromised (**Dashboard → API keys**) * Woo **bootstrap** keys: connect flow only; runtime uses the dedicated key issued after connect ## Related pages * [API keys and scopes](/api-reference/api-keys-and-scopes) * [Incident reporting](/security/incident-reporting) # Customer Data Source: https://docs.meum.io/security/customer-data How Meum handles customer-related data. Customer records are wallet-centric and derived from invoice metadata. * WooCommerce customer IDs, emails, and phone may appear in invoice `metadata` * Analytics are available in Merchant Admin (session login) — not via public API * Follow applicable privacy regulations for your jurisdiction ## Related pages * [Customers API status](/api-reference/customers) * [API key security](/security/api-key-security) # Incident Reporting Source: https://docs.meum.io/security/incident-reporting Report security incidents to Meum. Email [support@meum.io](mailto:support@meum.io) with: * Organization and store name (not API keys or secrets) * Timestamp and affected invoice IDs * Description of the incident Rotate compromised API keys and webhook secrets immediately in Merchant Admin. ## Related pages * [API key security](/security/api-key-security) * [Verify signatures](/webhooks/verify-signatures) # Common API errors Source: https://docs.meum.io/troubleshooting/common-api-errors Common Meum API and WooCommerce invoice error codes and fixes. | HTTP | Error | Fix | | ---- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | 401 | Unauthorized | Check Bearer token | | 403 | Bootstrap key for invoices | Use dedicated key after Woo connect | | 403 | `CURRENCY_NOT_ALLOWED` | Allow the shop/invoice currency in Merchant Admin fiat/invoice currency settings, or change the WooCommerce shop currency to a permitted currency | | 400 | Payout wallet not configured | Configure settlement wallet | | 409 | Order ID conflict | Use unique external\_order\_id | | 429 | Too many requests | Back off and retry |

`CURRENCY_NOT_ALLOWED`

Invoice creation returns HTTP **403** with code `CURRENCY_NOT_ALLOWED` when the requested fiat currency is not in the merchant’s allowed invoice fiat currencies. **Typical WooCommerce case:** the shop currency (for example `EUR`) is sent on `POST /v1/invoices`, but the connected Meum org/store only allows another currency (often `USD` by default). **Fix (pick one):** 1. In Merchant Admin, allow that currency for invoice fiat currencies (org/store settings), **or** 2. Change **WooCommerce → Settings → General → Currency** to a currency Meum already allows. The WooCommerce plugin shows a short shopper-safe checkout message; merchants see the full currency hint under **WooCommerce → Settings → Payments → Meum**. ## Related pages * [Errors](/api-reference/errors) * [WooCommerce configuration](/woocommerce/configuration) * [Configure settlement wallet](/getting-started/configure-settlement-wallet) # Invalid Settlement Wallet Source: https://docs.meum.io/troubleshooting/invalid-settlement-wallet Troubleshoot invalid settlement wallet issues with Meum. Invoice creation or WooCommerce connect fails with payout wallet error. **Resolution:** 1. Go to **Dashboard → Account → Organization settlement** 2. Enter a valid payout address for your chosen settlement stablecoin 3. Select output asset (settlement stablecoin) 4. Retry operation See [Configure settlement wallet](/getting-started/configure-settlement-wallet). ## Related pages * [Configure settlement wallet](/getting-started/configure-settlement-wallet) * [Errors](/api-reference/errors) # Payment Expired Source: https://docs.meum.io/troubleshooting/payment-expired Troubleshoot payment expired issues with Meum. Invoice status is `expired`. **Cause:** Invoice passed `expires_at` without full payment. **Resolution:** Create a new invoice or Pay Link. WooCommerce orders are set to `cancelled`. ## Related pages * [Payment statuses](/payments/payment-statuses) * [Accept your first payment](/getting-started/accept-first-payment) # Payment Received Order Not Updated Source: https://docs.meum.io/troubleshooting/payment-received-order-not-updated Troubleshoot payment received order not updated issues with Meum. Payment confirmed in Meum but WooCommerce order not updated. **Check:** 1. Webhook URL reachable from the public internet (check the URL shown in WooCommerce payment settings after connect) 2. WordPress permalinks enabled (not plain) 3. Webhook secret matches between Meum and plugin 4. Check WooCommerce order notes for webhook errors 5. Verify HTTP 200 response with `{ "received": true }` See [WooCommerce webhook verification](/woocommerce/webhook-verification). ## Related pages * [Webhook verification](/woocommerce/webhook-verification) * [Verify signatures](/webhooks/verify-signatures) # Payment Remains Pending Source: https://docs.meum.io/troubleshooting/payment-remains-pending Troubleshoot payment remains pending issues with Meum. Invoice status stays `awaiting_payment` or `quoted`. **Check:** 1. Customer completed on-chain payment to correct deposit address 2. Correct token/network selected at checkout 3. Poll `GET /v1/invoices/{id}/status` to trigger on-demand status check 4. Confirm you are testing against the production API (not a staging environment) **Expected result:** Status transitions within normal confirmation window. ## Related pages * [Payment statuses](/payments/payment-statuses) * [How Meum payments work](/introduction/how-payments-work) # Webhook Delivery Failed Source: https://docs.meum.io/troubleshooting/webhook-delivery-failed Troubleshoot webhook delivery failed issues with Meum. Webhook shows failed in Merchant Admin or integration events. **Check:** 1. Endpoint returns HTTP 2xx within 10 seconds 2. Signature verification passes on your server 3. For WooCommerce: response body passes acknowledgment check 4. Developer endpoints disabled after 10 consecutive failures. Re-enable in dashboard See [Webhooks overview](/webhooks/overview). ## Related pages * [Verify signatures](/webhooks/verify-signatures) * [Webhooks overview](/webhooks/overview) # Woocommerce Connection Failed Source: https://docs.meum.io/troubleshooting/woocommerce-connection-failed Troubleshoot woocommerce connection failed issues with Meum. WooCommerce plugin connect fails. | Error | Action | | ---------------------------- | ------------------------------------------------- | | Invalid connection key | Generate new key in Merchant Admin → Integrations | | Insufficient scope | Use bootstrap connection key, not dedicated key | | Site already connected | Disconnect from other store first | | Payout wallet not configured | Configure settlement wallet | | API unreachable | Verify Platform API URL is `https://api.meum.io` | ## Related pages * [WooCommerce configuration](/woocommerce/configuration) * [Get API credentials](/getting-started/get-api-credentials) # Configure endpoint Source: https://docs.meum.io/webhooks/configure-endpoint Set up webhook endpoints in Merchant Admin or via WooCommerce connect. ## WooCommerce (managed) Webhook endpoint is created automatically on connect. The plugin registers: ``` https://your-store.com/?wc-api=stablecoin_webhook ``` (`your-store.com` is your WordPress site URL.) Also shown in **WooCommerce → Settings → Payments → Meum** after connect. ## Custom integration (dashboard) 1. **Dashboard → Webhooks** → add endpoint URL 2. Select events to subscribe 3. Copy webhook secret (shown once) For one-off invoices without a stored endpoint, pass `callback_url` in `POST /v1/invoices`. ## Default events `invoice.created`, `invoice.paid`, `invoice.expired`, `invoice.failed` WooCommerce managed endpoints also include `invoice.cancelled` and `invoice.underpaid`. Send a test event from the dashboard (`webhook.test`). ## Related pages * [Webhooks overview](/webhooks/overview) * [Verify signatures](/webhooks/verify-signatures) * [Testing webhooks](/webhooks/testing-webhooks) # Event reference Source: https://docs.meum.io/webhooks/event-reference Complete webhook event payload reference. ## Payload envelope All events share this structure: ```json theme={null} { "id": "evt_a1b2c3d4e5f6789012345678abcdef01", "type": "invoice.paid", "createdAt": "2024-06-24T12:00:00.000Z", "data": { "invoice_id": "inv_a1b2c3d4e5f6789012345678abcdef01", "integration_id": "int_a1b2c3d4e5f6789012345678abcdef01", "external_order_id": "order_1048", "amount": "100.00", "expected_amount": "100.00", "received_amount": "100.00", "difference_amount": "0.00", "paid_amount": "100.00", "currency": "USD", "output_asset": "usdc", "tx_hash": "0x…", "paid_at": "2024-06-24T12:05:00.000Z", "payment_url": "https://pay.meum.io/inv_a1b2c3d4e5f6789012345678abcdef01", "status": "paid" } } ``` Payloads use opaque public IDs (`inv_`, `evt_`, `int_`). Do not rely on undocumented fields if present in a response. ## Standard merchant events ### invoice.created Sent immediately after invoice creation. `data.status` is typically `awaiting_payment`. ### invoice.paid Sent when full payment is validated. `data.paid_at` and `data.tx_hash` are populated. ### invoice.underpaid Sent when partial payment detected. Check `difference_amount`. ### invoice.failed Sent on payment failure. ### invoice.expired Sent when invoice expires. ### invoice.cancelled Sent when a merchant cancels an open invoice via `POST /v1/invoices/{id}/cancel`. Only invoices in open states (`awaiting_payment`, `quoted`, `pending`) can be cancelled. Terminal states (`paid`, `refunded`, etc.) cannot be cancelled. Previously this event was subscribed on WooCommerce endpoints but not emitted. Public cancel API now dispatches `invoice.cancelled`. ### webhook.test ```json theme={null} { "id": "evt_demo_test", "type": "webhook.test", "data": { "message": "Test webhook from Meum" } } ``` ## Platform-emitted events (not in default subscriptions) ### invoice.refunded Not a standard merchant integration event. Do not assume this event is subscribed or delivered by default. **When emitted:** Platform status polling detects a refund on an open invoice. The invoice status becomes `refunded` and `invoice.refunded` is dispatched. **Not available:** Merchant-initiated refund API. Default WooCommerce managed webhook subscriptions do not include this event. **WooCommerce behavior if received:** Adds an order note only; does not change order status. ## Expected HTTP response Return **HTTP 200** with JSON body acknowledging receipt. ## Related pages * [Verify signatures](/webhooks/verify-signatures) * [Webhooks overview](/webhooks/overview) * [Webhooks overview](/webhooks/overview) # Webhooks overview Source: https://docs.meum.io/webhooks/overview Meum outbound webhooks for events, headers, delivery, and reliability. Meum sends HTTP POST webhooks when invoice status changes. ## Events | Event | Trigger | | ------------------- | ------------------------------------------------------- | | `invoice.created` | Invoice created | | `invoice.paid` | Full payment received | | `invoice.underpaid` | Partial payment | | `invoice.failed` | Payment failed | | `invoice.expired` | Invoice expired | | `invoice.cancelled` | Invoice cancelled | | `webhook.test` | Manual test from dashboard | | `invoice.refunded` | Platform polling only: **not** in default subscriptions | WooCommerce managed endpoints subscribe to all invoice events except `webhook.test` and `invoice.refunded`. Full payload shapes: [Event reference](/webhooks/event-reference). ## Delivery headers | Header | Required | Description | | ----------------------- | ------------- | -------------------------------- | | `X-Meum-Event` | Yes | Event type | | `X-Meum-Event-Id` | Yes | `evt_...`: use for deduplication | | `X-Meum-Timestamp` | Yes | Unix seconds (signature input) | | `X-Meum-Signature` | Yes | `v1=` | | `X-Meum-Integration-Id` | If integrated | `int_...` | Legacy `X-Stablecoin-*` headers are **not** sent. Verify every delivery: [Verify signatures](/webhooks/verify-signatures). ## Delivery and reliability | Topic | Behavior | | ---------------- | ------------------------------------------------------------------------------------ | | **Retries** | Up to 6 attempts, exponential backoff from 60s, 10s timeout | | **Ordering** | Not guaranteed globally; per-invoice events follow the state machine | | **Duplicates** | Retries may redeliver: dedupe on `X-Meum-Event-Id` | | **Auto-disable** | Custom developer endpoints disabled after 10 consecutive failures | | **WooCommerce** | Endpoint auto-created on connect: [Configure endpoint](/webhooks/configure-endpoint) | ## Related pages * [Configure endpoint](/webhooks/configure-endpoint) * [Testing webhooks](/webhooks/testing-webhooks) * [Webhooks API](/api-reference/webhooks-api) # Testing webhooks Source: https://docs.meum.io/webhooks/testing-webhooks Test webhook delivery from Merchant Admin. ## Dashboard test 1. Go to **Dashboard → Webhooks** 2. Select an endpoint 3. Click **Send test webhook** 4. Event type: `webhook.test` ## Verify locally Use a tunnel (ngrok, cloudflared) to expose your local endpoint: ```bash theme={null} ngrok http 3000 ``` Register the tunnel URL in **Dashboard → Webhooks**. Do not use `webhook.site` placeholder URLs in production. Meum skips known placeholder URLs. ## Related pages * [Configure endpoint](/webhooks/configure-endpoint) * [Verify signatures](/webhooks/verify-signatures) # Verify signatures Source: https://docs.meum.io/webhooks/verify-signatures HMAC v1 webhook signature verification. ## Signature format ``` signedPayload = timestamp + "." + rawBody signature = HMAC_SHA256(webhook_secret, signedPayload) header value = "v1=" + hex(signature) ``` ## Verification steps 1. Read raw request body (before JSON parsing) 2. Require `X-Meum-Signature` and `X-Meum-Timestamp` 3. Reject timestamps older than **300 seconds** 4. When `X-Meum-Integration-Id` is present, match your stored `int_...` 5. Compare signatures with constant-time equality 6. Deduplicate on `X-Meum-Event-Id` before processing ## Example (Node.js) ```javascript theme={null} const crypto = require("crypto"); function verifyWebhook(rawBody, headers, secret) { const timestamp = headers["x-meum-timestamp"]; const signature = headers["x-meum-signature"]; if (!timestamp || !signature) return false; if (Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) > 300) return false; const signed = `${timestamp}.${rawBody}`; const expected = "v1=" + crypto.createHmac("sha256", secret).update(signed).digest("hex"); try { return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); } catch { return false; } } ``` ## Security checklist * Return HTTP 200 only after verification succeeds * Never log webhook secrets * Rotate secrets immediately if compromised ([Incident reporting](/security/incident-reporting)) ## Related pages * [WooCommerce webhook verification](/woocommerce/webhook-verification) * [Webhooks overview](/webhooks/overview) # Checkout flow Source: https://docs.meum.io/woocommerce/checkout-flow WooCommerce checkout to Meum hosted checkout flow. ## Flow 1. Customer selects **Pay with Crypto** at WooCommerce checkout 2. Plugin calls `POST /v1/invoices` with Woo order ID as `external_order_id` 3. Order status set to `on-hold` with awaiting-payment order note 4. Order meta stores the Meum invoice ID and checkout URL for the customer to resume payment 5. Customer redirected to hosted checkout (`checkout_url`, e.g. `https://pay.meum.io/inv_…`) 6. Customer completes crypto payment on hosted checkout 7. Meum sends `invoice.paid` webhook to WooCommerce 8. Plugin calls `$order->payment_complete()` and adds payment received order note ## Redirect behavior Plugin returns `{ result: 'success', redirect: checkout_url }`. Full redirect to Meum hosted checkout. ## Related pages * [Webhook verification](/woocommerce/webhook-verification) * [How Meum payments work](/introduction/how-payments-work) # Configuration Source: https://docs.meum.io/woocommerce/configuration Connect WooCommerce to Meum via connection key. ## Prerequisites * Plugin installed and activated * Settlement wallet configured in Merchant Admin * WooCommerce connection key from **Dashboard → Integrations → WooCommerce** ## Steps 1. Open **WooCommerce → Settings → Payments → Meum Crypto Payments** 2. Paste the **connection key** from Merchant Admin 3. Click **Connect** 4. On success, the plugin stores: * Dedicated API key * Webhook secret * Integration ID 5. Enable the gateway checkbox 6. Save settings ## Advanced settings * **Platform API URL**: default `https://api.meum.io`. Change only when Meum support provides a different base URL for your environment. On **Growth** and **Business** plans, configure whether the platform fee is paid by the merchant or customer under **Dashboard → Stores → \[Store] → Settings → Checkout**. See [Checkout fees](/payments/checkout-fees). ## Shop currency WooCommerce sends the store **shop currency** on each invoice. That currency must be allowed in Meum merchant invoice fiat settings. Otherwise checkout fails with `CURRENCY_NOT_ALLOWED` (HTTP 403). **Fix:** allow the shop currency in Merchant Admin, or change **WooCommerce → Settings → General → Currency** to a currency Meum already allows. See [Common API errors](/troubleshooting/common-api-errors#currency_not_allowed). ## Expected result Gateway shows "Connected" status. Checkout displays "Pay with Crypto". ## Related pages * [Webhook verification](/woocommerce/webhook-verification) * [Checkout flow](/woocommerce/checkout-flow) * [Common API errors](/troubleshooting/common-api-errors) # Installation Source: https://docs.meum.io/woocommerce/installation Install the Meum WooCommerce plugin. ## Requirements * WordPress 6.5+ * WooCommerce 7.0+ * PHP 7.4+ * HTTPS-enabled site (required for webhooks) * Meum merchant account with settlement wallet configured ## Download Download the latest plugin ZIP from: * **[meum.io/integrations](https://meum.io/integrations#woocommerce)** — version shown on the page * Direct file: `meum-crypto-payments-for-woocommerce.zip` ## Installation steps 1. In WordPress admin, go to **Plugins → Add New → Upload Plugin** 2. Upload the `meum-crypto-payments-for-woocommerce.zip` file 3. Click **Install Now**, then **Activate** 4. Go to **WooCommerce → Settings → Payments → Meum Crypto Payments** ## Expected result The Meum payment gateway appears in WooCommerce payments settings with a connection form. ## Related pages * [Configuration](/woocommerce/configuration) # Webhook verification Source: https://docs.meum.io/woocommerce/webhook-verification WooCommerce plugin webhook URL and acknowledgment behavior. ## Webhook URL ``` https://your-store.com/?wc-api=stablecoin_webhook ``` Built by the plugin on connect. Also shown in **WooCommerce → Settings → Payments → Meum**. ## Plugin behavior * Verifies `X-Meum-*` headers (see [Verify signatures](/webhooks/verify-signatures)) * Rejects legacy `X-Stablecoin-*` headers * Dedupes on `X-Meum-Event-Id` in order meta * Returns HTTP `200` with `{ "received": true }` or `{ "duplicate": true }` ## Related pages * [Checkout flow](/woocommerce/checkout-flow) * [Configure endpoint](/webhooks/configure-endpoint)