Skip to content

Getting delivery notifications

Translation takes hours to days. You have two ways to find out when it's done: poll, or let Eurotext call you.

Option A: webhook (preferred if you can receive one)

Pass a url when you create the project:

$client->createProject('Spring catalogue', type: 'order',
    webhookUrl: 'https://my.app/api/eurotext/webhook');

Eurotext then POSTs to that URL on project status updates, so you don't poll at all. Treat the callback as a "something changed, go look" signal: on receipt, re-read the project with getProject() and act on that authoritative state.

Also make the endpoint defensive: verify it's really Eurotext (shared secret in the URL or a header you agree on), respond 2xx fast, and do the actual work async. A webhook you can't receive (local dev, no public URL) is useless — fall back to polling there.

Option B: polling (always works)

Store the project id, then check on a schedule from a cron job or queue worker — never from a web request.

// e.g. a Symfony console command run every 30 min by cron
foreach ($this->openProjects() as $row) {
    $project = $client->getProject($row->eurotextProjectId);
    $status  = ProjectStatus::fromProject($project);

    match ($status) {
        ProjectStatus::DELIVERED => $this->importAndClose($row, $project),
        ProjectStatus::FAILED    => $this->flagForReview($row),
        ProjectStatus::IN_PROGRESS,
        ProjectStatus::PENDING   => null, // check again next tick
    };
}

A polling policy that holds up in production

  • Interval: 30 minutes is plenty. Delivery is measured in hours; polling every minute just burns rate limit for nothing.
  • Backoff: if a poll fails (5xx/timeout), back off exponentially (30m → 1h → 2h) rather than hammering. A 4xx like 404 means the project is gone — stop polling it, don't retry.
  • Give up eventually: set a deadline (e.g. 14 days) after which you stop polling and raise an alert for a human. Otherwise a stuck project polls forever. Store submitted_at and check it each tick.
  • Partial delivery: items finish independently. You can import the ones in finished early and keep polling for the rest — just record which item ids you've imported so you don't double-write (see 12-idempotency.md).
  • Re-fetching is safe: GET /project and GET /item are read-only, so polling the same project repeatedly costs nothing and changes nothing. The non-idempotent part is the write-back into your own system — make that idempotent on your side.

Belt and braces

Registering a webhook and running a slow safety-net poll (say every few hours) is a reasonable setup: the webhook gives you fast turnaround, the poll catches anything a missed or failed callback would otherwise strand.