Gratias

Fiscal Classification API

Classify a monthly compensation situation against per-country tax rules. The engine evaluates only the inputs you send: it never reads establishment or individual data, and it exposes no amounts from the platform. Results are informational and are not tax advice.

Authentication

Every request must carry an API key in the Authorization header using the Bearer scheme. Keys are issued from the Gratias back-office and shown only once at creation. A key must hold the fiscal:classify scope to call the classification endpoint.

Authorization: Bearer grt_live_xxxxxxxxxxxx.xxxxxxxxxxxxxxxx

Each authenticated call counts against the key's daily quota. Once the quota is reached, further calls return 429 until the next UTC day.

POST /api/public/fiscal/classify

Send the situation to classify as a JSON body. All fields are inputs you provide; none are read from Gratias data.

Request body

FieldTypeDescription
countrystringEstablishment jurisdiction. One of: FR, ES, US, GB, IT, GR.
yearintegerCalendar year (2000-2100).
monthintegerCalendar month (1-12).
monthlyBaseCentsintegerMonthly base compensation in integer cents, excluding gratuities. A value you provide.
tipsCentsintegerGratuities for the month in integer cents. A value you provide.

Example request

curl -X POST https://your-domain.example/api/public/fiscal/classify \
  -H "Authorization: Bearer grt_live_xxxxxxxxxxxx.xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "FR",
    "year": 2027,
    "month": 3,
    "monthlyBaseCents": 200000,
    "tipsCents": 40000
  }'

Response

FieldTypeDescription
statusKindstringRegime nature: exempt, standard, reduced, deductible or self_assessment.
ruleCodestring | nullStable identifier of the matched rule.
legalRefstring | nullLegal reference for the matched rule.
disclaimerstringInformational notice returned with every result.

Example response

{
  "statusKind": "exempt",
  "ruleCode": "FR_EXO_2026_S2",
  "legalRef": "LF 2026 art. 5; revalorisation SMIC 1er juin 2026",
  "disclaimer": "This classification is derived solely from the inputs you provided. It is not tax advice and does not read any establishment or individual data. Confirm with a qualified local tax professional before relying on it."
}

Error codes

Errors return a JSON body with an error message and a stable code. Validation errors (400) also include an issues array describing the offending fields. No internal detail is ever disclosed.

StatusCodeMeaning
400invalid_requestThe request body failed validation (see issues).
401invalid_keyMissing, invalid, inactive or revoked API key.
403insufficient_scopeThe key lacks the "fiscal:classify" scope.
429rate_limitedDaily request quota exceeded (see Retry-After).
500internal_errorUnexpected server error.

Gratitude Kit (embedded thank-you journey)

The Gratitude Kit lets a chain application embed a house's thank-you journey directly inside its own experience (an overlay or an iframe). The guest chooses an amount and pays without leaving the host app.

The payment is always a direct debit from the guest to the employee's wallet through the Gratias PSP. The host application never touches the funds and never receives any individual data: no amount, no employee, no balance.

Requirements

GET /api/public/embed/context

Called from your backend to discover the embedding configuration for your key. Authenticate with the key in the Authorization header (Bearer scheme) and pass the embedding origin in the Origin header (or an ?origin= query parameter). The response carries only technical embedding facts.

curl "https://your-domain.example/api/public/embed/context" \
  -H "Authorization: Bearer grt_live_xxxxxxxxxxxx.xxxxxxxxxxxxxxxx" \
  -H "Origin: https://app.your-chain.example"

Response

FieldTypeDescription
allowedOriginstringThe normalized host-app origin that is allowed to embed (the caller origin).
appUrlstringPublic base URL of the Gratias app that serves the thank-you journey.
tipPathTemplatestringPath template of the journey to frame, with a {token} placeholder.
frameAncestorsHintstringSuggested value for your own frame-ancestors / CSP configuration.
noticestringReminder that the payment is a direct guest-to-employee debit; the host app never touches funds.

Error codes

StatusCodeMeaning
400invalid_requestMissing or invalid embedding origin (Origin header or ?origin=).
401invalid_keyMissing, invalid, inactive or revoked API key.
403insufficient_scopeThe key lacks the "embed:tip" scope.
403origin_not_allowedThe origin is not in this key's allowlist.
429rate_limitedDaily request quota exceeded (see Retry-After).
500internal_errorUnexpected server error.

Integration snippet

Paste the following web component in your host app. It defines a <tacitapay-thankyou> element that mounts the journey in an iframe on the Gratias origin, so the settlement happens on our PSP. Never paste your key secret: the snippet only references the key prefix.

<!-- Gratias: parcours de remerciement embarque. Cle: grt_live_xxxxxxxxxxxx -->
<!-- D49: le paiement est un debit DIRECT du client vers le wallet du salarie via -->
<!-- notre PSP. Cette app ne touche jamais les fonds. Ne collez jamais votre secret ici. -->
<script>
(function () {
  if (customElements.get("tacitapay-thankyou")) return;
  var BASE = "https://gratias.io";
  customElements.define(
    "tacitapay-thankyou",
    class extends HTMLElement {
      connectedCallback() {
        var token = this.getAttribute("token") || "";
        var frame = document.createElement("iframe");
        frame.src = BASE + "/embed/" + encodeURIComponent(token);
        frame.setAttribute("title", "Gratias");
        frame.setAttribute("allow", "payment " + BASE);
        frame.setAttribute("loading", "lazy");
        frame.style.border = "0";
        frame.style.width = "100%";
        frame.style.height = this.getAttribute("height") || "720px";
        this.replaceChildren(frame);
      }
    }
  );
})();
</script>
<!-- Usage: <tacitapay-thankyou token="LE_JETON_DU_SALARIE"></tacitapay-thankyou> -->

Usage: <tacitapay-thankyou token="THE_EMPLOYEE_TOKEN"></tacitapay-thankyou>. Only origins present in the key's allowlist are allowed to embed the journey; any other origin is refused.

OpenAPI specification

A machine-readable OpenAPI 3.0 document is served at /api/public/fiscal/openapi.json. It describes only caller-provided inputs and technical outputs, with no individual amounts from the platform.