public function post(string $resource, array $payload): Promise {
        return call(function () use ($resource, $payload) {
            $uri = yield $this->getResourceUri($resource);

            $attempt = 0;
            $statusCode = null;

            do {
                $attempt++;

                if ($attempt > 3) {
                    throw new AcmeException("POST request to {$uri} failed, received too many errors (last code: ${statusCode}).");
                }

                $payload['resource'] = $payload['resource'] ?? $resource;

                $requestBody = $this->cryptoBackend->signJwt($this->accountKey, yield $this->getNonce($uri), $payload);
                $request = (new Request($uri, 'POST'))
                    ->withBody($requestBody);

                $this->logger->debug('Requesting {uri} via POST: {body}', [
                    'uri' => $uri,
                    'body' => $requestBody,
                ]);

                try {
                    /** @var Response $response */
                    $response = yield $this->http->request($request);
                    $statusCode = $response->getStatus();
                    $body = yield $response->getBody();

                    $this->logger->debug('Request for {uri} via POST has been processed with status {status}: {body}', [
                        'uri' => $uri,
                        'status' => $statusCode,
                        'body' => $body
                    ]);

                    $this->saveNonce($response);

                    if ($statusCode === 400) {
                        $info = json_decode($body);

                        if (!empty($info->type) && ($info->type === 'urn:acme:badNonce' || $info->type === 'urn:acme:error:badNonce')) {
                            $this->nonces = [];
                            continue;
                        }
                    } else if ($statusCode === 429) {
                        /**
                         * Hit rate limit
                         * @{link} https://letsencrypt.org/docs/rate-limits/
                         */
                        yield new Delayed(1000);
                        continue;
                    }
                } catch (Throwable $e) {
                    throw new AcmeException("POST request to {$uri} failed: " . $e->getMessage(), null, $e);
                } catch (Exception $e) {
                    throw new AcmeException("POST request to {$uri} failed: " . $e->getMessage(), null, $e);
                }

                return $response;
            } while (true);
        });
    }