# Requests

Source: <https://docs.gjold.com/v1/requests>

A request names what it acts on in its URL, and says what to do with it in its body, a JSON object. The shop is the API key's.

## Environments

| Host | Environment |
|---|---|
| `api.gjold.com` | Production, where payers pay for real. |
| `api.gjold.dev` | The test environment, for developing integrations, where no money moves. |

The two are not connected: an account, a key, or an ID on one means nothing on the other. Only we create accounts in the test environment: [write to us](mailto:support@gjold.com) and say what you need one for.

## URLs

A request's URL is `https://api.gjold.com/v1/`, then the request's path. A path that names a transaction or a subscriber has its ID, and then the action:

```
https://api.gjold.com/v1/new
https://api.gjold.com/v1/seq/{seq}
https://api.gjold.com/v1/transactions/{trnid}/{action}
https://api.gjold.com/v1/subscribers/{subid}/{action}
```

There is no shop ID in the URL: a request acts on the shop of its [API key](https://docs.gjold.com/v1/authentication#api-keys).

A URL that fits no request is answered `404 Not Found`, and a known URL with the wrong method, such as a `GET` of `/v1/new`, `405 Method Not Allowed`.

### IDs

| ID | What it names |
|---|---|
| `{trnid}` | A transaction, which a paid link or a charge of a subscriber creates: its `"id"` in [seq](https://docs.gjold.com/v1/synchronization/seq)'s changes, or in the answer to [Charge subscriber](https://docs.gjold.com/v1/subscribers/charge#response). |
| `{subid}` | A subscriber: its `"id"` in seq's changes. |
| `{seq}` | A number in the shop's sequence of changes: see [Seq](https://docs.gjold.com/v1/synchronization/seq). |

A payment link has no ID in v1: [Create payment link](https://docs.gjold.com/v1/payment-links/create) answers with its URL alone, and seq tells you of the transaction that paying it creates.

Your shop ID is the part of your API key before the colon. Shop, transaction, and subscriber IDs are positive integers, written in decimal without leading zeros, and never reused. A shop's transactions are numbered from 1 in the order they were created, and so are its subscribers. Store an ID as a 64-bit integer, or as a string.

## Request bodies

A `POST` request has a body: one JSON object, encoded as UTF-8, of at most 32 KiB. We don't read `Content-Type`, but send `application/json`, which is what it is.

The body must be valid JSON. If it isn't, the request fails with `400 invalid json in {where}: {why}`, where `{where}` is the path of the field at fault, as in `items[1].total`, or `json root object` for the body as a whole. See [Errors](https://docs.gjold.com/v1/errors#invalid-json).

v1 is lenient with what it can read, and quiet about what it can't:

- **Unknown fields** are ignored, so that a field that you misspelled goes unnoticed. Check your spelling against the field tables.
- **Types** are as each field table gives them. A field of another type, or `null`, is ignored, as if you had left it out, and is not an error. A misspelled field and a mistyped one fail the same way: the request goes through without them.
- **Strings** may contain any Unicode text, which we clean up before we store it: each white space character, such as a tab or a newline, becomes a space, other control characters are removed, and spaces at the ends are trimmed. A string that is empty after that is the same as no string at all. Create payment link, Create subscriber, and Renew subscriber also take a number or a boolean for a string, and drop bytes that are not UTF-8, where the other requests fail with `invalid utf in string`.
- **Integers** are JSON numbers without a fraction or an exponent, so `2`, not `2.0` or `"2"`.
- **Amounts** are strings, as `"99.95 DKK"`, never JSON numbers. See [Amounts](https://docs.gjold.com/v1/amounts).

## Responses

A request that succeeds is answered with `200 OK` and a JSON object, which is `{}` for capture and refund, which only act. Its `Content-Type` is `application/json`. A request that fails is answered with another status and a line of text. See [Errors](https://docs.gjold.com/v1/errors).

Every response has these headers:

| HTTP header | Why |
|---|---|
| `Cache-Control: no-store` | No answer is to be cached, by you or anything in between. |
| `Strict-Transport-Security: max-age=63072000` | Browsers and clients that honour it use HTTPS only, for two years. |
| `X-Content-Type-Options: nosniff` | The `Content-Type` is what it says. |

## Compatibility

The API's version is in its URL, `/v1/`. Within a version, we may add to the API, but not change or take away:

- We may add requests, optional request fields, response fields, and new values of fields that list their values, such as a change's `"type"`, a transaction's `"act"`, a card's `"brand"`, or a transaction's `"services"`. Write your client to skip what it doesn't know.
- We may add error messages, and reword them. Branch on the status, not on the message.
- We don't remove or rename a field, change its type or meaning, or make an optional field required.

What these rules don't allow is in v2, at `/v2/`, which launches in early 2027. v1 stays beside it, and is supported for years after.
