# Ping

Source: <https://docs.gjold.com/v2/synchronization/ping>

A request we send you when a shop's sequence has grown, so that you call seq. It says which shop, and where the sequence ends now, and nothing else.

## When we ping

You give an API key a ping URL in the dashboard, and we ping it about every shop that the key can act on: one shop for a shop's key, and every shop that the user or partner has for theirs. We ping:

- As soon as a shop's sequence grows: a payment, an act, or a change to a subscriber, whoever made it. Changes that come together give one ping, with the latest `"seq"`.
- Every 5 minutes after the last ping, whether anything changed or not, with the `"seq"` as it is then.

A ping that fails is not sent again: the next change, or the next 5 minutes, brings another. Pings can arrive out of order, and more than once with the same `"seq"`.

## Request

**POST** {your ping URL}

We connect to your URL's host, on its port, or 443 for `https` and 80 for `http`. With `https`, your certificate must be valid for the host, as a browser would require: we don't ping a host whose certificate fails. We don't follow redirects.

### Headers

| HTTP header | Description |
|---|---|
| `Content-Type` | `application/json; charset=UTF-8` |
| `Content-Length` | The length of the body. |
| `X-Signature` | The body's signature, as base64: see [Signature](https://docs.gjold.com/v2/synchronization/ping#signature). |
| `Connection` | `close`. Each ping has a connection of its own. |

### Body

| Field | Type | Description |
|---|---|---|
| `shopid` | integer | The shop whose sequence has grown. |
| `seq` | integer | Where the shop's sequence ends now: the `"seq"` that [seq](https://docs.gjold.com/v2/synchronization/seq) returns when you have read all of it. |

```json
{"shopid":1234,"seq":164}
```

## Signature

`X-Signature` is the base64, with padding, of the HMAC-SHA256 of the body as sent, with the API key as the HMAC's key: the whole key, as you give it to Basic authentication before base64, such as `s1234#1:FhnIJVS2ZgRi2B35...`. Check it before you trust the ping:

```
want := Base64(HMAC-SHA256(key: apikey, message: rawbody))
if not ConstantTimeEqual(want, headers["X-Signature"]) then
    return 403
end if
ping := JSONDecode(rawbody)
if ping.seq > LoadSeq() then
    WakeSynchronizer(ping.seq)
end if
return "ok"
```

Sign the bytes as received, before any parsing, and compare in constant time. [Receiving pings](https://docs.gjold.com/notes/pings#checking-the-signature) has the mistakes to avoid.

A ping carries no data but the shop's ID and a number, so a forged one can do no worse than make you call seq. The signature lets you skip even that.

## Response

Answer with `200 OK` and the body `ok`, at once. We give a ping 7 seconds from connecting until the first byte of your answer, and then hang up, so synchronize after answering, or in another process: see [Synchronizing with seq](https://docs.gjold.com/notes/synchronization#a-single-worker).

We don't act on your answer: a ping that you answer with an error, or not at all, is not sent again, as the next one comes anyway.
