> ## Documentation Index
> Fetch the complete documentation index at: https://docs.joinmarkt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Merchant payments

> Read and update store payment settings with a Bearer API key. Secret fields that match the redaction rules are returned as [redacted].

All routes require:

```txt theme={null}
Authorization: Bearer <your_key>
```

Paths are store-scoped. The key must include the scope for that method and access to that shop. Dashboard permission ceiling: `managePayments`.

`storeId` in the JSON body is ignored. The shop is the `{storeId}` in the path.

These routes are rate limited to 120 requests per 60 seconds (`429`).

## Payment method ids

Payment method ids that exist are only:

`customer-balance`, `stripe`, `paypal`, `mollie`, `square`, `sumup`, `revolut`, `authorizenet`, `skrill`, `misticpay`, `rewarble`, `paypal-ff`, `venmo-ff`, `cash-app`, `shopify`, `adyen`, `lemon-squeezy`, `whop`, `overpay`, `paymongo`, `dodo`, `pandabase`, `moneymotion`, `amazon-ps`, `custom`, `cryptomus`, `nowpayments`, `join-markt-crypto`.

Those are the only catalog method ids. `paymentNotesConfig.lists[].method` is only `cash-app`, `paypal-ff`, or `venmo-ff`. `paymentOptionsConfig.methods` keys are trimmed strings and are not limited to that list: a blank key is dropped, a catalog id used as a key is one of the ids above, and any other key is stored. Checkout reads a custom method presentation at `custom:{id}`. That key is not another catalog method id.

Enable flags map to method ids as follows. `custom` has no enable flag on this resource. `customer-balance` is `paymentOptionsConfig.customerBalanceEnabled`.

| Method id | Enable field |
| - | - |
| `stripe` | `stripeEnabled` |
| `paypal` | `paypalEnabled` |
| `mollie` | `mollieEnabled` |
| `square` | `squareEnabled` |
| `sumup` | `sumupEnabled` |
| `revolut` | `revolutEnabled` |
| `authorizenet` | `authorizenetEnabled` |
| `skrill` | `skrillEnabled` |
| `misticpay` | `misticpayEnabled` |
| `rewarble` | `rewarbleEnabled` |
| `paypal-ff` | `paypalFfEnabled` |
| `venmo-ff` | `venmoFfEnabled` |
| `cash-app` | `cashAppEnabled` |
| `shopify` | `shopifyEnabled` |
| `adyen` | `adyenEnabled` |
| `lemon-squeezy` | `lemonSqueezyEnabled` |
| `whop` | `whopEnabled` |
| `overpay` | `overpayEnabled` |
| `paymongo` | `paymongoEnabled` |
| `dodo` | `dodoEnabled` |
| `pandabase` | `pandabaseEnabled` |
| `moneymotion` | `moneymotionEnabled` |
| `amazon-ps` | `amazonPsEnabled` |
| `cryptomus` | `cryptomusEnabled` |
| `nowpayments` | `nowpaymentsEnabled` |
| `join-markt-crypto` | `joinMarktCryptoEnabled` |
| `customer-balance` | `paymentOptionsConfig.customerBalanceEnabled` |

Setting an enable flag to `true` for a method the platform has disabled returns `403` when that flag is not already `true` on the store. The error is `This payment method is disabled by the platform administrator`, with the administrator reason appended when one is set. If the store already has that flag `true`, the save turns the flag off and does not return `403`. Setting a flag to `false` is allowed. `customer-balance` has no stale-enable exception: turning `customerBalanceEnabled` on while the platform has disabled `customer-balance` returns `403`.

`joinMarktCryptoEnabled: true` also requires Premium or Business (`403`, `code` `plan_join_markt_crypto`).

## Get

```http theme={null}
GET /api/merchant/v1/stores/{storeId}/payments
```

Scope: `payment:read`

Returns the payment settings object. A missing store returns `404`.

Non-empty values whose names match these patterns are replaced with the string `[redacted]`. Null and empty string are left as stored.

`Secret`, `ApiKey`, `ClientSecret`, `TransactionKey`, `SignatureKey`, `WebhookSecret`, `ShaRequestPhrase`, `ShaResponsePhrase`, `AccessCode`, `Password`, `botToken` (each matched at the end of the field name, case-insensitive).

Fields that do not match are returned as stored. A name ending in `SecretKey` does not match `Secret`. That includes `stripeSecretKey`, `squareAccessToken`, `skrillSecretWord`, `adyenWebhookHmacKey`, `overpayPublicKey`, `overpaySecretKey`, and `paymongoSecretKey`.

`paypalIntegrationType` is `rest` when the stored value is null. `paypalFfUnderpayPercent`, `venmoFfUnderpayPercent`, and `cashAppUnderpayPercent` are `5` when the stored value is null. `joinMarktCryptoPayoutEmail` is the store owner's platform account email when that email exists, otherwise the stored payout email.

`cryptomusCommissionPercentage` and `nowpaymentsCommissionPercentage` are not in this object.

| Field | Notes |
| - | - |
| `id` | Store id |
| `name` | Store name |
| `ownerAccountEmail` | Store owner platform account email |
| `stripeEnabled` | Boolean |
| `stripeSecretKey` | Returned as stored |
| `stripePublishableKey` | |
| `stripeEmbeddedForm` | Boolean |
| `stripeCurrencyConversion` | Boolean |
| `stripeAllowedCurrencies` | Array or null |
| `stripeShowTos` | Boolean |
| `stripeTosText` | |
| `stripeBillingAddressCollection` | Boolean |
| `stripeAutomaticTax` | Boolean |
| `stripeWebhookSecret` | Redacted when non-empty |
| `stripeAccountId` | |
| `cryptomusEnabled` | Boolean |
| `cryptomusEnabledCurrencies` | |
| `cryptomusCommissionPayer` | |
| `nowpaymentsEnabled` | Boolean |
| `nowpaymentsEnabledCurrencies` | |
| `nowpaymentsCommissionPayer` | |
| `joinMarktCryptoEnabled` | Boolean |
| `joinMarktCryptoEnabledCurrencies` | |
| `joinMarktCryptoCommissionPercentage` | Read only. Sending it on update returns `403` |
| `joinMarktCryptoCommissionPayer` | |
| `joinMarktCryptoPayoutEnabled` | Boolean |
| `joinMarktCryptoPayoutEmail` | Read only. Sending it on update returns `403` |
| `joinMarktCryptoPayoutWallets` | `{ usdtTron, btc, ltc }`, each string or null, or `null` |
| `paypalEnabled` | Boolean |
| `paypalIntegrationType` | `classic` or `rest` |
| `paypalEmail` | |
| `paypalClientId` | |
| `paypalClientSecret` | Redacted when non-empty |
| `paypalWebhookId` | |
| `paypalSandbox` | Boolean |
| `paypalCardsOnly` | Boolean |
| `paypalCollectShipping` | Boolean |
| `mollieEnabled` | Boolean |
| `mollieApiKey` | Redacted when non-empty |
| `squareEnabled` | Boolean |
| `squareAccessToken` | Returned as stored |
| `squareLocationId` | |
| `squareWebhookSignatureKey` | Redacted when non-empty |
| `squareSandbox` | Boolean |
| `sumupEnabled` | Boolean |
| `sumupApiKey` | Redacted when non-empty |
| `sumupMerchantCode` | |
| `revolutEnabled` | Boolean |
| `revolutApiSecret` | Redacted when non-empty |
| `revolutWebhookSecret` | Redacted when non-empty |
| `revolutSandbox` | Boolean |
| `authorizenetEnabled` | Boolean |
| `authorizenetApiLoginId` | |
| `authorizenetTransactionKey` | Redacted when non-empty |
| `authorizenetSignatureKey` | Redacted when non-empty |
| `authorizenetSandbox` | Boolean |
| `skrillEnabled` | Boolean |
| `skrillMerchantEmail` | |
| `skrillApiMqiPassword` | Redacted when non-empty |
| `skrillSecretWord` | Returned as stored |
| `misticpayEnabled` | Boolean |
| `misticpayClientId` | |
| `misticpayClientSecret` | Redacted when non-empty |
| `rewarbleEnabled` | Boolean |
| `rewarbleApiKey` | Redacted when non-empty |
| `rewarbleTestMode` | Boolean |
| `paypalFfEnabled` | Boolean |
| `paypalFfEmail` | |
| `paypalFfAccountInfo` | |
| `paypalFfUnderpayPercent` | Number. Read defaults to `5` |
| `paypalFfNotes` | String array or null |
| `venmoFfEnabled` | Boolean |
| `venmoFfTag` | |
| `venmoFfEmail` | |
| `venmoFfAccountInfo` | |
| `venmoFfUnderpayPercent` | Number. Read defaults to `5` |
| `venmoFfNotes` | String array or null |
| `cashAppEnabled` | Boolean |
| `cashAppCashtag` | |
| `cashAppEmail` | |
| `cashAppUnderpayPercent` | Number. Read defaults to `5` |
| `cashAppNotes` | String array or null |
| `shopifyEnabled` | Boolean |
| `shopifyShopDomain` | |
| `shopifyClientId` | |
| `shopifyClientSecret` | Redacted when non-empty |
| `shopifyWebhookSecret` | Redacted when non-empty |
| `shopifyCurrency` | |
| `adyenEnabled` | Boolean |
| `adyenApiKey` | Redacted when non-empty |
| `adyenMerchantAccount` | |
| `adyenWebhookHmacKey` | Returned as stored |
| `adyenLiveUrlPrefix` | |
| `adyenSandbox` | Boolean |
| `lemonSqueezyEnabled` | Boolean |
| `lemonSqueezyApiKey` | Redacted when non-empty |
| `lemonSqueezyStoreId` | |
| `lemonSqueezyVariantId` | |
| `lemonSqueezyWebhookSecret` | Redacted when non-empty |
| `whopEnabled` | Boolean |
| `whopApiKey` | Redacted when non-empty |
| `whopCompanyId` | |
| `whopWebhookSecret` | Redacted when non-empty |
| `whopSandbox` | Boolean |
| `overpayEnabled` | Boolean |
| `overpayShopId` | |
| `overpayPublicKey` | Returned as stored |
| `overpaySecretKey` | Returned as stored |
| `overpayTestMode` | Boolean |
| `paymongoEnabled` | Boolean |
| `paymongoSecretKey` | Returned as stored |
| `paymongoWebhookSecret` | Redacted when non-empty |
| `paymongoPaymentMethodTypes` | PayMongo checkout type ids. See below |
| `paymongoPassOnFees` | Boolean |
| `paymongoSendEmailReceipt` | Boolean |
| `dodoEnabled` | Boolean |
| `dodoApiKey` | Redacted when non-empty |
| `dodoWebhookSecret` | Redacted when non-empty |
| `dodoProductId` | |
| `dodoCheckoutMode` | String or null |
| `dodoPricesIncludeTax` | Boolean |
| `dodoTestMode` | Boolean |
| `pandabaseEnabled` | Boolean |
| `pandabaseApiKey` | Redacted when non-empty |
| `pandabaseStoreId` | |
| `pandabaseWebhookSecret` | Redacted when non-empty |
| `moneymotionEnabled` | Boolean |
| `moneymotionApiKey` | Redacted when non-empty |
| `moneymotionWebhookSecret` | Redacted when non-empty |
| `moneymotionTestMode` | Boolean |
| `amazonPsEnabled` | Boolean |
| `amazonPsMerchantIdentifier` | |
| `amazonPsAccessCode` | Redacted when non-empty |
| `amazonPsShaRequestPhrase` | Redacted when non-empty |
| `amazonPsShaResponsePhrase` | Redacted when non-empty |
| `amazonPsCurrency` | |
| `amazonPsSandbox` | Boolean |
| `paymentOptionsConfig` | See below |
| `paymentNotesConfig` | See below |

GET returns `paymongoPaymentMethodTypes` as stored. On update it is parsed to PayMongo checkout type ids on the `paymongo` method: `card`, `gcash`, `paymaya`, `grab_pay`, `shopee_pay`, `qrph`, `dob`, `brankas`, `billease`, `atome`. Those are not extra payment method ids. Unknown ids are dropped. A non-array, or an array that keeps nothing, is stored as `card`, `gcash`, `paymaya`, `grab_pay`, `qrph`.

## Update

```http theme={null}
PATCH /api/merchant/v1/stores/{storeId}/payments
PUT   /api/merchant/v1/stores/{storeId}/payments
```

Scope: `payment:write`

`PUT` runs the same handler as `PATCH`. Status `200`. The response is the same object as GET, after redaction. A new secret can be written. Matching secret fields come back as `[redacted]`.

The body must be a JSON object. An empty object, or an object that only contains `storeId`, returns `400` (`No updatable payment fields provided`). Invalid JSON returns `400`.

These keys return `403` and nothing is saved:

* `cryptomusCommissionPercentage`
* `nowpaymentsCommissionPercentage`
* `joinMarktCryptoCommissionPercentage`
* `joinMarktCryptoPayoutEmail`

The message is `{key} cannot be changed via the Merchant API`.

Recognized payment fields from the GET table are applied. Other keys the store update understands are also applied. Keys it does not read are ignored. The response is still only the payment settings object.

Write rules that differ from a plain assign:

| Field | Rule |
| - | - |
| String credentials and ids in the gateway string list | Truthy values are stored with `String(value)`. Falsy values are stored as `null`. This step does not trim |
| Gateway boolean flags (`paypalEnabled`, `paypalSandbox`, `paypalCardsOnly`, `paypalCollectShipping`, `mollieEnabled`, `squareEnabled`, `squareSandbox`, `sumupEnabled`, `revolutEnabled`, `revolutSandbox`, `authorizenetEnabled`, `authorizenetSandbox`, `skrillEnabled`, `misticpayEnabled`, `rewarbleEnabled`, `rewarbleTestMode`, `paypalFfEnabled`, `venmoFfEnabled`, `cashAppEnabled`, `shopifyEnabled`, `adyenEnabled`, `adyenSandbox`, `lemonSqueezyEnabled`, `whopEnabled`, `whopSandbox`, `overpayEnabled`, `overpayTestMode`, `paymongoEnabled`, `paymongoPassOnFees`, `paymongoSendEmailReceipt`, `dodoEnabled`, `dodoPricesIncludeTax`, `dodoTestMode`, `pandabaseEnabled`, `moneymotionEnabled`, `moneymotionTestMode`, `amazonPsEnabled`, `amazonPsSandbox`) | Stored as booleans |
| `stripeEmbeddedForm`, `stripeCurrencyConversion`, `stripeShowTos`, `stripeBillingAddressCollection`, `stripeAutomaticTax` | Stored as booleans |
| `stripeEnabled`, `cryptomusEnabled`, `nowpaymentsEnabled`, `joinMarktCryptoEnabled` | Stored as sent. The platform-disabled check runs only when the value is `true` |
| `paypalIntegrationType` | `classic` or `rest`. Anything else is `400` |
| `shopifyCurrency` | Must be a currency code, uppercased. Otherwise `400` |
| `shopifyShopDomain` | Normalized when non-empty |
| `lemonSqueezyStoreId`, `lemonSqueezyVariantId` | Normalized when non-empty |
| `whopCompanyId` | Must be `biz_…` or `blz_…`. Otherwise `400` |
| `adyenEnabled` true and `adyenSandbox` false in this request | `adyenLiveUrlPrefix` must be non-blank. Otherwise `400`. A sandbox value already stored on the shop is not read for this check |
| `paypalFfUnderpayPercent`, `venmoFfUnderpayPercent`, `cashAppUnderpayPercent` | Clamped to 0–100. A non-finite number is stored as `5` |
| `paypalFfNotes`, `venmoFfNotes`, `cashAppNotes` | String array, a newline-separated string, or `null`. Entries are trimmed. Blanks are dropped |
| `cryptomusCommissionPayer`, `nowpaymentsCommissionPayer`, `joinMarktCryptoCommissionPayer` | Stored as sent. A falsy value is stored as `seller` |
| `stripeAllowedCurrencies` | Stored when it is an array, otherwise `null` |
| `cryptomusEnabledCurrencies`, `nowpaymentsEnabledCurrencies`, `joinMarktCryptoEnabledCurrencies` | Falsy values are stored as `null`. Any other value, including an empty array, is stored as sent |
| `joinMarktCryptoPayoutWallets` | Partial `{ usdtTron, btc, ltc }`. Each value is a trimmed string up to 256 characters, or null. All empty becomes `null`. Sending wallets or `joinMarktCryptoPayoutEnabled` loads the current payout flag |
| `joinMarktCryptoPayoutEnabled` | When the resulting payout flag is on, `joinMarktCryptoPayoutEmail` is set to the owner account email. Missing owner email is `400`. Sending `false` clears the payout email. Updating wallets while payouts are already on also rebinds that email |
| `paymongoPaymentMethodTypes` | Parsed to the PayMongo type list above |
| `paymentOptionsConfig` | Normalized. See below |
| `paymentNotesConfig` | Normalized. See below |

`joinMarktCryptoPayoutWallets` shape:

```json theme={null}
{ "usdtTron": "T...", "btc": null, "ltc": null }
```

### `paymentOptionsConfig`

```json theme={null}
{
  "customerBalanceEnabled": false,
  "allowBalanceTopUps": false,
  "passGatewayFeesToCustomer": false,
  "minimumOrderAmount": null,
  "methods": {
    "stripe": {
      "displayName": null,
      "checkoutLabel": null,
      "iconUrl": null,
      "percentAdjustment": 0,
      "fixedAdjustment": 0,
      "minAmount": null,
      "maxAmount": null
    }
  }
}
```

| Field | Rule |
| - | - |
| `customerBalanceEnabled` | Boolean. `true` checks that `customer-balance` is allowed |
| `allowBalanceTopUps` | Boolean |
| `passGatewayFeesToCustomer` | Boolean |
| `minimumOrderAmount` | Number ≥ 0, or null |
| `methods` | Object. Keys are trimmed. A blank key is dropped. A catalog method id is only one from the list above. Other keys, including `custom:{id}`, are stored and do not return `400` |
| `methods.*.displayName` | String or null, max 120 |
| `methods.*.checkoutLabel` | String or null, max 200 |
| `methods.*.iconUrl` | String or null, max 2048 |
| `methods.*.percentAdjustment` | Number from -100 to 100. Omitted becomes 0 |
| `methods.*.fixedAdjustment` | Finite number. Omitted becomes 0 |
| `methods.*.minAmount`, `methods.*.maxAmount` | Number ≥ 0, or null. If min is greater than max, they are swapped |

Invalid options return `400`.

### `paymentNotesConfig`

```json theme={null}
{
  "lists": [
    {
      "id": "notes_1",
      "name": "Cash App notes",
      "method": "cash-app",
      "notes": ["Paid"],
      "enabled": true,
      "updatedAt": "2026-10-25T12:00:00.000Z"
    }
  ]
}
```

`lists` max 100. Each list requires `id` (1–64), `name` (1–80), `method` (`cash-app`, `paypal-ff`, or `venmo-ff`), `notes` (1–50 strings, each 1–200), `enabled`, and `updatedAt` as a datetime string. Invalid notes return `400`.

## Errors

| Status | Meaning |
| - | - |
| 400 | Invalid JSON, empty update, invalid payment options or notes, or a field rule above |
| 401 | Missing or invalid Bearer token |
| 403 | Scope or shop not allowed, blocked commission or payout-email key, platform-disabled method, or plan gate |
| 404 | Store not found |
| 429 | Rate limit exceeded |

Error JSON is `{ "success": false, "error": "...", "code": "..." }`. Plan gates add `requiredPlan` and `upgradePath`.

## Related

* [Merchant payouts](https://docs.joinmarkt.com/api-reference/merchant-payouts.md)
* [API keys](https://docs.joinmarkt.com/developers/api-keys.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.