API Integration documentation

Load the forms of a page

The endpoint the script calls to get the forms of a page, already translated.

Used by the script. The script calls this endpoint on its own, once for the forms found in the page, then once per batch of forms added later — see How forms are loaded. You only need it to build your own interface.

GET /api/websites/{website}/forms/config

Returns, for each requested form, its definition already translated into the language the server picked, with the settings of its link to the website.

Check Value
Authentication none; the page's Origin is authoritative
Origin the Origin header must match the website's host
Rate limiting api-forms-config, 60 per minute per IP
Cache Cache-Control: public, max-age=300, must-revalidate, ETag, Vary: Origin

Path parameters

Name Type Purpose
website UUID The website the page belongs to

Query parameters

Name Required Value
f yes Comma-separated entries slug~lang, 20 at most. slug: letters, digits, - and _; lang: a base language in lowercase (fr, en), or empty (contact~) to let the server choose

The script sends the entries deduplicated and sorted, with the language reduced to its base (en-GBen): identical pages share the same cached response.

Language of each form

  1. The requested language, if the form offers it.
  2. Otherwise, when the requested language is empty or not one of the seven languages of the platform, the website language, if the form offers it.
  3. Otherwise the form's source language.

A language of the platform that the form does not offer gives the source language — the same rule as for a submission, see Languages.

Response 200

One key per requested entry, as sent. null for a form that does not exist, is disabled, or is not linked to this website.

{
    "forms": {
        "contact~fr": {
            "slug": "contact",
            "locale": "fr",
            "submit_button_text": "Envoyer",
            "fields": [{
                "name": "email",
                "label": "Adresse email",
                "type": "email",
                "is_required": true,
                "show_label": true,
                "is_multiple": false,
                "placeholder": null,
                "help_text": null,
                "link_url": null,
                "options": [],
                "attributes": { "maxlength": "255" },
                "visibility": null
            }],
            "privacy_notice": { "text": null, "url": "https://www.example.com/privacy" },
            "css_selector": null,
            "injection_position": "inside",
            "html_wrapper": null,
            "appearance": { "--rk-form-accent": "#16a34a" }
        },
        "quote~en": null
    }
}

Each form has the shape described in What the script publishes: every text is in the language given by locale, untranslated texts falling back on the source language one by one. The confirmation message and the recipients are never returned; addresses are http or https only.

Response 304

A request carrying an If-None-Match equal to the current ETag receives a 304 with no body. A change to a form, one of its translations or its link to the website changes the ETag: with the 5-minute cache, it reaches visitors within 5 minutes.

Errors

Code Body Cause
403 {"error":"origin_not_allowed", …} The Origin does not match the website
403 {"message":"This website is disabled."} The client's account is suspended
404 {"message":"Website not found."} Unknown website
422 Laravel validation format f missing, more than 20 entries, or a malformed entry
429 Rate limit exceeded — see Rate limiting