A terminal's certificate is short-lived: it lasts 7 days by default, a lifetime set by the platform, and its expires_at says when it ends. Before then the terminal renews it over its current certificate: it asks for a new one at POST /v1/terminal/certificate_renewals, for the same key, with no Pairing Code and no attestation. This is for the app running on the terminal: a merchant's server never calls it.
When to renew
Section titled “When to renew”Renew once a day. A certificate can be renewed at any time while it is still honoured; there is no window to wait for. Renewing daily leaves the terminal days to spare if it is switched off or offline for a while.
A certificate that has expired cannot be renewed, since it no longer counts on any call. A terminal left off for longer than its certificate's lifetime is paired again, with a new Pairing Code from the operations team. So is one whose certificate was revoked, replaced or moved with the terminal to another store or merchant: see When a terminal is refused.
How it goes
Section titled “How it goes”- Make a new certificate signing request (PKCS#10, PEM), signed by the key the terminal was paired with, the one in its Android Keystore. Do not generate a new key: a new key needs a new Pairing Code. The subject is ignored.
- Send it over mutual TLS with the current certificate. The body is the CSR alone.
- Keep the new certificate and its chain with the key, and use the new certificate from the next call on.
curl https://terminal.api.example.com/v1/terminal/certificate_renewals \ --cert terminal-certificate.pem --key terminal-key.pem \ -H "Content-Type: application/json" \ -d '{"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBDzCBtgIBADAUMRIwEAYD...\n-----END CERTIFICATE REQUEST-----\n"}'The sample uses curl's --cert and --key to show the request; on the terminal, your app's TLS client presents the certificate and signs with the Keystore key.
{ "object": "terminal_certificate_renewal", "livemode": true, "terminal_id": "3f6c2a9e-8b41-4d7a-9e25-0c1b7d4f8a63", "certificate": "-----BEGIN CERTIFICATE-----\nMIIB9TCCAZugAwIBAgIU...\n-----END CERTIFICATE-----\n", "chain": "-----BEGIN CERTIFICATE-----\nMIIBvjCCAWSgAwIBAgIU...\n-----END CERTIFICATE-----\n", "expires_at": 1791604200}The answer is 201, sent with Cache-Control: no-store. certificate is the new one, for the same terminal and the same key, valid for up to 7 days from now: expires_at says when it ends. chain holds the certificates above it, its issuer first.
Switching to the new certificate
Section titled “Switching to the new certificate”Both certificates are honoured until the new one is first used. From the first call made with the new certificate, the old one is refused with 401 terminal_credential_refused. So store the new certificate before you use it, and keep the old one until the new one has answered a call.
A terminal session carries on across a renewal: heartbeat, resume and close it with the new certificate.
Retrying
Section titled “Retrying”If the answer was lost, send the same request again, with the old certificate and the same key: you get the same new certificate back, not a second one. This holds until the new certificate is first used.
If the platform was unavailable (503 service_unavailable), whether the certificate was renewed is not known: the platform may have made the new certificate before it failed. Retry the same request shortly, with the old certificate and the same key. If it was renewed, you get that new certificate back, not a second one; if not, it is renewed now. The old certificate keeps being honoured until the new one is first used, so a retry made with it still works.
Errors
Section titled “Errors”In the usual error envelope.
| Status | code | When |
|---|---|---|
| 400 | invalid_parameter | param is csr: the CSR is missing, is not a PEM certificate signing request, or is not signed by the key this terminal was paired with. Sign it with the paired key; a new key needs a new Pairing Code. |
| 401 | terminal_credential_refused | The current certificate does not count, or the terminal is suspended or retired. Retrying will not help: see When a terminal is refused. |
| 503 | service_unavailable | Renewal could not be completed just now, and it is not known whether a new certificate was made. Retry shortly with the same request, the old certificate and the same key. |