{
  "info": {
    "name": "PayF API",
    "description": "PayF API collection \u2014 auto-generated from https://api.payf.ai/openapi.json. Set {apiKey} in your Postman environment (or leave the sandbox default) to start making calls.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "version": "0.1.0-sandbox"
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.payf.ai",
      "type": "string"
    },
    {
      "key": "apiKey",
      "value": "sandbox_demo",
      "type": "string",
      "description": "Sandbox key works out of the box. Swap for a real key in production."
    }
  ],
  "item": [
    {
      "name": "API Keys",
      "item": [
        {
          "name": "list-api-keys",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/api-keys",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "api-keys"
              ]
            },
            "description": "Return all API keys belonging to the authenticated merchant, newest first."
          }
        },
        {
          "name": "create-api-key",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/api-keys",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "api-keys"
              ]
            },
            "description": "Allocate a new API key for the authenticated merchant. The plaintext key is returned exactly once. Save it now \u2014 it cannot be retrieved after this response is consumed."
          }
        },
        {
          "name": "revoke-api-key",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/api-keys/{key_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "api-keys",
                "{key_id}"
              ]
            },
            "description": "Permanently delete the named API key. Subsequent requests using the plaintext value will receive 401."
          }
        }
      ]
    },
    {
      "name": "Admin",
      "item": [
        {
          "name": "admin-list-audit",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/audit",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "audit"
              ]
            },
            "description": "Operator-only. Returns the append-only record of operator actions (KYB decisions, force-status, secret rotations, etc.), newest first. Supports filtering by actor user, operation, and target."
          }
        },
        {
          "name": "admin-list-candidates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/candidates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "candidates"
              ]
            },
            "description": "Operator-only. Returns every candidate; filter by status or partner_id."
          }
        },
        {
          "name": "admin-candidates-health",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/candidates/health",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "candidates",
                "health"
              ]
            },
            "description": "Operator-only. Returns the routing engine's rolling-window health snapshot for every candidate it has seen samples for. Health is the score multiplier in [floor, 1] the engine applies during ranking; lower values mean recent failures are downranking the candidate."
          }
        },
        {
          "name": "admin-activate-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/candidates/{candidate_id}/activate",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "candidates",
                "{candidate_id}",
                "activate"
              ]
            },
            "description": "Reactivate a draining or paused channel"
          }
        },
        {
          "name": "admin-approve-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/candidates/{candidate_id}/approve",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "candidates",
                "{candidate_id}",
                "approve"
              ]
            },
            "description": "Approve a pending channel into the routing pool"
          }
        },
        {
          "name": "admin-drain-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/candidates/{candidate_id}/drain",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "candidates",
                "{candidate_id}",
                "drain"
              ]
            },
            "description": "Begin draining a channel \u2014 no new traffic, in-flight allowed to land"
          }
        },
        {
          "name": "admin-list-feature-flags",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/feature-flags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "feature-flags"
              ]
            },
            "description": "Operator-only. Returns every flag, sorted by key. An empty merchant_whitelist means the flag applies network-wide when Enabled is true."
          }
        },
        {
          "name": "admin-delete-feature-flag",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/feature-flags/{key}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "feature-flags",
                "{key}"
              ]
            },
            "description": "Operator-only. The deletion is recorded in the audit log. Consumers that poll this key receive `false` after removal."
          }
        },
        {
          "name": "admin-get-feature-flag",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/feature-flags/{key}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "feature-flags",
                "{key}"
              ]
            },
            "description": "Get a feature flag"
          }
        },
        {
          "name": "admin-upsert-feature-flag",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/feature-flags/{key}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "feature-flags",
                "{key}"
              ]
            },
            "description": "Operator-only. Idempotent \u2014 PUT replaces the full row, including merchant_whitelist. To roll out gradually, list the merchants in merchant_whitelist; to flip network-wide, leave it empty."
          }
        },
        {
          "name": "admin-list-merchants",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants"
              ]
            },
            "description": "Operator-only. Returns the set of merchants derived from the user table along with each merchant's user count."
          }
        },
        {
          "name": "admin-list-merchant-fees",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants/{merchant_id}/fees",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants",
                "{merchant_id}",
                "fees"
              ]
            },
            "description": "Operator-only. Returns the merchant's configured fee overrides. Unconfigured currencies fall through to the network default (50bps)."
          }
        },
        {
          "name": "admin-delete-merchant-fee",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants/{merchant_id}/fees/{currency}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants",
                "{merchant_id}",
                "fees",
                "{currency}"
              ]
            },
            "description": "Operator-only (finance scope). Deletes the override; future settlements in that currency revert to the network default fee."
          }
        },
        {
          "name": "admin-set-merchant-fee",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants/{merchant_id}/fees/{currency}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants",
                "{merchant_id}",
                "fees",
                "{currency}"
              ]
            },
            "description": "Operator-only (finance scope). Sets the fee in basis points (1bps = 0.01%) that will apply to settlements for this merchant in this currency. Recorded in the audit log."
          }
        },
        {
          "name": "admin-list-merchant-notes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants/{merchant_id}/notes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants",
                "{merchant_id}",
                "notes"
              ]
            },
            "description": "Operator-only. Returns the merchant's free-form operator note timeline, newest first. Used to record judgement calls and follow-ups that don't fit the audit log."
          }
        },
        {
          "name": "admin-add-merchant-note",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/merchants/{merchant_id}/notes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "merchants",
                "{merchant_id}",
                "notes"
              ]
            },
            "description": "Operator-only. Append a free-form note to the merchant's operator timeline. The actor is attributed automatically."
          }
        },
        {
          "name": "admin-list-onboarding",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/onboarding",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "onboarding"
              ]
            },
            "description": "Operator-only. Returns merchant applications, newest first."
          }
        },
        {
          "name": "admin-decide-onboarding",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/onboarding/{application_id}/decision",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "onboarding",
                "{application_id}",
                "decision"
              ]
            },
            "description": "Operator-only. Record a verdict. On 'approved' a merchant and an initial admin user are provisioned and attached to the application record."
          }
        },
        {
          "name": "admin-list-partners",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/partners",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "partners"
              ]
            },
            "description": "Operator-only. Returns every registered partner, newest first."
          }
        },
        {
          "name": "admin-mint-partner-key",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/partners/{partner_id}/keys",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "partners",
                "{partner_id}",
                "keys"
              ]
            },
            "description": "Operator-only. The plaintext key is returned exactly once. Give it to the partner out-of-band; PayF never logs the value."
          }
        },
        {
          "name": "admin-list-payments",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments"
              ]
            },
            "description": "Operator-only. Returns payments across every merchant, newest first. Filter to one merchant with merchant_id=."
          }
        },
        {
          "name": "admin-get-payment",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}"
              ]
            },
            "description": "Operator-only. Returns a payment regardless of merchant ownership. Used by support tools to investigate customer-reported issues."
          }
        },
        {
          "name": "admin-force-payment-status",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/force-status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "force-status"
              ]
            },
            "description": "Operator-only. Bypasses the time-based lifecycle. Use to release a risk_hold, recover a stuck issuer_processing, or manually complete a payment after out-of-band reconciliation."
          }
        },
        {
          "name": "admin-reroute-leg",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/legs/{step}/reroute",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "legs",
                "{step}",
                "reroute"
              ]
            },
            "description": "Operator-only. Fails the targeted leg (recording a failure against its current candidate) and re-binds the leg to an alternative compatible candidate. The payment's lifecycle clock realigns so execution resumes from that leg. Returns 404 when the leg index is out of range, 409 when the leg is already settled, and 409 when no alternative candidate is available."
          }
        },
        {
          "name": "admin-list-payment-notes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/notes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "notes"
              ]
            },
            "description": "Operator-only. Returns the per-payment operator note timeline, newest first. Use for incident write-ups, refund reasoning, and follow-ups that need to stay with the transaction."
          }
        },
        {
          "name": "admin-add-payment-note",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/notes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "notes"
              ]
            },
            "description": "Operator-only. Append a free-form note to the payment's operator timeline. The actor is attributed automatically."
          }
        },
        {
          "name": "admin-refund-payment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/refund",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "refund"
              ]
            },
            "description": "Operator-only refund. Same engine as the merchant /v1/payments/{id}/refund but callable by an operator with the support scope on behalf of the merchant \u2014 used when the merchant cannot or will not initiate the refund themselves (dispute resolution, post-incident remediation, etc). Records to the audit log with the operator's identity. Only completed payments are refundable. Omit amount for a full refund; supply a smaller amount (minor units) for partial."
          }
        },
        {
          "name": "admin-reroute-payment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/payments/{payment_id}/reroute",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "payments",
                "{payment_id}",
                "reroute"
              ]
            },
            "description": "Operator-only. Marks the current candidate as a failed attempt (feeding the routing health tracker) and re-binds the payment to the next entry on its fallback chain. The status drops back to 'routing' and the lifecycle resumes. Returns 409 when the fallback chain is exhausted."
          }
        },
        {
          "name": "admin-list-risk-rules",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/risk-rules",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "risk-rules"
              ]
            },
            "description": "Operator-only. Returns every rule, sorted by priority ascending. Each row carries hit stats so the UI can highlight noisy or never-fired rules."
          }
        },
        {
          "name": "admin-create-risk-rule",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/risk-rules",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "risk-rules"
              ]
            },
            "description": "Operator-only. ALL of the supplied conditions must match for the rule to fire. Action `manual_review` puts the payment in a queue for review; `risk_hold` puts the payment in a status that requires explicit operator release."
          }
        },
        {
          "name": "admin-delete-risk-rule",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/risk-rules/{rule_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "risk-rules",
                "{rule_id}"
              ]
            },
            "description": "Operator-only. The deletion is recorded in the audit log."
          }
        },
        {
          "name": "admin-get-risk-rule",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/risk-rules/{rule_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "risk-rules",
                "{rule_id}"
              ]
            },
            "description": "Get a risk rule"
          }
        },
        {
          "name": "admin-update-risk-rule",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/risk-rules/{rule_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "risk-rules",
                "{rule_id}"
              ]
            },
            "description": "Operator-only. Replaces all editable fields. Hit stats are preserved."
          }
        },
        {
          "name": "admin-route-plan",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/routing/plan",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "routing",
                "plan"
              ]
            },
            "description": "Operator-only. Synthesizes a sequence of legs that move funds from the source side (fiat or stablecoin) to the target side. Returns the planned legs without executing them \u2014 used by support tools to debug cross-currency / cross-region payments before they are created."
          }
        },
        {
          "name": "admin-get-system-settings",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/settings",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "settings"
              ]
            },
            "description": "Operator-only. Returns all hot-configurable settings (default fee, etc.). Mutate them via PUT /v1/admin/settings/{key}."
          }
        },
        {
          "name": "admin-set-system-setting",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/settings/{key}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "settings",
                "{key}"
              ]
            },
            "description": "Operator-only (finance scope). Sets a single setting and refreshes the in-process cache immediately \u2014 no restart required. Currently supports the `default_fee_bps` key; future keys land here too."
          }
        },
        {
          "name": "admin-list-tickets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/tickets",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "tickets"
              ]
            },
            "description": "Operator-only. Filter by merchant, status, or severity. Sorted by last activity, newest first."
          }
        },
        {
          "name": "admin-get-ticket",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/tickets/{ticket_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "tickets",
                "{ticket_id}"
              ]
            },
            "description": "Operator-only. Returns full thread regardless of merchant."
          }
        },
        {
          "name": "admin-reply-to-ticket",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/tickets/{ticket_id}/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "tickets",
                "{ticket_id}",
                "messages"
              ]
            },
            "description": "Operator-only. Posting flips status to `waiting_merchant`. Posting to a closed ticket returns 409."
          }
        },
        {
          "name": "admin-set-ticket-status",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/tickets/{ticket_id}/status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "tickets",
                "{ticket_id}",
                "status"
              ]
            },
            "description": "Operator-only. Set status to `resolved` to close the loop with a stamp; `closed` makes it terminal (no more messages accepted)."
          }
        },
        {
          "name": "admin-list-users",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/users",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "users"
              ]
            },
            "description": "Operator-only. Returns every dashboard user, newest first."
          }
        },
        {
          "name": "admin-create-operator",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/users",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "users"
              ]
            },
            "description": "Super-operator only. Provisions a new user with role=operator and the supplied operator_scope. PayF generates a one-time temporary password and returns it once \u2014 share with the new operator securely. They should rotate it via the dashboard Security page on first login."
          }
        },
        {
          "name": "admin-set-operator-scope",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/admin/users/{user_id}/operator-scope",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "admin",
                "users",
                "{user_id}",
                "operator-scope"
              ]
            },
            "description": "Super-operator only. Sets the operator_scope on another user (typically another operator account). Use to delegate KYB review, risk decisions, support, or finance read-only access without granting full admin authority."
          }
        }
      ]
    },
    {
      "name": "Analytics",
      "item": [
        {
          "name": "analytics-summary",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/analytics/summary",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "analytics",
                "summary"
              ]
            },
            "description": "Counts and gross volume across a trailing window, plus breakdowns by stablecoin, country, and status, and a daily transaction time series."
          }
        }
      ]
    },
    {
      "name": "Auth",
      "item": [
        {
          "name": "login",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/login",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "login"
              ]
            },
            "description": "Verify a user's email + password and return a signed access token. The token authenticates subsequent requests via Authorization: Bearer <token>. After 5 failed attempts within 5 minutes the account is locked for 15 minutes (in-process \u2014 resets on API restart). Successful login clears the counter."
          }
        },
        {
          "name": "me",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/me",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "me"
              ]
            },
            "description": "Return the identity attached to the current session token. Requires JWT authentication; API-key-authenticated sessions have no user identity and receive 404."
          }
        },
        {
          "name": "change-password",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/password",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "password"
              ]
            },
            "description": "Authenticated. Verify the caller's current password and replace it with the new one. Affects only the calling user \u2014 operators cannot change other users' passwords through this endpoint."
          }
        },
        {
          "name": "password-reset-request",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/password-reset",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "password-reset"
              ]
            },
            "description": "Public endpoint. Always returns 200 regardless of whether the email matches an account \u2014 this protects against email enumeration. If the email IS recognized, PayF emails a single-use reset link valid for one hour."
          }
        },
        {
          "name": "password-reset-confirm",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/password-reset/confirm",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "password-reset",
                "confirm"
              ]
            },
            "description": "Public endpoint. Validates the single-use token from the email and replaces the user's password. The token is invalidated on first successful confirm. Returns 400 for invalid/expired/used tokens; the body never says which."
          }
        },
        {
          "name": "totp-disable",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/totp/disable",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "totp",
                "disable"
              ]
            },
            "description": "Wipe the stored TOTP secret and disable 2FA on the authenticated user. The caller must present their current TOTP code (or an empty body when 2FA was never enabled). This is the only way to remove a lost authenticator binding without operator intervention."
          }
        },
        {
          "name": "totp-enroll",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/totp/enroll",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "totp",
                "enroll"
              ]
            },
            "description": "Generate a fresh TOTP secret for the authenticated user. Returns the otpauth URI, a base64-encoded PNG of the QR code, and the raw base32 secret for manual entry. The user must call /v1/auth/totp/verify with their first 6-digit code before 2FA is actually enforced at login."
          }
        },
        {
          "name": "totp-verify",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/auth/totp/verify",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "auth",
                "totp",
                "verify"
              ]
            },
            "description": "Verify a 6-digit code against the pending TOTP secret produced by /v1/auth/totp/enroll. On success the secret is marked enabled and future logins must include a totp_code field. Rejects when the user is already enrolled \u2014 call /v1/auth/totp/disable first to re-enroll."
          }
        }
      ]
    },
    {
      "name": "Feature Flags",
      "item": [
        {
          "name": "list-effective-feature-flags",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/feature-flags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "feature-flags"
              ]
            },
            "description": "Returns the flags that are enabled for the authenticated caller. Merchants only see flags that are enabled AND (whitelist is empty OR their merchant_id is in the whitelist). Operators see the flags whose whitelist is empty or contains the operator merchant."
          }
        }
      ]
    },
    {
      "name": "Meta",
      "item": [
        {
          "name": "get-changelog",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/changelog",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "changelog"
              ]
            },
            "description": "Public, unauthenticated. Returns the full changelog (newest first). Use this to track endpoint additions, contract changes, and security fixes between API releases \u2014 your CI can diff successive responses to flag a breaking change before it hits production."
          }
        },
        {
          "name": "get-public-status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/public/status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "public",
                "status"
              ]
            },
            "description": "Public, unauthenticated snapshot of PayF service health. Renders the data shown on payf.ai/status. Status pages and uptime monitors poll this endpoint every 30\u201360 seconds."
          }
        }
      ]
    },
    {
      "name": "Onboarding",
      "item": [
        {
          "name": "onboarding-submit",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/onboarding",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "onboarding"
              ]
            },
            "description": "Public endpoint. Submit business information to request a PayF merchant account. The application enters the review queue and an operator will issue a verdict."
          }
        },
        {
          "name": "onboarding-status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/onboarding/{application_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "onboarding",
                "{application_id}"
              ]
            },
            "description": "Public endpoint. Returns the current status and decision (if any) for a previously submitted application. Operator-only fields on the decision are scrubbed."
          }
        }
      ]
    },
    {
      "name": "Partner",
      "item": [
        {
          "name": "partner-apply",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/apply",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "apply"
              ]
            },
            "description": "Public endpoint. Issuers, PSPs, wallets, acquirers, and card programs submit an integration request. An operator reviews and either approves (which provisions a routing candidate) or rejects."
          }
        },
        {
          "name": "partner-apply-status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/apply/{application_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "apply",
                "{application_id}"
              ]
            },
            "description": "Public endpoint. Returns the current status and decision (if any) for a previously submitted partner application."
          }
        },
        {
          "name": "list-candidates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates"
              ]
            },
            "description": "Return the routing candidate pool the engine is currently evaluating. Sandbox returns the entire seeded pool; production will filter to the calling partner."
          }
        },
        {
          "name": "partner-create-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates"
              ]
            },
            "description": "Partner-only. The new candidate enters in 'pending' status and awaits operator approval before the routing engine considers it."
          }
        },
        {
          "name": "partner-list-candidates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates/mine",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates",
                "mine"
              ]
            },
            "description": "Partner-only. Returns the calling partner's channels in every status."
          }
        },
        {
          "name": "partner-get-candidate",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates/{candidate_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates",
                "{candidate_id}"
              ]
            },
            "description": "Get one of my routing channels"
          }
        },
        {
          "name": "partner-update-candidate",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates/{candidate_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates",
                "{candidate_id}"
              ]
            },
            "description": "Partner-only. Adjust fees, capacity, and supported geographies. Compliance score and status are operator-controlled."
          }
        },
        {
          "name": "partner-pause-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates/{candidate_id}/pause",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates",
                "{candidate_id}",
                "pause"
              ]
            },
            "description": "Partner-only. Withdraws the channel from the routing pool without deleting it. Use for maintenance, capacity issues, etc. Re-enable with /resume."
          }
        },
        {
          "name": "partner-resume-candidate",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/candidates/{candidate_id}/resume",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "candidates",
                "{candidate_id}",
                "resume"
              ]
            },
            "description": "Partner-only. Only works on currently-paused channels. Pending / draining channels must go through operator approval to come back."
          }
        },
        {
          "name": "partner-dashboard",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/dashboard",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "dashboard"
              ]
            },
            "description": "Partner-only. Returns lifetime + recent-window aggregates of payments routed through this partner's candidates, plus a per-candidate breakdown and a daily timeseries. Revenue is estimated by applying a flat 50bps fee against gross volume \u2014 when per-candidate fees ship this becomes per-candidate accurate."
          }
        }
      ]
    },
    {
      "name": "Payments",
      "item": [
        {
          "name": "get-checkout",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/checkout/{payment_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "checkout",
                "{payment_id}"
              ]
            },
            "description": "Returns a payment for the hosted checkout page at pay.payf.ai. PUBLIC \u2014 no Authorization header required: knowledge of the payment_id grants read access, like a paste/sharable receipt. Returns a strict subset of payment fields (amount, currency, status, legs progress) \u2014 never the merchant id, callback URL, candidate ids, fallback chain, or any internal routing detail."
          }
        },
        {
          "name": "list-payments",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/payments",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "payments"
              ]
            },
            "description": "Return the authenticated merchant's payments, newest first."
          }
        },
        {
          "name": "create-payment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/payments",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "payments"
              ]
            },
            "description": "Create a payment order. The PayF Routing Engine runs synchronously during creation and attaches the selected route to the response. Pass an Idempotency-Key header to make this call safely retryable: a repeat call with the same key returns the original payment instead of creating a duplicate."
          }
        },
        {
          "name": "get-payment",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/payments/{payment_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "payments",
                "{payment_id}"
              ]
            },
            "description": "Retrieve a payment and its current lifecycle status. Sandbox payments auto-advance through the status lifecycle (created \u2192 routing \u2192 issuer_processing \u2192 settlement_pending \u2192 completed) within roughly three seconds of creation."
          }
        },
        {
          "name": "refund-payment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/payments/{payment_id}/refund",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "payments",
                "{payment_id}",
                "refund"
              ]
            },
            "description": "Reverse a completed payment. Partial refunds reduce the recorded payment amount. Only completed payments are refundable. Pass an Idempotency-Key header to make this call safely retryable."
          }
        }
      ]
    },
    {
      "name": "Settlements",
      "item": [
        {
          "name": "get-merchant-fees",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/fees",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "fees"
              ]
            },
            "description": "Returns the calling merchant's per-currency fee overrides plus the network default. Read-only \u2014 only operators can mutate the fee schedule."
          }
        },
        {
          "name": "list-settlements",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/settlements",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "settlements"
              ]
            },
            "description": "Return per-day, per-currency rollups of completed payments for the authenticated merchant. Status reflects payout aging: <24h pending, <48h scheduled, otherwise paid. Sandbox uses a flat 50 bps routing fee."
          }
        }
      ]
    },
    {
      "name": "Support",
      "item": [
        {
          "name": "list-tickets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/tickets",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "tickets"
              ]
            },
            "description": "Returns the calling merchant's tickets, newest activity first."
          }
        },
        {
          "name": "create-ticket",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/tickets",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "tickets"
              ]
            },
            "description": "Create a new support ticket. The first message body goes in the same call. The created ticket starts in status `open`; once an operator replies it transitions to `waiting_merchant`."
          }
        },
        {
          "name": "get-ticket",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/tickets/{ticket_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "tickets",
                "{ticket_id}"
              ]
            },
            "description": "Returns a single ticket along with the full message thread, oldest message first."
          }
        },
        {
          "name": "reply-to-ticket",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/tickets/{ticket_id}/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "tickets",
                "{ticket_id}",
                "messages"
              ]
            },
            "description": "Appends a message to the ticket. Posting flips status to `waiting_operator`. Posting to a closed ticket returns 409."
          }
        }
      ]
    },
    {
      "name": "System",
      "item": [
        {
          "name": "health",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/health",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "health"
              ]
            },
            "description": "Liveness + readiness check. Returns 200 with status=ok when the API can reach its datastore; 503 with status=down otherwise. Does not require authentication. Suitable for load balancer probes and external uptime monitors."
          }
        }
      ]
    },
    {
      "name": "Users",
      "item": [
        {
          "name": "list-users",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/users",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "users"
              ]
            },
            "description": "Return every user belonging to the authenticated merchant. JWT sessions are scoped to that merchant; API-key sessions inherit the merchant the key belongs to. Operators should use /v1/admin/users for cross-merchant views."
          }
        },
        {
          "name": "create-user",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/users",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "users"
              ]
            },
            "description": "Create a new dashboard user under the authenticated merchant. Admin only."
          }
        },
        {
          "name": "delete-user",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/users/{user_id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}"
              ]
            },
            "description": "Admin only. Self-deletion is blocked \u2014 ask another admin."
          }
        },
        {
          "name": "set-user-role",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/users/{user_id}/role",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}",
                "role"
              ]
            },
            "description": "Admin only. New role must be admin / finance / viewer. 403 when called by a non-admin, 409 on self-demotion, 404 when the target doesn't belong to your merchant."
          }
        }
      ]
    },
    {
      "name": "Webhooks",
      "item": [
        {
          "name": "list-webhook-deliveries",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook-deliveries",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook-deliveries"
              ]
            },
            "description": "Return recent outbound webhook delivery attempts for the authenticated merchant. Sandbox stores the last 1000 deliveries in memory; production will persist these in the audit log with replay support."
          }
        },
        {
          "name": "replay-webhook-delivery",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook-deliveries/{event_id}/replay",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook-deliveries",
                "{event_id}",
                "replay"
              ]
            },
            "description": "Operator/admin endpoint. Flips a previously-failed (or even already-delivered) webhook event back to 'pending', resets the attempt counter, and lets the background worker pick it up on its next poll. The original payload is reused from the outbox \u2014 replay is bit-for-bit identical to the first attempt."
          }
        },
        {
          "name": "rotate-webhook-secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{apiKey}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/rotate-secret",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                "rotate-secret"
              ]
            },
            "description": "Operator/admin endpoint. Generates a fresh HMAC secret for the authenticated merchant and returns it once. Subsequent outbound webhooks will be signed with the new secret immediately; the old one is destroyed."
          }
        }
      ]
    }
  ]
}
