{"openapi":"3.1.0","info":{"title":"MaxMerit Exchange API","version":"1.0.0","summary":"Fiat-to-crypto, crypto-to-fiat and crypto-to-crypto exchange for Canada, with hosted checkout, embeddable widget and NakoPay custody.","description":"REST API with JSON bodies and snake_case fields, shaped to match the Guardarian partner API (same endpoints, field names and statuses) so integrations can move between MaxMerit rails and Guardarian without code changes. Authenticate server-to-server calls with your secret key in the `x-api-key` header. The hosted widget and checkout use your public widget key (`?partner=mm_..._pk_...`). Every partner has a sandbox mode in which transactions progress automatically so you can test the full lifecycle without money moving. MaxMerit extensions (custody with NakoPay, locked estimates, fee breakdowns) are additive and clearly marked.","contact":{"name":"MaxMerit Exchange partnerships","email":"info@maxmeritexchange.com"},"x-logo":{"url":"/favicon.ico"}},"servers":[{"url":"http://localhost:3000","description":"This deployment"},{"url":"https://maxmeritexchange.com","description":"Production"},{"url":"http://localhost:3000","description":"Local development"}],"tags":[{"name":"Catalog","description":"Currencies, networks, payment methods and countries."},{"name":"Pricing","description":"Live rates, limits and binding estimates."},{"name":"Transactions","description":"Create exchanges, send customers to the hosted checkout and track status."},{"name":"Checkout","description":"The hosted checkout, step by step (method, email code, wallet or payout details, billing, identity, payment). Drive it yourself with the widget key, or just send the customer to redirect_url."},{"name":"Customers","description":"Customer records, risk level and shared KYC."},{"name":"Sandbox","description":"Test data accepted in sandbox mode."},{"name":"Custody","description":"NakoPay custody accounts and withdrawals."},{"name":"Webhooks","description":"Signed notifications from MaxMerit to you, and from NakoPay to MaxMerit."}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Secret partner key (mm_live_sk_... or mm_test_sk_...). `x-secret-key` is accepted as an alias. Partners that uploaded an RSA public key must also sign POST /transaction bodies: `Partner-Signature: <base64 RSA-SHA256 of the raw body>`."},"WidgetKey":{"type":"apiKey","in":"query","name":"partner","description":"Public widget key (mm_..._pk_...). Only for the hosted widget / checkout."}},"schemas":{"Estimate":{"type":"object","description":"Guardarian-compatible estimate. `value` and `estimated_exchange_rate` match Guardarian; everything from `id` down is a MaxMerit extension.","properties":{"value":{"type":"number","description":"Amount the customer receives (Guardarian field).","example":0.00206},"estimated_exchange_rate":{"type":"number","description":"to_currency per 1 from_currency, net of fees (Guardarian field)."},"estimated_from_amount":{"type":"number"},"estimated_to_amount":{"type":"number"},"type":{"type":"string","enum":["direct","reverse"]},"estimate_breakdown":{"type":"object","properties":{"service_fee":{"type":"number"},"payment_fee":{"type":"number"},"network_fee":{"type":"number"},"total_fee_cad":{"type":"number"},"mid_rate":{"type":"number"},"value_cad":{"type":"number"}}},"id":{"type":"string","example":"est_8k3mq2p7w9ab","description":"Pass to POST /api/v1/transaction to lock this price."},"provider":{"type":"string","enum":["maxmerit","guardarian"],"description":"Rails that produced the quote."},"direction":{"type":"string","enum":["buy","sell","swap"]},"from_currency":{"type":"string","example":"CAD","description":"Currency code (fiat ISO code or crypto ticker)."},"from_network":{"type":["string","null"],"example":null},"to_currency":{"type":"string","example":"BTC","description":"Currency code (fiat ISO code or crypto ticker)."},"to_network":{"type":["string","null"],"example":"BTC"},"from_amount":{"type":"number","example":300},"to_amount":{"type":"number","example":0.00206},"rate":{"type":"number","description":"Units of to_currency per 1 unit of from_currency, net of fees.","example":0.00000686},"mid_rate":{"type":"number","description":"Mid-market rate before spread and fees."},"fees":{"type":"object","properties":{"service":{"type":"number","description":"Service fee in from_currency."},"payment":{"type":"number","description":"Payment or payout method fee in the fiat currency."},"network":{"type":"number","description":"Network fee in the crypto sent out."},"total_cad":{"type":"number"}}},"payment_method":{"type":["string","null"],"example":"interac"},"value_cad":{"type":"number"},"limits":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"currency":{"type":"string"}}},"kyc_required":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"}}},"Transaction":{"type":"object","description":"Guardarian-compatible transaction (id, status, from/to amounts, payout_address, external_partner_link_id, output_hash, redirect_url ...) plus MaxMerit extensions (mode, provider, fees, payout, deposit, custody, events).","properties":{"id":{"type":"string","example":"tx_7hq2m9kd3pxz"},"status":{"type":"string","enum":["new","waiting_for_customer","waiting_for_deposit","on_hold","exchanging","sending","finished","failed","refunded","expired","cancelled"]},"status_reason":{"type":["string","null"]},"status_details":{"type":["string","null"]},"refund_reason":{"type":["string","null"]},"errors":{"type":"array","items":{"type":"string"}},"email":{"type":["string","null"]},"location":{"type":["string","null"],"description":"Customer country (ISO alpha-2)."},"partner_id":{"type":"string"},"expected_from_amount":{"type":"number"},"expected_to_amount":{"type":"number"},"from_currency_with_network":{"type":"string","example":"USDT_TRX"},"to_currency_with_network":{"type":"string","example":"BTC"},"payout_address":{"type":["string","null"]},"payout_extra_id":{"type":["string","null"]},"payout_type":{"type":"string","enum":["wallet","custody","bank"]},"deposit_type":{"type":["string","null"],"description":"Payment category for buys (INTERAC, VISA_MC...) or CRYPTO."},"deposit_payment_category":{"type":["string","null"]},"payout_payment_category":{"type":["string","null"]},"external_partner_link_id":{"type":["string","null"],"description":"Your reference (Guardarian name). Same as external_id."},"output_hash":{"type":["string","null"],"description":"Payout transaction hash (Guardarian name)."},"mode":{"type":"string","enum":["sandbox","live"]},"provider":{"type":"string","enum":["maxmerit","guardarian"]},"provider_id":{"type":["string","null"],"description":"Upstream Guardarian transaction id when routed there."},"direction":{"type":"string","enum":["buy","sell","swap"]},"from_currency":{"type":"string","example":"CAD","description":"Currency code (fiat ISO code or crypto ticker)."},"from_network":{"type":["string","null"]},"to_currency":{"type":"string","example":"BTC","description":"Currency code (fiat ISO code or crypto ticker)."},"to_network":{"type":["string","null"]},"from_amount":{"type":"number","example":300},"to_amount":{"type":"number"},"rate":{"type":"number"},"fees":{"type":"object","properties":{"service":{"type":"number","description":"Service fee in from_currency."},"payment":{"type":"number","description":"Payment or payout method fee in the fiat currency."},"network":{"type":"number","description":"Network fee in the crypto sent out."},"total_cad":{"type":"number"}}},"value_cad":{"type":"number"},"payment_method":{"type":["string","null"]},"payout":{"type":"object","properties":{"type":{"type":"string","enum":["wallet","custody","bank"]},"address":{"type":["string","null"]},"extra_id":{"type":["string","null"]},"custody_account_id":{"type":["string","null"]},"bank_reference":{"type":["string","null"],"description":"Human summary of a fiat payout destination."},"details":{"type":["object","null"],"description":"Structured, masked payout destination for sells (kind: interac | eft | card | sepa | fasterpayments | wire | ach | cash | other).","additionalProperties":true},"refund_address":{"type":["string","null"],"description":"Swaps: where to return the deposit on failure."},"changeable":{"type":"boolean"}}},"deposit":{"type":"object","description":"Where the customer pays (buy) or sends crypto (sell/swap).","properties":{"address":{"type":["string","null"]},"extra_id":{"type":["string","null"]},"instructions":{"type":["string","null"]},"tx_hash":{"type":["string","null"]},"confirmations":{"type":"integer"},"required_confirmations":{"type":"integer"},"received_at":{"type":["string","null"]},"uri":{"type":["string","null"],"example":"bitcoin:bc1q...?amount=0.005","description":"Payment URI for the QR code."}}},"payout_tx_hash":{"type":["string","null"]},"preauth_token":{"type":["string","null"],"description":"One-time token in redirect_url (`auth_token`). Opening the checkout with it skips the email verification when you supplied the customer's email (Guardarian pre-auth)."},"customer_payout_address_changeable":{"type":"boolean","description":"false when the partner locked the payout address with skip_choose_payout_address."},"from_amount_in_eur":{"type":["number","null"]},"from_amount_in_cad":{"type":"number"},"estimate_breakdown":{"type":"object","description":"Guardarian-shaped breakdown: toAmount, fromAmount, serviceFees[], convertedAmount, estimatedExchangeRate, networkFee, partnerFee.","additionalProperties":true},"payment":{"type":"object","description":"Fiat payment state for buys (MaxMerit extension).","properties":{"status":{"type":"string","enum":["not_started","awaiting_transfer","requires_action","authorized","captured","declined"]},"provider":{"type":["string","null"],"enum":["sandbox","maxmerit","guardarian",null]},"card":{"type":["object","null"],"properties":{"brand":{"type":"string","enum":["visa","mastercard","amex","unknown"]},"last4":{"type":"string"},"exp_month":{"type":"integer"},"exp_year":{"type":"integer"},"holder":{"type":["string","null"]}}},"three_ds":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["pending","passed","failed"]}}},"reference":{"type":"string","example":"MM-7K3P9QX2","description":"What the customer quotes on a transfer."},"instructions":{"type":["object","null"],"description":"Bank / Interac / cash instructions for transfer methods.","properties":{"title":{"type":"string"},"lines":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}}}},"note":{"type":["string","null"]}}},"decline_reason":{"type":["string","null"]},"attempts":{"type":"integer"},"paid_at":{"type":["string","null"],"format":"date-time"}}},"customer":{"type":"object","properties":{"id":{"type":["string","null"],"description":"Customer record (see /customer/{id}/status)."},"email":{"type":["string","null"]},"email_verified":{"type":"boolean"},"phone":{"type":["string","null"]},"country":{"type":["string","null"]},"external_id":{"type":["string","null"]},"locale":{"type":"string"},"marketing_opt_in":{"type":"boolean"},"terms_accepted_at":{"type":["string","null"]},"billing":{"type":"object","properties":{"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"date_of_birth":{"type":["string","null"],"example":"1990-04-12"},"country":{"type":["string","null"]},"region":{"type":["string","null"]},"city":{"type":["string","null"]},"street":{"type":["string","null"]},"apt":{"type":["string","null"]},"postal_code":{"type":["string","null"]}}}}},"kyc":{"type":"object","properties":{"status":{"type":"string","enum":["not_required","pending","submitted","approved","rejected"]},"provider":{"type":["string","null"],"enum":["sandbox","sumsub","shared",null]},"document_type":{"type":["string","null"],"enum":["passport","drivers_licence","id_card",null]},"document_country":{"type":["string","null"]},"submitted_at":{"type":["string","null"]},"reviewed_at":{"type":["string","null"]},"reason":{"type":["string","null"]}}},"checkout":{"type":"object","description":"What the hosted checkout still needs from the customer.","properties":{"requirements":{"type":"array","items":{"type":"string","enum":["method","email","destination","details","kyc"]}},"next_step":{"type":"string","enum":["method","email","destination","details","kyc","payment","deposit","review","status","done"]},"email_verified":{"type":"boolean"},"payout_changeable":{"type":"boolean"}}},"kyc_status":{"type":"string","enum":["not_required","pending","approved","rejected"]},"external_id":{"type":["string","null"],"description":"Your reference, echoed in webhooks."},"redirect_url":{"type":"string","description":"Hosted checkout URL to send the customer to."},"success_url":{"type":["string","null"]},"failure_url":{"type":["string","null"]},"estimate_id":{"type":["string","null"]},"events":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"status":{"type":"string"},"note":{"type":"string"}}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"}}},"TransactionCreate":{"type":"object","description":"Guardarian v1 body (nested `redirects`, `payout_info`, `customer`, `deposit`) with the flat aliases still accepted.","properties":{"from_amount":{"type":"number","example":300},"to_amount":{"type":"number","description":"Alternative to from_amount (reverse quote)."},"from_currency":{"type":"string","example":"CAD"},"to_currency":{"type":"string","example":"BTC"},"from_network":{"type":"string"},"to_network":{"type":"string","example":"BTC"},"redirects":{"type":"object","description":"Where to send the customer 3 seconds after a final status. `$$` is replaced with the transaction id.","properties":{"successful":{"type":"string","format":"uri","example":"https://yourapp.com/finished/$$"},"cancelled":{"type":"string","format":"uri"},"failed":{"type":"string","format":"uri","description":"Failed, expired or refunded."}}},"payout_info":{"type":"object","properties":{"payout_address":{"type":"string"},"extra_id":{"type":"string"},"skip_choose_payout_address":{"type":"boolean","description":"Lock the preset address; the customer cannot change it."},"refund_address":{"type":"string","description":"Swaps: MaxMerit extension."}}},"deposit":{"type":"object","properties":{"payment_category":{"type":"string","example":"VISA_MC"},"skip_choose_payment_category":{"type":"boolean"}}},"locale":{"type":"string","example":"en"},"kyc_shared_token":{"type":"string","description":"Sumsub share token; the customer skips the identity check."},"kyc_shared_token_provider":{"type":"string","enum":["sumsub"]},"payout_address":{"type":"string","description":"Customer wallet for wallet payouts. May be omitted and collected on the hosted checkout."},"payout_extra_id":{"type":"string","description":"Destination tag / memo when the network needs one."},"external_partner_link_id":{"type":"string","description":"Your own reference; echoed in responses and webhooks."},"redirects_successful":{"type":"string","format":"uri"},"redirects_failed":{"type":"string","format":"uri"},"redirects_cancelled":{"type":"string","format":"uri"},"customer_country":{"type":"string","example":"CA"},"deposit_type":{"type":"string","example":"INTERAC","description":"Payment category or method id for buys."},"payout_method":{"type":"string","example":"BANK_TRANSFER","description":"Payout category for sells."},"payout_type":{"type":"string","enum":["wallet","custody","bank"],"description":"Defaults to wallet for crypto payouts, bank for fiat payouts. custody = NakoPay custody (MaxMerit extension)."},"skip_choose_payout_address":{"type":"boolean","description":"Flat alias of payout_info.skip_choose_payout_address."},"customer":{"type":"object","properties":{"email":{"type":"string"},"country":{"type":"string"},"external_id":{"type":"string"},"contact_info":{"type":"object","properties":{"email":{"type":"string"},"phone_number":{"type":"string"}}},"billing_info":{"type":"object","description":"Guardarian `customer.billing_info`. When complete, the checkout skips the details step.","properties":{"country_alpha_2":{"type":"string","example":"CA"},"us_region_alpha_2":{"type":"string"},"region":{"type":"string","example":"ON"},"city":{"type":"string","example":"Toronto"},"street_address":{"type":"string"},"apt_number":{"type":"string"},"post_index":{"type":"string","example":"M5X 1C9"},"first_name":{"type":"string"},"last_name":{"type":"string"},"date_of_birthday":{"type":"string","example":"12.04.1990","description":"DD.MM.YYYY or YYYY-MM-DD."},"gender":{"type":"string","enum":["M","F","O"]},"ip":{"type":"string"}}},"ip":{"type":"string"},"ipV4":{"type":"string"},"ipV6":{"type":"string"}}},"estimate_id":{"type":"string","description":"MaxMerit: lock a previously returned estimate."},"custody_customer_ref":{"type":"string","description":"MaxMerit: your identifier for the customer who owns the custody account."},"payment_method":{"type":"string","description":"MaxMerit alias of deposit_type."},"success_url":{"type":"string","format":"uri","description":"Alias of redirects_successful."},"failure_url":{"type":"string","format":"uri","description":"Alias of redirects_failed."},"provider":{"type":"string","enum":["maxmerit","guardarian"],"description":"Force the rails for this transaction."}}},"BillingInfo":{"type":"object","description":"Guardarian `customer.billing_info`. When complete, the checkout skips the details step.","properties":{"country_alpha_2":{"type":"string","example":"CA"},"us_region_alpha_2":{"type":"string"},"region":{"type":"string","example":"ON"},"city":{"type":"string","example":"Toronto"},"street_address":{"type":"string"},"apt_number":{"type":"string"},"post_index":{"type":"string","example":"M5X 1C9"},"first_name":{"type":"string"},"last_name":{"type":"string"},"date_of_birthday":{"type":"string","example":"12.04.1990","description":"DD.MM.YYYY or YYYY-MM-DD."},"gender":{"type":"string","enum":["M","F","O"]},"ip":{"type":"string"}}},"PayoutDetails":{"type":"object","description":"Fiat payout destination for sells. `kind` must match the payout method chosen (swift uses `wire`).","required":["kind"],"properties":{"kind":{"type":"string","enum":["interac","eft","card","sepa","fasterpayments","wire","ach","cash","other"]},"name":{"type":"string","description":"Account holder (all kinds except card)."},"email":{"type":"string","description":"interac"},"institution":{"type":"string","description":"eft: 3 digits"},"transit":{"type":"string","description":"eft: 5 digits"},"account":{"type":"string","description":"eft / fasterpayments / wire / ach"},"holder":{"type":"string","description":"card"},"number":{"type":"string","description":"card: Visa or Mastercard number (Luhn checked, stored as last4)"},"iban":{"type":"string","description":"sepa (mod-97 checked)"},"bic":{"type":"string","description":"sepa (optional)"},"sort_code":{"type":"string","description":"fasterpayments"},"bank_name":{"type":"string","description":"wire"},"swift":{"type":"string","description":"wire"},"bank_country":{"type":"string","description":"wire (optional)"},"routing":{"type":"string","description":"ach (ABA checksum)"},"account_type":{"type":"string","enum":["checking","savings"],"description":"ach"},"reference":{"type":"string","description":"other (PIX key, CLABE...)"}}},"MethodQuote":{"type":"object","properties":{"id":{"type":"string","example":"card"},"category":{"type":"string","example":"VISA_MC"},"name":{"type":"string"},"type":{"type":"string","enum":["card","bank","wallet","interac","crypto"]},"icon":{"type":["string","null"]},"settlement":{"type":"string","example":"Instant"},"fee_bps":{"type":"integer"},"fee_fixed":{"type":"number"},"to_amount":{"type":"number","description":"What the customer receives with this method."},"from_amount":{"type":"number"},"fee_total":{"type":"number","description":"All fees in CAD."},"selected":{"type":"boolean"}}},"CustomerStatus":{"type":"object","properties":{"id":{"type":"string","example":"cus_8k3mq2p7w9ab"},"email":{"type":"string"},"risk_level":{"type":"string","enum":["LOW","MEDIUM","HIGH","BLOCKED"]},"kyc_status":{"type":"string","enum":["not_required","pending","submitted","approved","rejected"]},"limits":{"type":"object","properties":{"used":{"type":"number"},"max":{"type":"number"},"currency":{"type":"string","example":"CAD"}}},"created_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"amount_below_minimum"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}}}},"paths":{"/api/v1/status":{"get":{"tags":["Catalog"],"summary":"Service status","operationId":"getStatus","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"version":{"type":"string"},"time":{"type":"string"}}}}}}}}},"/api/v1/currencies":{"get":{"tags":["Catalog"],"summary":"All currencies (Guardarian-compatible)","description":"Fiat and crypto in one array with `currency_type`, `ticker`, `networks[]` and `payment_methods[]`, like Guardarian's GET /v1/currencies.","operationId":"listCurrencies","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"currency_type":{"type":"string","enum":["FIAT","CRYPTO"]},"ticker":{"type":"string"},"name":{"type":"string"},"enabled":{"type":"boolean"},"logo_url":{"type":"string"},"networks":{"type":"array","items":{"type":"object","properties":{"network":{"type":"string"},"name":{"type":"string"},"default":{"type":"boolean"}}}},"payment_methods":{"type":"array","items":{"type":"object"}}}}}}}}}}},"/api/v1/currencies/crypto":{"get":{"tags":["Catalog"],"summary":"List crypto assets","operationId":"listCrypto","parameters":[{"name":"include_disabled","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"symbol":{"type":"string","example":"BTC"},"name":{"type":"string"},"icon":{"type":"string","example":"/icons/crypto/btc.svg"},"color":{"type":"string"},"decimals":{"type":"integer"},"buy":{"type":"boolean"},"sell":{"type":"boolean"},"swap":{"type":"boolean"},"custody":{"type":"boolean","description":"Can be held in a NakoPay custody account."},"default_network":{"type":"string"},"networks":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"extra_id":{"type":["string","null"]}}}},"price_cad":{"type":["number","null"]},"change_24h":{"type":["number","null"]}}}}}}}}}},"/api/v1/currencies/fiat":{"get":{"tags":["Catalog"],"summary":"List fiat currencies","operationId":"listFiat","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","example":"CAD"},"name":{"type":"string"},"symbol":{"type":"string","example":"$"},"icon":{"type":"string","example":"/icons/flags/ca.svg"},"decimals":{"type":"integer"},"min_amount":{"type":"number"},"max_amount":{"type":"number"},"cad_per_unit":{"type":["number","null"]},"payment_methods":{"type":"object","properties":{"buy":{"type":"array","items":{"type":"string"}},"sell":{"type":"array","items":{"type":"string"}}}}}}}}}}}}},"/api/v1/payment-methods":{"get":{"tags":["Catalog"],"summary":"List payment methods","operationId":"listPaymentMethods","parameters":[{"name":"currency","in":"query","schema":{"type":"string","example":"CAD"}},{"name":"direction","in":"query","schema":{"type":"string","enum":["buy","sell"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"interac"},"category":{"type":"string","example":"INTERAC"},"name":{"type":"string"},"type":{"type":"string"},"icon":{"type":["string","null"]},"fee_bps":{"type":"integer"},"fee_fixed":{"type":"number"},"settlement":{"type":"string"},"currencies":{"type":"array","items":{"type":"string"}}}}}}}}}}},"/api/v1/payment-categories":{"get":{"tags":["Catalog"],"summary":"Payment categories (Guardarian-compatible)","description":"Category codes such as VISA_MC, SEPA, APPLE_PAY, INTERAC. Accepted interchangeably with payment method ids in `payment_method` / `deposit_type`.","operationId":"listPaymentCategories","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"VISA_MC"},"category":{"type":"string"},"name":{"type":"string"},"payment_method_id":{"type":"string","example":"card"},"deposit_enabled":{"type":"boolean"},"payout_enabled":{"type":"boolean"},"fee_bps":{"type":"integer"},"fee_fixed":{"type":"number"}}}}}}}}}},"/api/v1/market-info/min-max-range/{from_to}":{"get":{"tags":["Pricing"],"summary":"Min and max for a pair (Guardarian-compatible)","operationId":"getMinMaxRange","parameters":[{"name":"from_to","in":"path","required":true,"schema":{"type":"string","example":"CAD_BTC"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"from_currency":{"type":"string"},"to_currency":{"type":"string"},"currency":{"type":"string"},"min":{"type":"number"},"max":{"type":"number"},"kyc_threshold":{"type":"number"}}}}}},"422":{"description":"Malformed pair","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/countries":{"get":{"tags":["Catalog"],"summary":"List countries and whether they are served","operationId":"listCountries","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"code_iso_alpha_2":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"supported":{"type":"boolean"}}}}}}}}}},"/api/v1/rates":{"get":{"tags":["Pricing"],"summary":"Mid-market rates in CAD plus the fee schedule","operationId":"getRates","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"base":{"type":"string","example":"CAD"},"source":{"type":"string"},"fetched_at":{"type":"string"},"fees":{"type":"object"},"crypto":{"type":"array","items":{"type":"object"}},"fiat":{"type":"array","items":{"type":"object"}}}}}}}}}},"/api/v1/limits":{"get":{"tags":["Pricing"],"summary":"Per-transaction limits for a fiat currency","operationId":"getLimits","parameters":[{"name":"currency","in":"query","schema":{"type":"string","example":"CAD"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string"},"min_amount":{"type":"number"},"max_amount":{"type":"number"},"daily_max_amount":{"type":"number"},"kyc_threshold_amount":{"type":"number"},"quote_ttl_seconds":{"type":"integer"}}}}}},"422":{"description":"Unsupported currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/estimate":{"get":{"tags":["Pricing"],"summary":"Get a binding estimate","description":"Returns the amount the customer receives after fees, with an `id` you can pass to `POST /api/v1/transactions` to lock the price for `expires_at`. Works without a key (rate limited) so widgets can quote before sign-in.","operationId":"getEstimate","security":[{},{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"from_currency","in":"query","required":true,"schema":{"type":"string","example":"CAD"}},{"name":"to_currency","in":"query","required":true,"schema":{"type":"string","example":"BTC"}},{"name":"from_amount","in":"query","schema":{"type":"number","example":300},"description":"Provide this or to_amount."},{"name":"to_amount","in":"query","schema":{"type":"number"}},{"name":"to_network","in":"query","schema":{"type":"string","example":"BTC"}},{"name":"from_network","in":"query","schema":{"type":"string"}},{"name":"payment_method","in":"query","schema":{"type":"string","example":"interac"},"description":"Method id or Guardarian category (VISA_MC, SEPA...)."},{"name":"payout_method","in":"query","schema":{"type":"string","example":"BANK_TRANSFER"},"description":"Payout category for sells."},{"name":"type","in":"query","schema":{"type":"string","enum":["direct","reverse"]},"description":"reverse = to_amount is fixed (Guardarian semantics)."},{"name":"direction","in":"query","schema":{"type":"string","enum":["buy","sell","swap"]},"description":"Inferred from the currencies when omitted."},{"name":"provider","in":"query","schema":{"type":"string","enum":["maxmerit","guardarian"]},"description":"Force a provider (testing)."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Estimate"}}}},"422":{"description":"Validation error, unsupported pair, or amount outside limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transaction":{"post":{"tags":["Transactions"],"summary":"Create a transaction (Guardarian-compatible)","description":"Same request body as Guardarian's POST /v1/transaction: nested `redirects`, `payout_info`, `deposit` and `customer` (`contact_info`, `billing_info`, `ip`/`ipV4`/`ipV6`), `kyc_shared_token`, `external_partner_link_id`, `locale`, plus the flat aliases (`payout_address`, `redirects_successful`, `deposit_type`, `customer_country` query parameter...). MaxMerit extensions: `estimate_id` (locks a quote), `payout_type: \"custody\"` with `custody_customer_ref` (custody partners), `payment_method`, `success_url` / `failure_url` aliases and `provider`. Whatever you do not send (method, email, wallet, billing, identity) the hosted checkout collects; `redirect_url` carries a one-time `auth_token` so a customer whose email you supplied skips the sign-in step (pre-auth). Returns 201 with the transaction.","operationId":"createTransactionCompat","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Unique per order. Retrying with the same key within 24 hours returns the transaction already created (200, `Idempotent-Replayed: true`)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionCreate"},"example":{"from_amount":300,"from_currency":"CAD","to_currency":"BTC","from_network":"CAD","to_network":"BTC","redirects":{"successful":"https://yourapp.com/finished/$$","cancelled":"https://yourapp.com/cancelled","failed":"https://yourapp.com/failed"},"payout_info":{"payout_address":"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq","skip_choose_payout_address":true},"deposit":{"payment_category":"VISA_MC","skip_choose_payment_category":true},"customer":{"ipV4":"203.0.113.42","contact_info":{"email":"alex@example.com"},"billing_info":{"country_alpha_2":"CA","region":"ON","city":"Toronto","street_address":"100 King Street West","post_index":"M5X 1C9","first_name":"Alex","last_name":"Tremblay","date_of_birthday":"12.04.1990"}},"external_partner_link_id":"order_55","locale":"en"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Country restricted or custody disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transaction/health":{"post":{"tags":["Transactions"],"summary":"Dry run a transaction (Guardarian-compatible)","description":"Validates the same body as POST /transaction (pair, limits, payment method, country, address, signature) without creating anything.","operationId":"checkTransactionHealth","security":[{"ApiKey":[]},{"WidgetKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionCreate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"checked_at":{"type":"string"}}}}}},"403":{"description":"Country restricted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transaction/{id}":{"get":{"tags":["Transactions"],"summary":"Get a transaction (Guardarian-compatible)","description":"With the widget key and `auth_token` (the `preauth_token` carried in redirect_url) the customer's email is treated as verified, so the checkout opens past the sign-in step.","operationId":"getTransactionCompat","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"auth_token","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions":{"get":{"tags":["Transactions"],"summary":"List your transactions","operationId":"listTransactions","security":[{"ApiKey":[]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string"},"description":"Comma-separated statuses."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Transactions"],"summary":"Create a transaction (alias of POST /api/v1/transaction)","description":"Create from an `estimate_id` (price locked) or from currencies and an amount (a fresh estimate is made). Returns a `redirect_url` for the hosted checkout, where the customer completes payment, wallet and identity steps. Set `payout_type` to `custody` to deliver crypto into a NakoPay custody account instead of a wallet address.","operationId":"createTransaction","security":[{"ApiKey":[]},{"WidgetKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionCreate"},"example":{"estimate_id":"est_8k3mq2p7w9ab","payout_type":"wallet","payout_address":"bc1q...","customer":{"email":"alex@example.com","country":"CA"},"external_id":"order_55"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Country restricted or custody disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}":{"get":{"tags":["Transactions"],"summary":"Get a transaction (alias)","operationId":"getTransaction","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/cancel":{"post":{"tags":["Transactions"],"summary":"Cancel before deposit","operationId":"cancelTransaction","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"409":{"description":"Cannot cancel after a deposit was received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout":{"patch":{"tags":["Checkout"],"summary":"Update checkout details","description":"Payment or payout method (re-quotes the exchange), payout wallet (or custody), structured payout details for sells, billing details. In sandbox, `simulate` stands in for the processor and the chain: `payment_received`, `deposit`, `payment_declined`, `kyc_approved`, `kyc_rejected`, `payout_sent`, `finish`, `fail`, `refund`.","operationId":"updateCheckout","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"payment_method":{"type":"string","example":"card"},"payout_address":{"type":"string"},"payout_extra_id":{"type":"string"},"refund_address":{"type":"string"},"payout_type":{"type":"string","enum":["wallet","custody"]},"custody_customer_ref":{"type":"string"},"payout_details":{"$ref":"#/components/schemas/PayoutDetails"},"billing":{"type":"object","required":["first_name","last_name","date_of_birth","country","region","city","street","postal_code"],"properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"date_of_birth":{"type":"string","example":"1990-04-12"},"country":{"type":"string","example":"CA"},"region":{"type":"string","example":"ON"},"city":{"type":"string"},"street":{"type":"string"},"apt":{"type":"string"},"postal_code":{"type":"string"},"phone":{"type":"string"}}},"customer_email":{"type":"string"},"customer_country":{"type":"string"},"simulate":{"type":"string","enum":["deposit","payment_received","payment_declined","kyc_approved","kyc_rejected","payout_sent","finish","fail","refund"]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"403":{"description":"Sandbox only / custody disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Transaction closed or payout locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation error (invalid address, IBAN, routing number...)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout/methods":{"get":{"tags":["Checkout"],"summary":"Per-method quotes for the method step","description":"Every payment (buy) or payout (sell) method available for the fiat currency, with the amount the customer ends up with and the processing time, as on Guardarian's first checkout screen.","operationId":"checkoutMethods","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MethodQuote"}},"direction":{"type":"string"},"fiat":{"type":"string"},"crypto":{"type":"string"}}}}}}}}},"/api/v1/transactions/{id}/checkout/email":{"post":{"tags":["Checkout"],"summary":"Start email authentication","description":"Records the email, terms acceptance and newsletter choice, then emails a 6-digit code (10 minutes). Sandbox responses include `email_code.sandbox_code`; the master code `000000` also works in sandbox.","operationId":"checkoutEmail","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","terms_accepted"],"properties":{"email":{"type":"string","format":"email"},"marketing_opt_in":{"type":"boolean"},"terms_accepted":{"type":"boolean","enum":[true]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Transaction"},{"type":"object","properties":{"email_code":{"type":"object","properties":{"sent_to":{"type":"string"},"expires_at":{"type":"string"},"sandbox_code":{"type":"string","description":"Sandbox only."},"sandbox_master_code":{"type":"string","example":"000000"}}}}}]}}}},"422":{"description":"Terms not accepted / invalid email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout/verify":{"post":{"tags":["Checkout"],"summary":"Confirm the email code","description":"Marks the email verified, links the customer record and carries over an approved identity check from earlier exchanges. Five wrong attempts lock the code.","operationId":"checkoutVerify","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","example":"123456"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"410":{"description":"Code expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Wrong code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout/kyc":{"post":{"tags":["Checkout"],"summary":"Submit identity documents","description":"Required for exchanges at or above the identity threshold (1,000 CAD by default) unless the customer is already verified or a `kyc_shared_token` was passed. Sandbox approves instantly (reject with `outcome: \"reject\"` or a restricted document country); live mode uses Sumsub.","operationId":"checkoutKyc","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["document_type","document_country","front","selfie"],"properties":{"document_type":{"type":"string","enum":["passport","drivers_licence","id_card"]},"document_country":{"type":"string","example":"CA"},"front":{"type":"string","description":"Data URL or base64 image / PDF."},"back":{"type":"string"},"selfie":{"type":"string"},"outcome":{"type":"string","enum":["approve","reject","pending"],"description":"Sandbox only."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"409":{"description":"Email not verified / already approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Identity provider not configured (live mode)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout/payment":{"post":{"tags":["Checkout"],"summary":"Pay for a buy","description":"`method: \"card\"` sends the card (sandbox test cards: 4242 4242 4242 4242 approved, 4000 0000 0000 3220 needs 3-D Secure, 4000 0000 0000 0002 declined, 4000 0000 0000 9995 insufficient funds, 4000 0000 0000 0069 expired); `method: \"wallet\"` is an Apple Pay / Google Pay token; `method: \"transfer\"` records that the customer sent a bank / Interac / cash payment, which staff (or `simulate: payment_received`) then match. A captured payment moves the exchange to `exchanging`.","operationId":"checkoutPayment","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["method","card"],"properties":{"method":{"type":"string","enum":["card"]},"card":{"type":"object","required":["number","exp_month","exp_year","cvc","holder"],"properties":{"number":{"type":"string","example":"4242424242424242"},"exp_month":{"type":"integer","example":12},"exp_year":{"type":"integer","example":2030},"cvc":{"type":"string","example":"123"},"holder":{"type":"string"}}}}},{"type":"object","required":["method","wallet","token"],"properties":{"method":{"type":"string","enum":["wallet"]},"wallet":{"type":"string","enum":["applepay","googlepay"]},"token":{"type":"string","example":"sandbox"}}},{"type":"object","required":["method","action"],"properties":{"method":{"type":"string","enum":["transfer"]},"action":{"type":"string","enum":["transfer_sent"]}}}]}}}},"responses":{"200":{"description":"Authorised / captured / awaiting transfer / requires_action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"402":{"description":"Card declined (code card_declined, insufficient_funds, card_expired, authentication_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Checkout incomplete or already paid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid card or method mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Payment processor not configured (live mode)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/transactions/{id}/checkout/payment/confirm":{"post":{"tags":["Checkout"],"summary":"Complete 3-D Secure","description":"Finishes a `requires_action` card payment. Sandbox code `1234` passes; anything else fails the authentication.","operationId":"checkoutPaymentConfirm","security":[{"ApiKey":[]},{"WidgetKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","example":"1234"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"402":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No pending challenge","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/customer/{id}/status":{"get":{"tags":["Customers"],"summary":"Customer risk level and limits (Guardarian-compatible)","operationId":"getCustomerStatus","security":[{"ApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerStatus"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/customer/by-shared-token":{"post":{"tags":["Customers"],"summary":"Import a customer with a Sumsub share token (Guardarian-compatible)","description":"Creates the customer as verified so their exchanges skip the identity check. 201 when created, 200 when the email already exists.","operationId":"createCustomerBySharedToken","security":[{"ApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","kyc_shared_token","kyc_shared_token_provider"],"properties":{"email":{"type":"string","format":"email"},"kyc_shared_token":{"type":"string","example":"_act-460a698b-d2bc-4cbc-9456-5f36fee38650"},"kyc_shared_token_provider":{"type":"string","enum":["sumsub"]}}}}}},"responses":{"200":{"description":"Already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerStatus"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerStatus"}}}},"503":{"description":"Identity provider not configured (live mode)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sandbox":{"get":{"tags":["Sandbox"],"summary":"Sandbox test data","description":"Test cards, the email master code, the 3-D Secure code, valid wallet addresses per network, demo billing and payout details.","operationId":"getSandboxData","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/payment-categories/{category}/countries":{"get":{"tags":["Catalog"],"summary":"Countries where a payment category is offered (Guardarian-compatible)","operationId":"getPaymentCategoryCountries","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","example":"INTERAC"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"code_iso_alpha_2":{"type":"string"},"country_name":{"type":"string"},"supported":{"type":"boolean"}}}}}}},"404":{"description":"Unknown category","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/countries/{country}/payment-categories":{"get":{"tags":["Catalog"],"summary":"Payment categories offered in a country (Guardarian-compatible)","operationId":"getCountryPaymentCategories","parameters":[{"name":"country","in":"path","required":true,"schema":{"type":"string","example":"CA"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"payment_method_id":{"type":"string"},"deposit_enabled":{"type":"boolean"},"payout_enabled":{"type":"boolean"}}}}}}},"404":{"description":"Unknown country","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/custody/accounts":{"get":{"tags":["Custody"],"summary":"List custody accounts","operationId":"listCustodyAccounts","security":[{"ApiKey":[]}],"parameters":[{"name":"customer_ref","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}}}}}}}}},"post":{"tags":["Custody"],"summary":"Create or reuse a custody account","description":"One account per customer, asset and network. Returns the NakoPay deposit address; crypto bought with `payout_type: custody` lands here.","operationId":"createCustodyAccount","security":[{"ApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customer_ref","asset"],"properties":{"customer_ref":{"type":"string","example":"user_1001"},"asset":{"type":"string","example":"BTC"},"network":{"type":"string","example":"BTC"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"customer_ref":{"type":"string"},"asset":{"type":"string"},"network":{"type":"string"},"deposit_address":{"type":["string","null"]},"deposit_extra_id":{"type":["string","null"]},"balance":{"type":"number"},"pending":{"type":"number"},"status":{"type":"string"},"mode":{"type":"string"}}}}}}}},"403":{"description":"Custody disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Unsupported asset or network","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/custody/accounts/{id}":{"get":{"tags":["Custody"],"summary":"Get balance and deposit address","operationId":"getCustodyAccount","security":[{"ApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/custody/accounts/{id}/payouts":{"post":{"tags":["Custody"],"summary":"Withdraw from custody","operationId":"createCustodyPayout","security":[{"ApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["address","amount"],"properties":{"address":{"type":"string"},"extra_id":{"type":"string"},"amount":{"type":"number"}}}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"payout_id":{"type":"string"},"status":{"type":"string"}}}}}}}},"422":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/partner":{"get":{"tags":["Catalog"],"summary":"Your partner profile, widget key and webhook config","description":"With a secret key: the full partner record. With only a public widget key (`?partner=`): `{ id, name, mode, custody_enabled }`, which the hosted widget and checkout use to decide what to offer.","operationId":"getPartner","security":[{"ApiKey":[]},{}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}}}},"patch":{"tags":["Catalog"],"summary":"Update your webhook URL, allowed origins or contact email","description":"Secret key. Self-service for the settings a partner owns; keys, mode and revenue share are changed by MaxMerit.","operationId":"updatePartner","security":[{"ApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhook_url":{"type":"string","format":"uri","nullable":true},"allowed_origins":{"type":"array","items":{"type":"string"}},"contact_email":{"type":"string","format":"email","nullable":true}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}}}}},"/api/v1/webhooks/deliveries":{"get":{"tags":["Webhooks"],"summary":"Your recent webhook deliveries","description":"Secret key. Newest first, with attempts, response status, last error and the signed payload, so you can debug an endpoint without asking support.","operationId":"listWebhookDeliveries","security":[{"ApiKey":[]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","delivered","failed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}}}}}}}}}},"/api/v1/webhooks/test":{"post":{"tags":["Webhooks"],"summary":"Send a test.ping event to your webhook URL","description":"Secret key. Queues a signed `test.ping` delivery to the webhook URL on file (set it with PATCH /api/v1/partner or in the partner portal). Rate limited to 10 per minute.","operationId":"testWebhook","security":[{"ApiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","nullable":true},"status":{"type":"string"}}}}}}}}}}},"/api/v1/contact":{"post":{"tags":["Catalog"],"summary":"Website contact / quote form","description":"Public, no key. Stores an inquiry that MaxMerit staff review by hand in the admin (quotes, transfers, crypto, business and partner-access requests). Rate limited per IP.","operationId":"createInquiry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email"],"properties":{"type":{"type":"string","enum":["quote","exchange","transfer","crypto","business","partner","token"],"default":"quote"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"company":{"type":"string"},"website":{"type":"string"},"from_currency":{"type":"string","example":"CAD"},"to_currency":{"type":"string","example":"USD"},"amount":{"type":"number"},"message":{"type":"string"}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","example":"new"}}}}}}}}}}},"/api/v1/webhooks/nakopay":{"post":{"tags":["Webhooks"],"summary":"Inbound NakoPay custody events","description":"Signed with `X-NakoPay-Signature: t=<unix>,v1=<hmac>` using NAKOPAY_WEBHOOK_SECRET.","operationId":"nakopayWebhook","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["custody.deposit","custody.payout","custody.account_updated"]},"account_id":{"type":"string"},"amount":{"type":"number"},"tx_hash":{"type":"string"},"balance":{"type":"number"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"matched":{"type":"boolean"}}}}}},"401":{"description":"Bad signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"transaction.status_changed":{"post":{"summary":"Sent to your webhook_url on every status change","description":"Guardarian-style envelope: `{ payload, version: \"1.0\", requesterType: \"EXCHANGE\" }` where `payload` is the transaction (plus `previous_status`, `status_reason` or custody fields), with MaxMerit extensions `event`, `guardarian_event`, `event_id`, `created_at`, `mode`. Besides status changes you get the per-step events Guardarian offers on request: kyc.started / kyc.finished / kyc.failed, deposit.waiting / deposit.received / deposit.captured / deposit.failed, payment.submitted and crypto.sent. Headers: `X-MM-Signature: t=<unix>,v1=<hex HMAC-SHA256 of \"<t>.<body>\">`, `X-MM-Event`, `X-MM-Delivery`. Respond 2xx within 10 seconds; we retry 5 times with exponential backoff.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"payload":{"$ref":"#/components/schemas/Transaction"},"version":{"type":"string","example":"1.0"},"requesterType":{"type":"string","example":"EXCHANGE"},"event":{"type":"string","enum":["transaction.created","transaction.status_changed","transaction.finished","transaction.failed","kyc.started","kyc.finished","kyc.failed","deposit.waiting","deposit.received","deposit.captured","deposit.failed","payment.submitted","crypto.sent","custody.deposit_detected","custody.payout_sent","test.ping"]},"guardarian_event":{"type":["string","null"],"description":"Guardarian's name for the optional per-step events (kycStarted, depositReceived, cryptoSent...)."},"event_id":{"type":"string"},"created_at":{"type":"string"},"mode":{"type":"string"}}}}}},"responses":{"200":{"description":"Acknowledged"}}}}}}