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

# Connect Merchant Accounts (OAuth)

> Let HitPay merchants connect their account to your platform with OAuth 2.0

<Note>
  **Beta** — OAuth apps are currently in beta. The flow is stable and available to all businesses, but the API surface is still expanding and details may change. Share feedback at [support@hit-pay.com](mailto:support@hit-pay.com).
</Note>

## Overview

If you run a marketplace, SaaS platform, or any tool that serves HitPay merchants, you can add a **"Connect your HitPay account"** button to your product. Merchants authorize your app once, and your platform receives API tokens to act on their behalf — create payment requests, look up charges, and issue refunds. This is the structured alternative to collecting merchants' API keys: access is scoped, revocable, and no secrets change hands. (New to HitPay's platform model? Start with the [Platforms overview](/platforms/overview) for how the integration paths compare.)

The integration uses the industry-standard **OAuth 2.0 authorization code flow**:

1. You create an **app** in the HitPay Dashboard and receive a client ID and client secret.
2. Your platform redirects the merchant to HitPay's authorization page.
3. The merchant reviews the permissions your app is requesting and approves the connection.
4. HitPay redirects the merchant back to your platform with an authorization code.
5. Your server exchanges the code for an access token and refresh token.
6. You call the HitPay API with the access token, scoped to that merchant's business.

Merchants stay in control: they can see every connected app in their dashboard and revoke access at any time.

<Note>
  Looking to collect a platform commission on transactions? OAuth handles account access only — to take commissions, have your account [platform-enabled](/platforms/overview#add-on-platform-enablement) and pass your `X-PLATFORM-KEY` header alongside the Bearer token when creating payment requests. See [Platform Key](/apis/guide/platform-apis).
</Note>

## Create your app

<Steps>
  <Step title="Open the App Builder">
    In the [HitPay Dashboard](https://dashboard.hit-pay.com), go to **Developers → App Builder** and click **New App**. You need to be an Owner or Admin of your business.
  </Step>

  <Step title="Fill in your app details">
    | Field             | Required | Description                                                                                                                                        |
    | ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
    | App Name          | Yes      | Shown to merchants on the authorization screen.                                                                                                    |
    | Redirect URIs     | Yes      | One URL per line. HitPay will only redirect merchants back to a URI in this list, so it must exactly match the `redirect_uri` you use in the flow. |
    | App icon          | No       | Shown to merchants. PNG or JPG, square works best.                                                                                                 |
    | Developer website | No       | Your platform's homepage.                                                                                                                          |
  </Step>

  <Step title="Save your client credentials">
    After creating the app you'll see your **Client ID** and **Client Secret**.

    <Warning>
      The client secret is shown **only once**. Store it securely on your server — it can't be retrieved again. If you lose it, use **Regenerate Secret** in the app's detail panel (this immediately invalidates the old secret).
    </Warning>
  </Step>

  <Step title="Request the scopes you need">
    New apps start with the `business:read` scope only. To act on payments, open your app's detail panel, click **Request Scopes**, select the scopes your integration needs, and describe your use case. HitPay reviews scope requests and you'll see the status (pending, approved, or rejected) in the same panel.
  </Step>
</Steps>

## Scopes

| Scope             | Grants                                                                             |
| ----------------- | ---------------------------------------------------------------------------------- |
| `business:read`   | View the connected business profile and account information (default)              |
| `payments`        | Create, view, cancel, and refund payments (includes all `payments:*` scopes below) |
| `payments:read`   | View payment and payment request details                                           |
| `payments:create` | Create payments and payment requests                                               |
| `payments:cancel` | Cancel or delete payments and payment requests                                     |
| `payments:refund` | Create refunds for eligible payments                                               |

Request only the scopes your integration actually needs — merchants see the full list on the authorization screen.

## Step 1: Redirect the merchant to HitPay

When the merchant clicks **Connect your HitPay account** on your platform, redirect them to:

```text theme={"system"}
https://dashboard.hit-pay.com/oauth/authorize
  ?client_id=CLIENT_ID
  &redirect_uri=https://yourplatform.com/hitpay/callback
  &response_type=code
  &scope=business:read payments:create payments:read
  &state=RANDOM_STRING
```

| Parameter                                 | Required    | Description                                                                                                           |
| ----------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------- |
| `client_id`                               | Yes         | Your app's client ID.                                                                                                 |
| `redirect_uri`                            | Yes         | Where the merchant is sent after approving or denying. Must exactly match one of your app's registered redirect URIs. |
| `response_type`                           | Yes         | Always `code`.                                                                                                        |
| `scope`                                   | Yes         | Space-separated list of scopes to request. Must be scopes granted to your app.                                        |
| `state`                                   | Recommended | An opaque random value you generate and verify on the callback to protect against CSRF.                               |
| `code_challenge`, `code_challenge_method` | Optional    | PKCE parameters (`S256`) for an additional layer of security.                                                         |

### What the merchant sees

The merchant signs in to HitPay (if they aren't already) and lands on the authorization screen, which shows your app's name and icon and the permissions you're requesting. If the merchant manages multiple businesses, they choose which business to connect. Only business **Owners and Admins** can authorize an app.

The merchant then clicks **Authorize** or **Deny access**.

## Step 2: Handle the redirect

If the merchant approves, HitPay redirects back to your `redirect_uri` with an authorization code:

```text theme={"system"}
https://yourplatform.com/hitpay/callback?code=AUTHORIZATION_CODE&state=RANDOM_STRING
```

Verify that `state` matches the value you sent, then move on to the token exchange. Authorization codes are short-lived and single-use.

If the merchant denies access, the redirect includes an error instead:

```text theme={"system"}
https://yourplatform.com/hitpay/callback?error=access_denied&state=RANDOM_STRING
```

## Step 3: Exchange the code for tokens

From your server, exchange the authorization code for an access token:

```bash theme={"system"}
curl -X POST "https://api.hit-pay.com/v1/open/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=CLIENT_ID" \
  -d "client_secret=CLIENT_SECRET" \
  -d "redirect_uri=https://yourplatform.com/hitpay/callback" \
  -d "code=AUTHORIZATION_CODE"
```

```json Response theme={"system"}
{
  "token_type": "Bearer",
  "expires_in": 31536000,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "refresh_token": "def50200641f136a0811..."
}
```

Store both tokens securely against the merchant's record in your database. Access tokens are long-lived (one year); use the refresh token to obtain a new access token before it expires:

```bash theme={"system"}
curl -X POST "https://api.hit-pay.com/v1/open/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=CLIENT_ID" \
  -d "client_secret=CLIENT_SECRET" \
  -d "refresh_token=REFRESH_TOKEN"
```

<Note>
  The token endpoint is rate-limited to 90 requests per minute.
</Note>

## Step 4: Call the API on the merchant's behalf

Authenticate API calls by sending the access token as a Bearer token. The main endpoint you'll use is the [Payment Request API](/apis/overview) — create a payment request for the connected merchant, then redirect your customer to the returned checkout `url`:

```bash theme={"system"}
curl -X POST "https://api.hit-pay.com/v1/payment-requests" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "amount=25.00" \
  -d "currency=SGD" \
  -d "email=customer@example.com" \
  -d "purpose=Order 123" \
  -d "redirect_url=https://yourplatform.com/order/123/complete"
```

```json Response theme={"system"}
{
  "id": "974ee233-bc3e-4aac-a212-15af0d155133",
  "email": "customer@example.com",
  "amount": "25.00",
  "currency": "SGD",
  "status": "pending",
  "purpose": "Order 123",
  "url": "https://securecheckout.hit-pay.com/payment-request/@acme-coffee/974ee233-bc3e-4aac-a212-15af0d155133/checkout",
  "redirect_url": "https://yourplatform.com/order/123/complete",
  "allow_repeated_payments": false,
  "created_at": "2026-07-07T13:09:42",
  "updated_at": "2026-07-07T13:09:42"
}
```

The request and response shapes are identical to the standard [Payment Request API](/apis/overview) — the only difference is authentication: the Bearer token replaces the `X-BUSINESS-API-KEY` header, and the payment is created on the connected merchant's account.

The following endpoints accept OAuth access tokens:

| Endpoint                                                    | Required scope                        |
| ----------------------------------------------------------- | ------------------------------------- |
| `POST /v1/payment-requests`                                 | `payments:create`                     |
| `GET /v1/payment-requests`, `GET /v1/payment-requests/{id}` | `payments:read`                       |
| `PUT /v1/payment-requests/{id}`                             | `payments:create`                     |
| `DELETE /v1/payment-requests/{id}`                          | `payments:cancel`                     |
| `GET /v1/charges`, `GET /v1/charges/{id}`                   | `payments:read`                       |
| `POST /v1/refunds`, `GET /v1/refunds/{id}`                  | `payments:refund`                     |
| `GET /v1/info`                                              | Any (available to all connected apps) |

<Tip>
  `GET /v1/info` returns the connected business's profile (name, country, currency, and whether payments are enabled). Call it right after the token exchange to confirm the connection and store which business the token belongs to.
</Tip>

## Getting notified of payments

Pass a `webhook` URL when creating each payment request — HitPay will notify that URL when the payment completes, regardless of the merchant's own webhook configuration:

```bash theme={"system"}
curl -X POST "https://api.hit-pay.com/v1/payment-requests" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "amount=25.00" \
  -d "currency=SGD" \
  -d "webhook=https://yourplatform.com/hitpay/webhook"
```

See [Webhooks](/apis/guide/events) for payload structure and signature validation. If your account is also [platform-enabled](/platforms/overview#add-on-platform-enablement) and you pass `X-PLATFORM-KEY`, charge events for your merchants' payments are additionally delivered to the webhook endpoints registered on your platform account — see [Unified webhooks](/apis/guide/platform-apis#unified-webhooks).

## Disconnecting

Merchants can revoke your app at any time from **Developers → Connected Apps** in their HitPay Dashboard. Revocation immediately invalidates all access and refresh tokens for that merchant.

There is no disconnect notification, so treat a `401 Unauthorized` response as the merchant having revoked access: mark the account as disconnected in your system and prompt the merchant to reconnect if needed.

Also note that regenerating your client secret or deleting your app invalidates the tokens of **all** connected merchants.

## Testing in sandbox

The full flow works in the [sandbox environment](/apis/guide/sandbox) with a separate sandbox app:

1. Create a [sandbox account](https://dashboard.sandbox.hit-pay.com/register) and build your app under **Developers → App Builder**.
2. Create a second sandbox account to play the role of the merchant connecting to your platform.
3. Use the sandbox hosts throughout: `https://dashboard.sandbox.hit-pay.com/oauth/authorize` for authorization and `https://api.sandbox.hit-pay.com/v1/open/oauth/token` for tokens.

## FAQs

<AccordionGroup>
  <Accordion title="How is this different from a direct API key integration?">
    A [direct API key integration](/platforms/overview#option-1-direct-api-key-integration) requires each merchant to generate and hand you their API key, which grants full account access. OAuth replaces the manual key exchange with a one-click authorization flow, gives merchants scoped (rather than full) access control, and lets them revoke your access without rotating their own keys. Either way, commissions and unified webhooks come from the separate [Platform Key](/apis/guide/platform-apis), which works with both.
  </Accordion>

  <Accordion title="Can one merchant connect multiple businesses?">
    Yes. Each authorization connects exactly one business (the merchant picks which during the flow). To connect another business, send the merchant through the authorization flow again and store the resulting tokens separately.
  </Accordion>

  <Accordion title="What happens if I request a scope my app hasn't been granted?">
    The authorization request is rejected. Only request scopes that have been approved for your app — you can see your app's granted scopes in its detail panel under Developers → App Builder.
  </Accordion>

  <Accordion title="Do access tokens expire?">
    Yes, after one year. Use the refresh token to obtain a new access token. If both have expired or been revoked, send the merchant through the authorization flow again.
  </Accordion>
</AccordionGroup>
