{
  "info": {
    "name": "Fintar API",
    "description": "Generated from Fintar API 1.0 (https://api.fintar.id/v1/openapi.json). Import together with the Fintar Sandbox environment and put a ft_test_ key in apiKey. Docs: https://fintar.id/docs/api",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Sandbox happy path",
      "description": "Run in order with a ft_test_ key. Creates a test payment, reads it, simulates the buyer paying, and reads it again. Never put a live key in this environment.",
      "item": [
        {
          "name": "1. Create a test payment",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('created', () => pm.expect(pm.response.code).to.be.oneOf([200, 201]));",
                  "const tx = pm.response.json();",
                  "pm.environment.set('paymentId', tx.id);",
                  "pm.environment.set('checkoutToken', tx.checkout_url.split('/p/')[1]);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 150000,\n  \"description\": \"Tes Postman\",\n  \"checkout\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "2. Read the payment",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('pending', () => pm.expect(pm.response.json().status).to.eql('pending'));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions/{{paymentId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions",
                "{{paymentId}}"
              ]
            }
          }
        },
        {
          "name": "3. Simulate the buyer paying (test mode only)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('simulated', () => pm.expect(pm.response.code).to.eql(200));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "auth": {
              "type": "noauth"
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/checkout/{{checkoutToken}}/simulate-payment",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "checkout",
                "{{checkoutToken}}",
                "simulate-payment"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"outcome\": \"succeeded\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Answers 404 for a live payment. Use \"expired\" as the outcome to rehearse an expiry."
          }
        },
        {
          "name": "4. Read the payment again",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "setTimeout(() => {}, 1100);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('succeeded', () => pm.expect(pm.response.json().status).to.eql('succeeded'));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions/{{paymentId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions",
                "{{paymentId}}"
              ]
            }
          }
        }
      ]
    },
    {
      "name": "Transactions",
      "item": [
        {
          "name": "List payment requests",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions?limit=&starting_after=&status=&external_id=&merchant_ref=&created_after=&created_before=",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true,
                  "description": "Page size, 1–100. Out of range falls back to 20."
                },
                {
                  "key": "starting_after",
                  "value": "",
                  "disabled": true,
                  "description": "The last `id` of the previous page (`payreq_<uuid>`). A cursor that does not name one of your payment requests is refused 422 `invalid_cursor`."
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "external_id",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "merchant_ref",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true,
                  "description": "RFC3339 timestamp, e.g. `2026-08-18T09:00:00+07:00`."
                },
                {
                  "key": "created_before",
                  "value": "",
                  "disabled": true,
                  "description": "RFC3339 timestamp."
                }
              ]
            },
            "description": "List payment requests\n\nOne page of this key's payment requests, newest first, scoped to the key's mode. Malformed filters are refused 422, never silently dropped."
          }
        },
        {
          "name": "Create a payment request",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "A fresh key per attempt here. In your code, reuse the same key when retrying the same order."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Create a payment request\n\nCreates a payment request and, for headless integrations, attaches the\nrail's payload (`payment`) when it can be generated immediately. Send\nthe buyer to `checkout_url`, or render `payment` in your own screens.\nA replayed `Idempotency-Key` with the identical body returns the\noriginal with status 200."
          }
        },
        {
          "name": "Retrieve a payment request",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/transactions/:id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "transactions",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Retrieve a payment request\n\nAt most one read per second per transaction on one key; a second read inside that second is 429 `rate_limited` with `Retry-After`. A finished request (succeeded, failed, canceled, expired) is served from cache. Status changes arrive on the `payment.paid` webhook — poll only when you need certainty."
          }
        }
      ]
    },
    {
      "name": "Payment methods",
      "item": [
        {
          "name": "List this account's payment methods",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/payment_methods",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "payment_methods"
              ]
            },
            "description": "List this account's payment methods\n\nThe method codes a create may name in `payment_methods`, with each method's fee, amount bounds and required `customer.*` fields. Read this instead of hard-coding codes — methods can be enabled or suspended without a release on your side."
          }
        }
      ]
    },
    {
      "name": "Subscription customers",
      "item": [
        {
          "name": "[Beta] List customers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_customers?limit=&offset=",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_customers"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "offset",
                  "value": "",
                  "disabled": true,
                  "description": ""
                }
              ]
            },
            "description": "[Beta] List customers\n\nClosed beta. Every subscription endpoint answers 404 for accounts we have not enabled by hand, and the shape may change before general availability."
          }
        },
        {
          "name": "[Beta] Create or update a customer",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_customers",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_customers"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Create or update a customer\n\nSending an `external_id` you have used before updates that customer instead of creating a second one, which is what makes re-running an import safe. One of `email` or `phone` is required: a customer nobody can be reached at cannot be sent a renewal reminder."
          }
        },
        {
          "name": "[Beta] Retrieve a customer",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_customers/:id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_customers",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "[Beta] Retrieve a customer"
          }
        },
        {
          "name": "[Beta] Edit a customer",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_customers/:id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_customers",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Edit a customer\n\nEdits the customer at this id and never creates one. Use this rather than the create endpoint when correcting an `external_id`: that one matches on `external_id`, so changing it there mints a second customer and leaves the subscriptions pointing at the first. Every field is replaced by what you send, and the same rule as creating applies — one of `email` or `phone` must survive the edit."
          }
        }
      ]
    },
    {
      "name": "Subscription plans",
      "item": [
        {
          "name": "[Beta] List live plans",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_plans",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_plans"
              ]
            },
            "description": "[Beta] List live plans\n\nOnly the current version of each plan. Archived versions stay readable through the subscriptions that reference them."
          }
        },
        {
          "name": "[Beta] Create a plan, or reprice one",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_plans",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_plans"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"code\": \"\",\n  \"name\": \"\",\n  \"amount\": 0,\n  \"interval_unit\": \"day\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Create a plan, or reprice one\n\nPlans are immutable. Posting a `code` you have used before writes the next version and archives the one it replaces — subscribers stay on the version they signed up to until you move them, and their existing invoices keep the price they were issued at.\n\n`amount` is required even when it is 0: a free plan is a real plan, so an absent field cannot be read as a free one.\n\nDaily, weekly, monthly and annual. Anything longer than a year is refused."
          }
        }
      ]
    },
    {
      "name": "Subscriptions",
      "item": [
        {
          "name": "[Beta] List subscriptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions?limit=&offset=",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "offset",
                  "value": "",
                  "disabled": true,
                  "description": ""
                }
              ]
            },
            "description": "[Beta] List subscriptions"
          }
        },
        {
          "name": "[Beta] Start a subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer_id\": \"\",\n  \"plan_id\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Start a subscription\n\nBills the opening cycle immediately and returns with the first invoice already issued — unless the plan has a trial, which raises nothing until it ends.\n\nThe mode follows your key: a `ft_test_` key creates a sandbox subscription, which raises sandbox payment requests and sends no reminders to anybody.\n\nLive subscriptions are for verified accounts only: until verification is through, a live key is answered `403 verification_required` and nothing is written. A sandbox key works throughout."
          }
        },
        {
          "name": "[Beta] Retrieve a subscription",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "[Beta] Retrieve a subscription"
          }
        },
        {
          "name": "[Beta] Cancel a subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id/cancel",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id",
                "cancel"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Cancel a subscription\n\n`at_period_end: false` (the default) stops access immediately. `at_period_end: true` honours the service already paid for and stops when the current period runs out. Neither refunds anything.\n\nCancellation is final. A payment arriving afterwards settles its invoice — the debt was real — and grants no access and restarts no billing. Cancelling an already-cancelled subscription is `409`."
          }
        },
        {
          "name": "[Beta] Pause a subscription",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id/pause",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id",
                "pause"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "[Beta] Pause a subscription\n\nStops billing, and stops access with it. A pause is not a free month."
          }
        },
        {
          "name": "[Beta] Resume a paused subscription",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id/resume",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id",
                "resume"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "[Beta] Resume a paused subscription\n\nReturns to `active`, or to `past_due` when an invoice is still outstanding — the pause did not settle the debt."
          }
        },
        {
          "name": "[Beta] Schedule a plan or quantity change",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id/change",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id",
                "change"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta] Schedule a plan or quantity change\n\nTakes effect at the next renewal, and only then. There is no immediate option: proration is not available in this release, and applying a paid upgrade before it is paid for would grant service nobody authorised.\n\nThe scheduled values appear as `pending_plan_id` and `pending_quantity` until the renewal applies them."
          }
        },
        {
          "name": "[Beta, test mode] Move a sandbox subscription's clock forward",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/subscriptions/:id/advance",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                ":id",
                "advance"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "[Beta, test mode] Move a sandbox subscription's clock forward\n\nSimulate the passage of time so a renewal can be watched without waiting for one.\n\nThis bills nothing itself. It moves the subscription's own clock; the renewal sweep then does on its next pass exactly what it does in production — issues the invoice for each cycle passed, creates the QRIS request, and extends access when it is paid. A simulation running its own billing path would be testing code nobody runs.\n\nAdvances accumulate, so a year of renewals can be walked one call at a time. It only moves forward: rewinding would put a subscription behind cycles it has already billed.\n\nSandbox only. A live subscription is refused `422`."
          }
        }
      ]
    },
    {
      "name": "Subscription invoices",
      "item": [
        {
          "name": "[Beta] List invoices",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_invoices?limit=&offset=",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_invoices"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true,
                  "description": ""
                },
                {
                  "key": "offset",
                  "value": "",
                  "disabled": true,
                  "description": ""
                }
              ]
            },
            "description": "[Beta] List invoices"
          }
        },
        {
          "name": "[Beta] Retrieve an invoice",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/subscription_invoices/:id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "subscription_invoices",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "[Beta] Retrieve an invoice"
          }
        }
      ]
    }
  ]
}
