# Before going live

Source: <https://docs.gjold.com/notes/checklist>

Each item is a failure we have seen in production, and links to where the problem is explained. Go through them all.

## Keys

- The API key is only on your server, never in a browser or an app. See [Authentication](https://docs.gjold.com/v1/authentication#api-keys).
- Each server's key has only the permissions it needs. See [Permissions](https://docs.gjold.com/v1/authentication#permissions).
- In v1, pings are checked with the shop's first API key, which signs them. See [Checking the signature](https://docs.gjold.com/notes/pings#checking-the-signature).
- You use your production account's key and shop ID with `api.gjold.com`, and the test account's with `api.gjold.dev`, never mixed.

## Synchronization

- Orders are marked as paid by synchronization, never by the success page. See [Orders and payment links](https://docs.gjold.com/notes/orders#the-success-page-is-no-proof).
- A change is applied only if its `"rev"` is higher than the one you have, in the same database transaction as the check. See [Applying a change](https://docs.gjold.com/notes/synchronization#applying-a-change-the-higher-revision-wins).
- Only one synchronization runs at a time, under a lock that a crash releases, and one that finds the lock taken waits for it. See [One synchronization at a time](https://docs.gjold.com/notes/synchronization#one-synchronization-at-a-time).
- The `"seq"` is stored after the changes of its response are applied, never before, and never lowered.
- Changes of types and fields you don't use are skipped, not errors. See [Compatibility](https://docs.gjold.com/v1/requests#compatibility).
- A timer synchronizes every few minutes, in case a ping is lost. See [When pings stop coming](https://docs.gjold.com/notes/pings#when-pings-stop-coming).

## Pings

- The signature is checked over the raw body, with a constant-time comparison. See [Checking the signature](https://docs.gjold.com/notes/pings#checking-the-signature).
- The handler answers `ok` at once, and hands the work to a worker, or does it under a lock that it waits for, after we hang up.

## Requests that move money

- Every capture, refund, charge, and v2 void has an `Idempotency-Key`, random, stored before the first try, and reused for each retry. See [Retries and idempotency](https://docs.gjold.com/notes/retries).
- An act always sends the `"index"`, from the transaction as you last read it, and a stale index leads to a new read, not a blind retry.
- In v1, a `500` leads to a synchronization before anything is tried again, as v1 answers most failures with it.
- Errors are logged whole, with the status and the message.

## Payments

- Each order has its own `"orderid"`, always sent, and one live link at a time. See [One link per order](https://docs.gjold.com/notes/orders#one-link-per-order).
- In v1, a transaction's `totals.authorized` is checked against the order before it is delivered, as v1 accepts partial authorizations. See [What was authorized](https://docs.gjold.com/notes/orders#what-was-authorized).
- You capture when you ship, and within the card schemes' time limit for the authorization. See the knowledge base's [Authorizations](https://docs.gjold.com/learn/authorizations).
- The payment window opens by redirect, or in the system's browser view in an app, never in a frame. See [Websites and apps](https://docs.gjold.com/notes/payment-window).

## Subscribers

- One subscriber per payer, renewed rather than created again. See [One subscriber per payer](https://docs.gjold.com/notes/subscribers#one-subscriber-per-payer).
- A failed charge is looked for in seq before it is retried. A v2 `permanent` failure, or an expired card, is never retried, and any other failure at most once a day, five times in all. See [When a charge fails](https://docs.gjold.com/notes/subscribers#when-a-charge-fails).
- Payers are asked to renew before their card expires.
