# Authentication

Source: <https://docs.gjold.com/v2/authentication>

Every request authenticates with an API key, sent with HTTP Basic authentication. A key belongs to a shop, a user, or a partner, and may make only the requests it has permission for.

## The Authorization header

Send the key as the credentials of [HTTP Basic authentication](https://www.rfc-editor.org/rfc/rfc7617), base64-encoded:

```
Authorization: Basic base64({apikey})
```

A key contains a colon, which separates its ID from its secret, as Basic authentication separates a user name from a password. So curl's `-u {apikey}` sends it as it is, and so does any HTTP library that takes a user name and a password: give it the ID as the user name and the secret as the password.

There is no other way to authenticate: no key in the URL or the body, and no cookies.

## API keys

A key starts with whose it is, by a letter and an ID, then the key's own number, and its secret after the colon:

| Key | Belongs to |
|---|---|
| `s{shopid}#{keyid}:{secret}` | A shop. It can act on that shop only. |
| `u{userid}#{keyid}:{secret}` | A user. It can act on every shop the user has access to, as far as both the key and the user's role in the shop allow. |
| `p{partnerid}#{keyid}:{secret}` | A partner. It can act on every shop that the partner owns. |

The part before the colon is the key's ID, and its `{keyid}` is unique only among its owner's keys. Everything done with a key, through the API or the dashboard, is recorded with its ID: a capture made with key 1 of shop 1379 has `"who": "s1379#1"` in the transaction's [acts](https://docs.gjold.com/v2/transactions#acts).

Keep a key's secret on your server. A key in a browser or an app can be read by anyone who has the page or the app, and used to capture, refund, and charge as you.

## Permissions

A key has permission for some or all of these, and a request that its key lacks permission for fails:

| Permission | Requests |
|---|---|
| `payid` | [Create payment link](https://docs.gjold.com/v2/payment-links/create), [Create subscriber](https://docs.gjold.com/v2/subscribers/create), and [Renew subscriber](https://docs.gjold.com/v2/subscribers/renew), which all create a link, and [Delete payment link](https://docs.gjold.com/v2/payment-links/delete) |
| `seq` | [Seq](https://docs.gjold.com/v2/synchronization/seq) |
| `capture` | [Capture transaction](https://docs.gjold.com/v2/transactions/capture) |
| `refund` | [Refund transaction](https://docs.gjold.com/v2/transactions/refund) |
| `void` | [Void transaction](https://docs.gjold.com/v2/transactions/void) |
| `charge` | [Charge subscriber](https://docs.gjold.com/v2/subscribers/charge) and [Delete subscriber](https://docs.gjold.com/v2/subscribers/delete) |

A key for a server that only creates links and reads seq needs nothing more, and can't refund if it leaks.

## Pings

A key with a ping URL gets a [ping](https://docs.gjold.com/v2/synchronization/ping) whenever something changes in a shop that the key can act on: one shop for a shop's key, and every shop the user or partner has for theirs. You set the ping URL in the dashboard.

## Errors

A request that fails to authenticate is answered with:

```
HTTP/1.1 401 Unauthorized
Content-Type: text/plain

Unauthorized
```

It is the same, whatever the reason, so that it tells an attacker nothing:

- The `Authorization` header is missing, or is not `Basic`.
- The credentials are not valid base64, or not of a key's form.
- The key does not exist, or its secret is wrong.
- The key is a shop's, and the URL names another shop.
- The key, or the user it belongs to, lacks permission for the request or has no access to the shop.

Don't retry a `401`: it will fail the same way until the key or its permissions change. We check the key before we read the body, so a `401` means that nothing was done.
