# Moving from v1 to v2

Source: <https://docs.gjold.com/notes/moving-to-v2>

v2 launches in early 2027, and v1 is supported for years after it, so move when it suits you. The objects stay what they were: payment links, transactions, subscribers, seq, and pings. What changes is how you name them, how strictly we read a request, and how clearly an error says what went wrong.

Until v2 launches, its pages are its spec, and may change.

## Requests

v2 names the shop in every URL, and an object by its kind and ID, where v1 takes the shop from the key:

| v1 | v2 |
|---|---|
| `POST /v1/new` | [`POST /v2/{shopid}:pay/new`](https://docs.gjold.com/v2/payment-links/create) |
| `POST /v1/new` with `"subscriber"` | [`POST /v2/{shopid}:sub/new`](https://docs.gjold.com/v2/subscribers/create) |
| `POST /v1/transactions/{trnid}/capture` | [`POST /v2/{shopid}:trn:{trnid}/capture`](https://docs.gjold.com/v2/transactions/capture) |
| `POST /v1/transactions/{trnid}/refund` | [`POST /v2/{shopid}:trn:{trnid}/refund`](https://docs.gjold.com/v2/transactions/refund) |
| None: a void is made in the dashboard | [`POST /v2/{shopid}:trn:{trnid}/void`](https://docs.gjold.com/v2/transactions/void) |
| `POST /v1/subscribers/{subid}/charge` | [`POST /v2/{shopid}:sub:{subid}/charge`](https://docs.gjold.com/v2/subscribers/charge) |
| `POST /v1/subscribers/{subid}/renew` | [`POST /v2/{shopid}:sub:{subid}/renew`](https://docs.gjold.com/v2/subscribers/renew) |
| None | [`DELETE /v2/{shopid}:pay:{payid}`](https://docs.gjold.com/v2/payment-links/delete) |
| None | [`DELETE /v2/{shopid}:sub:{subid}`](https://docs.gjold.com/v2/subscribers/delete) |
| `GET /v1/seq/{seq}` | [`GET /v2/{shopid}:seq:{seq}`](https://docs.gjold.com/v2/synchronization/seq) |

See v2's [URLs](https://docs.gjold.com/v2/requests#urls).

## Keys

A v1 key is `{shopid}:{secret}`. A v2 key starts with whose it is, and the key's own number: `s{shopid}#{keyid}:{secret}` for a shop's key, and there are keys for users and partners too. Each v2 key has its own permissions and its own ping URL, where a v1 shop has one ping URL for all its keys. See v2's [Authentication](https://docs.gjold.com/v2/authentication).

## Stricter requests

v1 reads a request leniently, and makes the best of what it can't use. v2 refuses it, so that a mistake shows at once and not in the payments:

- A field of the wrong type, or `null`, is ignored in v1, and an error in v2: see v2's [Request bodies](https://docs.gjold.com/v2/requests#request-bodies).
- `"orderid"` is optional in v1, and required in v2.
- An amount with more decimals than the currency has is cut down in v1, as `"10.999 DKK"` to 10.99 DKK, and an error in v2: see v2's [Amounts](https://docs.gjold.com/v2/amounts).
- A `"lifetime"` that is too short, too long, or unreadable becomes the nearest one v1 allows, or an hour, and is an error in v2, which takes `"5m"` to `"30d"`.
- `"index"` may be left out of a capture or a refund in v1, which reads it as 0, and is required in v2.
- v1 accepts a payment that the bank authorizes only in part, for what it authorized; v2 declines it, so a transaction is always for the whole amount. In v1, check `totals.authorized`, as [What was authorized](https://docs.gjold.com/notes/orders#what-was-authorized) says.

## Answers

- Create payment link answers with the link's `"id"` beside its `"url"` in v2, so that you can delete the link, and match it to its transaction.
- v1 answers most failures with `500`, and its message says what failed. v2 answers each kind with its own status: `404` for an object that doesn't exist, `409` for a conflict, such as `409 index mismatch`, `402` for a declined charge, and `410` for a deleted subscriber. See v2's [Errors](https://docs.gjold.com/v2/errors).
- A declined charge in v2 says whether to try again: its message starts with `transient` or `permanent`. See [When a charge fails](https://docs.gjold.com/notes/subscribers#when-a-charge-fails).
- `Idempotency-Status: OK` is on every answer to a request with a key in v1, and marks only a replay in v2.
- In seq, an act says who made it with `"who"`, a key's or a user's ID, in v2, where v1 has `"uid"` and `"apikey"`. A transaction's card is always under `method.card` in v2, where v1 names the object for the method, as `method.applepay`. See v2's [transaction object](https://docs.gjold.com/v2/transactions#the-transaction-object).

## How to move

1. Get v2 keys, and give each a ping URL.
2. Change your requests' URLs, and send `"orderid"` and `"index"` always, and fields of the types that v2's reference gives.
3. Branch on v2's status codes where you parsed v1's messages, and on `transient` and `permanent` for a failed charge.
4. Read seq's acts by `"who"`, and the card from `method.card`.
5. Test it all in the test environment, as for a first integration: [Before going live](https://docs.gjold.com/notes/checklist).
