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

# Payment method configuration (v2)

> Read the payment method configuration for the vendor bound to your API key, resolved per store: which methods exist, where each one charges, and with which values.

Returns the payment configuration Fire holds for the vendor bound to your API key, resolved store
by store: which methods each one offers, where each of them charges, and with which values. Every
entry is self-contained — there is no catalog to join against.

With no filter it returns every store of the vendor, paginated. With `storeId` or `storeCode`, a
single one.

<Warning>
  **The response includes configuration values, including the ones flagged as secret** (merchant
  keys, card-reader credentials). Treat this response as sensitive material: do not log it, do not
  cache it in a browser, and do not forward it to third parties.
</Warning>

<Info>
  This is v2. [v1](/en/api-reference/payment-methods-config) returns country → vendor → methods
  with an `enabled` flag and **stays available, with no sunset date**. v2 changes where the data
  comes from and adds the store, channel, fulfillment and terminal levels.
</Info>

## Authentication

<ParamField header="x-api-key" type="string" required>
  Your Fire API key with the `payment-methods:read` scope. The key **must be vendor-scoped**
  (account + vendor binding) — keys without a `vendorId` are rejected with `403`. Account and
  vendor are resolved from the key; they are not accepted as query params.
</ParamField>

## Parameters

<ParamField query="storeId" type="string">
  The store's UUID in Fire. Mutually exclusive with `storeCode`: sending both returns `400`.
</ParamField>

<ParamField query="storeCode" type="string">
  The store's external code (`EXTERNAL CODE` in the backoffice). This is the identifier you most
  likely already hold in your own store master. It is unambiguous because the API key pins the
  vendor.
</ParamField>

<ParamField query="channel" type="string">
  Narrows `availability` to one channel (for example `KIOSK`). Compared uppercased. Stores left
  with no combination for that channel still appear, with no methods.
</ParamField>

<ParamField query="page" type="integer" default="1">
  Page of `stores`.
</ParamField>

<ParamField query="size" type="integer" default="20">
  Stores per page. Maximum `100`.
</ParamField>

## Request

<RequestExample>
  ```http Whole vendor theme={null}
  GET https://api.fire.rest/api/v2/external/payment-methods/config
  x-api-key: <your_api_key>
  ```

  ```http One store theme={null}
  GET https://api.fire.rest/api/v2/external/payment-methods/config?storeCode=K008
  x-api-key: <your_api_key>
  ```
</RequestExample>

## Response

<ResponseField name="success" type="boolean">Always `true` on a `200`.</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="accountId" type="string">UUID of the API key's account.</ResponseField>
    <ResponseField name="vendorId" type="string">The API key's vendor.</ResponseField>
    <ResponseField name="generatedAt" type="string">ISO 8601 timestamp of the resolution.</ResponseField>

    <ResponseField name="stores" type="object[]">
      <Expandable title="store">
        <ResponseField name="storeId" type="string">The store's UUID.</ResponseField>
        <ResponseField name="storeCode" type="string | null">External code.</ResponseField>
        <ResponseField name="storeNumber" type="integer">The store's number in Fire.</ResponseField>
        <ResponseField name="name" type="string | null">Store name.</ResponseField>
        <ResponseField name="countryCode" type="string | null">`null` when the store has no country set; it then appears in `warnings` and `methods` comes back empty.</ResponseField>
        <ResponseField name="active" type="string">`ACTIVE`, `INACTIVE` or `SUSPENDED`.</ResponseField>
        <ResponseField name="status" type="string">`DRAFT`, `PUBLISHED`, `PARTIALLY_PUBLISHED` or `ARCHIVED`.</ResponseField>

        <ResponseField name="methods" type="object[]">
          <Expandable title="storeMethod">
            <ResponseField name="methodId" type="string">The method's UUID. **This is the identifier**, and the only stable one.</ResponseField>
            <ResponseField name="code" type="string">Code, for convenience. Unique only within a country, so use `methodId` to identify a method.</ResponseField>
            <ResponseField name="name" type="string">Display name.</ResponseField>
            <ResponseField name="description" type="string | null">Optional description.</ResponseField>
            <ResponseField name="logoUrl" type="string | null">Logo URL.</ResponseField>
            <ResponseField name="cardBrands" type="string[]">Accepted brands. Empty = not a card method.</ResponseField>
            <ResponseField name="active" type="boolean">Whether the method is active on the account. When `false` it charges in no store.</ResponseField>
            <ResponseField name="position" type="integer">Suggested order.</ResponseField>

            <ResponseField name="configFields" type="object[]">
              The fields the method declares. What the values in `config` mean.

              <Expandable title="configField">
                <ResponseField name="key" type="string">The key it appears under in `config`.</ResponseField>
                <ResponseField name="label" type="string">Label.</ResponseField>
                <ResponseField name="required" type="boolean">Whether it is mandatory.</ResponseField>
                <ResponseField name="scopeLevel" type="string">`account`, `store` or `device`. `device` fields do **not** appear in a store's `config`, only in `devices[].config`.</ResponseField>
                <ResponseField name="secret" type="boolean">Whether the value is sensitive.</ResponseField>
                <ResponseField name="helpText" type="string | null">Optional help text.</ResponseField>
              </Expandable>
            </ResponseField>

            <ResponseField name="charging" type="boolean">Derived: the method is active **and** charges in at least one combination. With `?channel=`, scoped to that channel.</ResponseField>

            <ResponseField name="availability" type="object[]">
              This is the truth; `charging` is a roll-up of it.

              <Expandable title="availability">
                <ResponseField name="channelCode" type="string">Channel (`KIOSK`, `POS`, `WEB`…).</ResponseField>
                <ResponseField name="fulfillmentCode" type="string">Fulfillment (`DINE_IN`, `TAKEAWAY`, `DELIVERY`…).</ResponseField>
                <ResponseField name="enabled" type="boolean">`false` = configured but paused. Not the same as not being offered: what is not offered does not appear at all.</ResponseField>
              </Expandable>
            </ResponseField>

            <ResponseField name="config" type="object">Effective store-level values: the account's, with the store's on top. Only `account` and `store` fields.</ResponseField>
            <ResponseField name="missingRequiredKeys" type="string[]">Mandatory account or store fields left empty. If this is not empty, the store is not ready to charge with that method.</ResponseField>

            <ResponseField name="devices" type="object[]">
              Terminals with their own configuration or stance. Empty is the normal case.

              <Expandable title="device">
                <ResponseField name="deviceType" type="string">`KIOSK` or `POS`.</ResponseField>
                <ResponseField name="deviceId" type="string">The terminal's identifier in Fire.</ResponseField>
                <ResponseField name="charging" type="boolean">Whether that unit charges, already resolved against its store.</ResponseField>
                <ResponseField name="availability" type="object[]">Same as the store's, with the terminal's own stance applied on top.</ResponseField>
                <ResponseField name="config" type="object">**Only** the values set on that terminal, without merging the store's again: that is how you tell an exception from inheritance.</ResponseField>
              </Expandable>
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="warnings" type="object[]">
      What came back incomplete without failing the request. Today only `STORE_COUNTRY_MISSING`:
      the store has no country set, so its catalog could not be resolved.
    </ResponseField>

    <ResponseField name="total" type="integer">Stores of the vendor matching the filter.</ResponseField>
    <ResponseField name="page" type="integer">Page returned.</ResponseField>
    <ResponseField name="size" type="integer">Page size.</ResponseField>
    <ResponseField name="totalPages" type="integer">Total pages.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "accountId": "550e8400-e29b-41d4-a716-446655440000",
      "vendorId": "100.1.10",
      "generatedAt": "2026-09-04T13:00:00.000Z",
      "stores": [
        {
          "storeId": "aa11bb22-0000-4000-8000-000000000002",
          "storeCode": "K008",
          "storeNumber": 812,
          "name": "Quicentro",
          "countryCode": "EC",
          "active": "ACTIVE",
          "status": "PUBLISHED",
          "methods": [
            {
              "methodId": "9f3a1c2e-0000-4000-8000-000000000001",
              "code": "datafast",
              "name": "Datafast",
              "description": null,
              "logoUrl": "https://cdn.fire.rest/logos/datafast.webp",
              "cardBrands": ["visa", "mastercard"],
              "active": true,
              "position": 0,
              "configFields": [
                {
                  "key": "merchant_id",
                  "label": "Merchant ID",
                  "required": true,
                  "scopeLevel": "account",
                  "secret": false,
                  "helpText": null
                },
                {
                  "key": "terminal_key",
                  "label": "Terminal key",
                  "required": true,
                  "scopeLevel": "store",
                  "secret": true,
                  "helpText": null
                },
                {
                  "key": "terminal_ip",
                  "label": "Card reader IP",
                  "required": false,
                  "scopeLevel": "device",
                  "secret": false,
                  "helpText": null
                }
              ],
              "charging": true,
              "availability": [
                {"channelCode": "KIOSK", "fulfillmentCode": "DINE_IN", "enabled": true},
                {"channelCode": "KIOSK", "fulfillmentCode": "TAKEAWAY", "enabled": false}
              ],
              "config": {"merchant_id": "M-000123", "terminal_key": "sk_live_..."},
              "missingRequiredKeys": [],
              "devices": [
                {
                  "deviceType": "KIOSK",
                  "deviceId": "cc33dd44-0000-4000-8000-000000000003",
                  "charging": false,
                  "availability": [
                    {"channelCode": "KIOSK", "fulfillmentCode": "DINE_IN", "enabled": false},
                    {"channelCode": "KIOSK", "fulfillmentCode": "TAKEAWAY", "enabled": false}
                  ],
                  "config": {"terminal_ip": "10.20.0.9"}
                }
              ]
            }
          ]
        }
      ],
      "warnings": [],
      "total": 1,
      "page": 1,
      "size": 20,
      "totalPages": 1
    }
  }
  ```

  ```json 400 — storeId and storeCode together theme={null}
  {
    "success": false,
    "error": "VALIDATION_ERROR",
    "message": "Datos de entrada inválidos",
    "details": [
      {
        "code": "custom",
        "path": ["storeCode"],
        "message": "Use either storeId or storeCode, not both"
      }
    ]
  }
  ```

  ```json 401 — invalid API key theme={null}
  {
    "success": false,
    "error": "UNAUTHORIZED",
    "message": "API key required. Use x-api-key: pk_live_... header"
  }
  ```

  ```json 403 — key without the scope theme={null}
  {
    "success": false,
    "error": "FORBIDDEN",
    "message": "API key does not have required scope: payment-methods:read. Available: store:read"
  }
  ```

  ```json 403 — key not vendor-scoped theme={null}
  {
    "success": false,
    "error": "FORBIDDEN",
    "message": "API key must be vendor-scoped (account + vendor binding) to access this endpoint"
  }
  ```

  ```json 404 — the store is not yours theme={null}
  {
    "success": false,
    "error": "NOT_FOUND",
    "message": "Store not found"
  }
  ```
</ResponseExample>

## How to read the response

**To decide whether to show a method in a store**, look at `charging`. It is `true` when the
method is active on the account and charges in at least one combination of that store.

**To know in which channel and fulfillment it charges**, look at `availability`. An entry with
`enabled: false` means "configured here, but switched off right now" — the provider is down, say.
That is different from not appearing at all: what does not appear is not offered in that store.
Collapsing the two costs you later: drop the paused entries and, the day the method is resumed,
your side reads it as a combination nobody ever set up and reconfigures what was already there.

**Before attempting a charge**, look at `missingRequiredKeys`. If it carries anything, mandatory
data is missing and the charge will fail on the provider's side.

**`devices` is almost always empty.** It shows up when one terminal has an exception — a kiosk's
card reader broke and only that unit was switched off, leaving the rest of the store charging. If
your integration does not distinguish terminals you can ignore it: the store level is the right
answer for a sales channel.

## Notes

* **Identify methods by `methodId`, never by `code`.** A code is unique only within a country, and
  a vendor with stores in two countries can define the same code twice, with different ids.
* `fulfillmentCode` is returned exactly as stored, without normalizing against the global
  catalog.
* Methods with `active: false` are returned anyway, so you can render them as "unavailable" or
  hide them — your call.
* Asking for a store that does not belong to your key's vendor returns `404`, not `403`.

## Related

<CardGroup cols={2}>
  <Card title="Payment method configuration (v1)" icon="clock-rotate-left" href="/en/api-reference/payment-methods-config">
    The previous version, without store levels. Still available.
  </Card>

  <Card title="Channels configuration" icon="grid-2" href="/en/api-reference/channels-config">
    Which channels and fulfillments your vendor has enabled.
  </Card>
</CardGroup>
