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

# Authentication

> Per-terminal HTTP Basic credentials — how to get them, use them, and rotate them.

Every request to the Charge API carries HTTP Basic credentials belonging to a single terminal.

```bash theme={null}
curl -u 'term_a7f3k9d2:vpt_Kd8sPq2mXn5wLr7tYv1zBc4hGj6fNa0e' \
  https://api.vibepay.mn/v1/transactions?limit=1
```

Or set the header yourself:

```http theme={null}
Authorization: Basic dGVybV9hN2Yzazlk...
```

## Where credentials come from

Terminals are created in the [merchant dashboard](https://merchant.vibepay.mn) under **Terminals**.
There is no API to provision one — a person with access to your merchant account has to do it.

| Part     | Shape                  | Notes                                                  |
| -------- | ---------------------- | ------------------------------------------------------ |
| Username | `term_` + 8 characters | Safe to log. Identifies the till.                      |
| Password | `vpt_` + 32 characters | A secret. Shown **once**, at creation and at rotation. |

Create one terminal per physical till or per running POS instance. That is what makes
`GET /v1/transactions` useful for end-of-day reconciliation, and it means losing one device does
not force you to re-credential the whole store.

<Warning>
  Treat the password like a card-network key. It can take money from customers' wallets. Do not
  put it in a mobile app binary you ship to stores, in a browser bundle, in a git repository, or
  in a support ticket.
</Warning>

## What the merchant dashboard can do

<CardGroup cols={3}>
  <Card title="Create" icon="plus">
    Issues a new username and password. The password is displayed once.
  </Card>

  <Card title="Rotate" icon="arrows-rotate">
    Issues a new password for the same username. **The old one stops working immediately** — there
    is no grace period, so roll it out to the device first.
  </Card>

  <Card title="Suspend" icon="ban">
    Blocks the terminal without deleting its history. Use this the moment a device goes missing.
  </Card>
</CardGroup>

## What the merchant identity is *not*

You never tell the API which merchant you are. Your merchant, your tax registration number, and
your terminal are all resolved from the credentials you authenticated with, and there is no
request field that can override them.

That is why a compromised terminal password can only ever take payments *to your own merchant
account* — where they are visible in your dashboard and reversible — and can never read or refund
another merchant's transactions.

## Every authentication failure looks the same

```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="vibepay-terminal"
Content-Type: text/plain; charset=utf-8

unauthorized
```

You get exactly this whether the header was missing, the username was unknown, the password was
wrong, or the terminal was suspended. The API will not tell you which, because that would let
someone enumerate valid usernames.

**So treat any `401` as "these credentials are dead."** Stop retrying, stop the sale, and prompt
staff to re-pair the terminal. Retrying a `401` never helps and looks exactly like an attack.

## There is no verify endpoint

To check a credential pair, ask for a single transaction:

```bash theme={null}
curl -sf -u "$USER:$PASS" 'https://api.vibepay.mn/v1/transactions?limit=1' > /dev/null \
  && echo "credentials OK"
```

`GET /health` is **not** a credential check — it is unauthenticated and answers `200` no matter
what you send.

<Card title="Now take a payment" icon="qrcode" href="/charge" horizontal>
  The charge request, field by field.
</Card>
