# Billing, invoices and status

What happens between clicking buy and the key switching on, where the invoice comes from, and how to tell whether the data behind the API is current.

**What this covers:** Checkout; Invoices and credit notes; Fiscal transmission (Greece, myDATA); Status — is the data current?.

**Assumed knowledge:** [Plans](./account-plans.md).

**Canonical HTML:** https://jobopportunitiesapi.org/docs/account/billing  
**Machine-readable index:** https://jobopportunitiesapi.org/docs/ai/index.md  
**Last verified:** 2026-08-22  
**Superseded by:** the live API at https://api.jobopportunitiesapi.org and its spec at https://jobopportunitiesapi.org/openapi.json — where this file and the API disagree, the API is right.

---

<a id="checkout-flow"></a>

## 1. Checkout

Pick a plan, enter your details, pay by card. The key is created immediately in a pending state and switches on when the payment confirms.

### 1.1 In depth

Card payments are handled by **Viva**, the payment service provider; the card details are entered on their page and never reach this site. The site's own checkout collects what an invoice needs — name, email, country, and a VAT number if you have one — and hands the order to the gateway.

The key row is written before the payment completes, in a `past_due` state. That is why a key can appear on your dashboard showing *Awaiting payment*: it is not an error, and it needs nothing from you beyond finishing the payment. When the gateway confirms, a webhook activates it.

> **The plan list on the checkout page is the live one** — It is read from the same table the API validates against, so the page cannot offer a plan the API would refuse. Free plans are filtered out — Explore is obtained by asking for a key, not by paying zero euros through a card form. If the price list cannot be loaded, the page says so and refuses to start an order rather than showing a form that cannot complete.

### 1.2 Exact contract

1. `/pricing` or `/api` → **Get access** → `/checkout?plan=<plan>`.
2. The form posts to the site's own `/api/checkout`, which forwards to `POST /public/checkout` on the API.
3. The API validates the plan against the live plans table, computes VAT for your country, writes a pending key, and creates an order at the gateway.
4. You are redirected to the gateway's card page.
5. On success you land on `/checkout/done`; on failure, `/checkout/failed`. Neither page is what activates the key.
6. The gateway's webhook activates the key. This is the authoritative step — the redirect is only a redirect.

> **The country field is the ledger's own list** — The checkout's country selector is built from the same facet table the API validates against, filtered to countries with meaningful volume, so the form cannot offer a value the order call would reject.

A legacy webhook path for a previous provider (Revolut) still exists in the API and is retained for historical orders. Live checkout does not use it.

**See also**

- [Invoices and credit notes](./account-billing.md#invoices)
- [Every control on the dashboard](./account-sign-in.md#dashboard-tour)
- [Every form, and where it posts](./website-pages.md#site-forms)

<a id="invoices"></a>

## 2. Invoices and credit notes

An invoice is issued for every completed order and reached by an unguessable link, so it works from an email with no sign-in.

### 2.1 In depth

The invoice URL carries a token in the path (`/invoice/<token>`) rather than requiring a session, because the person opening it is usually doing so from a mail client — often somebody in finance who has no account here. A challenge or a login wall in front of that link makes it a dead link.

A refund or a correction produces a **credit note** rather than an edit to the original document. That is a legal requirement, not a preference: an issued invoice is not modifiable after the fact.

For anything the dashboard does not cover — a copy, a VAT number added after the fact, a purchase-order reference — [/contact?topic=billing](https://jobopportunitiesapi.org/contact?topic=billing) reaches a person.

### 2.2 Exact contract

- **VAT** — Computed at checkout from your country and whether you supplied a VAT number. Business customers in other EU member states with a valid number are reverse-charged.
- **Currency** — EUR throughout.
- **Document types** — Invoice for orders; credit note for refunds and corrections. Retail and business documents are issued under different classifications.
- **Access** — `/invoice/<token>` — no session required, token in the path.
- **Copies** — Ask at `/contact?topic=billing`.

> **What appears on your card statement** — The payee shown by your bank is the merchant of record registered with the payment provider, which may not read as “Job Opportunities API”. If a line on your statement is unfamiliar and you think it is ours, send the date and amount to `/contact?topic=billing` and it will be identified rather than guessed at.

**See also**

- [Fiscal transmission (Greece, myDATA)](./account-billing.md#mydata)
- [Checkout](./account-billing.md#checkout-flow)
- [Cancelling](./account-sign-in.md#cancel-subscription)

<a id="mydata"></a>

## 3. Fiscal transmission (Greece, myDATA)

Invoices are transmitted to the Greek tax authority's myDATA platform. It affects what an invoice must contain, not what you have to do.

### 3.1 In depth

The business is registered in Greece, so every issued document is transmitted to AADE's myDATA platform. For a customer this is invisible; it matters here only because it constrains the invoice, and two of those constraints occasionally surprise people.

- **A name is required on a retail document** — The customer is a person, not a VAT number. The tax authority enforces this, so the checkout asks for a name even when you supply a company VAT number.
- **Corrections are credit notes** — A transmitted document cannot be edited. A correction is a new, related document.

### 3.2 Exact contract

Documents are classified as business-to-business or retail, with the corresponding myDATA income classification and document type, and credit notes are filed as related documents against the original. Payment method is recorded as card. None of this requires anything from you; it is documented because a customer asking “why does this invoice look like that” deserves an answer that is not “because the system does it”.

**See also**

- [Invoices and credit notes](./account-billing.md#invoices)
- [The legal pages](./website-legal.md#site-legal-pages)

<a id="status-page"></a>

## 4. Status — is the data current?

/status answers whether the ledger is current, measured from the ledger itself, not whether the website replied to a ping.

### 4.1 In depth

A green dot on a conventional status page proves the site answered a probe. That is not the question a data buyer has. The question is whether the data moved — how much was re-verified in the last day, how much was added, how much was delisted, and how old the oldest verification is. Those are what [/status](https://jobopportunitiesapi.org/status) reports, and all of them are read from the ledger.

The same figures are available programmatically at `/public/status` (keyless), and the deeper freshness report at [`/public/freshness`](./endpoints-meta.md#endpoint-meta-freshness).

> **There is no public error-budget or incident-history page** — `/status` is a freshness report, not an uptime history: it does not publish past incidents, an SLA, or an error budget. Saying so is more useful than implying otherwise. For a specific incident, ask at [/contact](https://jobopportunitiesapi.org/contact).

### 4.2 Exact contract

| What `/status` reports | Read it as |
| --- | --- |
| `state` | `ok`, `degraded`, or worse — computed from the figures below, not from a probe. |
| `live_listings` | Rows currently servable. |
| `reverified_last_24h` | Rows re-confirmed at their source in the last day. The main sign of a healthy refresh. |
| `added_last_24h` | New rows in the last day. Absent — shown as `—` — where the stored snapshot predates the measurement. |
| `delisted_last_24h` | Rows that left in the last day. |
| `oldest_verification` | How stale the least recently checked row is. |
| `last_projection` | When the served set was last rebuilt. |

A missing figure renders as `—` rather than as `0`, deliberately: a real zero and “not measured yet” must not look alike. Every number on that page comes from an endpoint that can legitimately not have measured something yet.

**See also**

- [Freshness — measured_at, stale, and the refresh cycle](./ledger-coverage.md#freshness)
- [GET /v1/meta/freshness](./endpoints-meta.md#endpoint-meta-freshness)
- [Every route on the site](./website-pages.md#site-marketing-pages)

---

## Where to go next

This file is part of **Account & billing**. Others in the same group:

- [Plans](./account-plans.md) — What each plan includes, rendered from the live price list, and what actually distinguishes them — which is records and entitlements, not features.
- [The record meter](./account-record-meter.md) — The licence is on rows delivered, not on requests made. This is the most commonly misunderstood mechanic here, and it changes how you write your client.
- [Sign-in and the dashboard](./account-sign-in.md) — Passwordless sign-in, every control on the account page, and what rotating or cancelling a key actually does.

Always useful:

- [index.md](./index.md) — the map of every file here
- [BUILD-A-SITE.md](./BUILD-A-SITE.md) — the paste-whole brief for building against this API
- [quickstart.md](./quickstart.md) — zero to a first authenticated response
- [api-errors.md](./api-errors.md) — every status code and whether to retry it
