Documentation
Base URL : https://supercalcula.ch/api
Get started in five minutes
- 1
Create a free account and confirm your email address. Create an account
- 2
Copy your API key from My account → API keys. It is shown only once.
- 3
Test it with the command below.
- 4
Call the API of your choice with the examples on this page.
curl https://supercalcula.ch/api/v1/ping \
-H "Authorization: Bearer sk_live_…"
# {"ok":true,"data":{"pong":true,"key":"sk_live_a1b2…9f3e"}}Two free endpoints: GET /v1/ping (tests a key) and GET /v1/me (plan, remaining quota and credits). openapi.yaml
Authentication
Every request carries the header Authorization: Bearer <key>. Keys starting with sk_test_ return mock results without using any quota (the header X-Test-Mode: true says so); validation is the same as with a production key.
Errors and quotas
Errors are JSON with a stable code and an English message. The headers X-Quota-Remaining, X-Credits-Remaining and X-RateLimit-Remaining are present on every response.
{ "ok": false, "error": { "code": "quota_exceeded", "message": "Monthly quota exhausted" } }| Code | HTTP | Meaning |
|---|---|---|
| invalid_api_key | 401 | Key missing, unknown or malformed. |
| key_revoked | 401 | Key revoked: create a new one from your account. |
| account_suspended | 403 | Account suspended: contact support. |
| invalid_input | 400 | Missing or invalid parameter (for conversions, line gives the faulty line). |
| payload_too_large | 413 | Body larger than your plan's limit (1 MB on Free, 10 MB above). |
| quota_exceeded | 429 | Monthly quota and credits exhausted. |
| rate_limited | 429 | Too many calls per minute; see the Retry-After header. |
| internal_error | 500 | Error on our side or an external source is unavailable: it costs nothing, retry. |
Credits and quotas
A successful request costs the endpoint's number of credits (1 for the wave-1 endpoints). A 4xx error caused by your request costs 1 credit; 401, 429 and 5xx errors cost nothing. The monthly quota is used first, then purchased credits.
Endpoint reference
/v1/qr
Cost: 1 credit(s)Generates a QR code or a barcode, as PNG or SVG.
Parameters (JSON body)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| content | string | yes | https://supercalcula.ch | Text, URL or vCard to encode (2,953 characters at most). |
| type | string qr | ean13 | code128 | no | qr | qr (default), ean13 (12 or 13 digits, the check digit is verified) or code128 (printable ASCII). |
| format | string png | svg | no | png | png (default) or svg. |
| size | integer | no | 512 | Width in pixels, 64 to 2,048 (default 512). |
| margin | integer | no | 2 | White margin in modules, 0 to 20 (default 2). |
| color | string | no | #000000 | Code colour, formatted #rrggbb. |
| background | string | no | #ffffff | Background colour, formatted #rrggbb. |
| error_correction | string L | M | Q | H | no | M | Error-correction level: L, M (default), Q or H. |
| logo_url | string | no | — | Centred logo (https only, 500 KB at most). Forces error_correction=H. SVG logos are only accepted with format=svg. |
| encoding | string binary | base64 | no | binary | binary (default: the image itself) or base64 (JSON containing the image). |
Example
curl -X POST https://supercalcula.ch/api/v1/qr \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"content":"https://supercalcula.ch","size":512}' --output qr.png
const res = await fetch("https://supercalcula.ch/api/v1/qr", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({
"content": "https://supercalcula.ch",
"size": 512
}),
});
const blob = await res.blob();
import requests
r = requests.post("https://supercalcula.ch/api/v1/qr",
headers={"Authorization": "Bearer sk_live_…"},
json={"content":"https://supercalcula.ch","size":512})
open("qr.png", "wb").write(r.content)
$ch = curl_init("https://supercalcula.ch/api/v1/qr");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["content" => "https://supercalcula.ch", "size" => 512]),
CURLOPT_RETURNTRANSFER => true,
]);
file_put_contents("qr.png", curl_exec($ch));
The response is the image itself (PNG or SVG); with encoding=base64, a JSON object containing the image.
Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/email/verify
Cost: 1 credit(s)Checks an email address without any SMTP connection: syntax, DNS, MX, disposable address, role account, likely typo.
Parameters (URL parameters)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| string | yes | jean.dupont@gmial.com | Address to check (254 characters at most). |
Example
curl "https://supercalcula.ch/api/v1/email/verify?email=jean.dupont%40gmial.com" \
-H "Authorization: Bearer sk_live_…"
const res = await fetch("https://supercalcula.ch/api/v1/email/verify?email=jean.dupont%40gmial.com", {
headers: { Authorization: "Bearer sk_live_…" },
});
console.log(await res.json());
import requests
r = requests.get("https://supercalcula.ch/api/v1/email/verify",
params={"email":"jean.dupont@gmial.com"},
headers={"Authorization": "Bearer sk_live_…"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/email/verify?email=jean.dupont%40gmial.com");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"email": "jean.dupont@gmial.com",
"normalized": "jean.dupont@gmial.com",
"syntax_valid": true,
"domain_exists": true,
"has_mx": false,
"disposable": false,
"role_account": false,
"free_provider": false,
"suggestion": "jean.dupont@gmail.com",
"score": 0.05,
"verdict": "invalid"
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/convert
Cost: 1 credit(s)Converts a document between JSON, CSV, XML and YAML. Variant: send the raw document with ?from=csv&to=json as URL parameters; the response is then the converted document.
Parameters (JSON body)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| from | string json | csv | xml | yaml | yes | csv | Source format: json, csv, xml or yaml. |
| to | string json | csv | xml | yaml | yes | json | Target format: json, csv, xml or yaml. |
| data | string | yes | … | Source document, as text. |
| options.delimiter | string | no | , | CSV: column separator (comma by default; “tab”, “semicolon” and “pipe” are accepted). |
| options.header | boolean | no | true | CSV: the first line contains the headers (default true). |
| options.root | string | no | root | XML: root element name (default root). |
| options.pretty | boolean | no | true | JSON and XML: indented output (default true). |
| options.infer_types | boolean | no | false | Turns “12”, “true” or “3.5” into numbers and booleans (default false). |
| options.escape_formulas | boolean | no | true | CSV: prefixes cells starting with = + - @ with an apostrophe to neutralise spreadsheet formulas (default true). |
Example
curl -X POST https://supercalcula.ch/api/v1/convert \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"from":"csv","to":"json","data":"name,city\nAlexandre,Genève"}'
const res = await fetch("https://supercalcula.ch/api/v1/convert", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({
"from": "csv",
"to": "json",
"data": "name,city\nAlexandre,Genève"
}),
});
const data = await res.json();
import requests
r = requests.post("https://supercalcula.ch/api/v1/convert",
headers={"Authorization": "Bearer sk_live_…"},
json={"from":"csv","to":"json","data":"name,city\nAlexandre,Genève"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/convert");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["from" => "csv", "to" => "json", "data" => "name,city\nAlexandre,Genève"]),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"to": "json",
"result": "[\n {\n \"name\": \"Alexandre\",\n \"city\": \"Genève\"\n }\n]",
"rows": 1
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/seo/analyze
Cost: 1 credit(s)Generates a slug and analyses title, description, keywords, density, reading time and readability.
Parameters (JSON body)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| title | string | yes | … | Page title (300 characters at most). |
| text | string | no | … | Article body (200,000 characters at most). |
| description | string | no | Meta description to evaluate (500 characters at most). | |
| lang | string fr | de | en | no | fr | fr (default), de or en: stop words and readability formula. |
| max_keywords | integer | no | 10 | Maximum number of keywords, 1 to 50 (default 10). |
Example
curl -X POST https://supercalcula.ch/api/v1/seo/analyze \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"title":"Comment créer un QR code avec logo en 2026","text":"Un QR code avec logo…","lang":"fr"}'
const res = await fetch("https://supercalcula.ch/api/v1/seo/analyze", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({
"title": "Comment créer un QR code avec logo en 2026",
"text": "Un QR code avec logo…",
"lang": "fr"
}),
});
const data = await res.json();
import requests
r = requests.post("https://supercalcula.ch/api/v1/seo/analyze",
headers={"Authorization": "Bearer sk_live_…"},
json={"title":"Comment créer un QR code avec logo en 2026","text":"Un QR code avec logo…","lang":"fr"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/seo/analyze");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["title" => "Comment créer un QR code avec logo en 2026", "text" => "Un QR code avec logo…", "lang" => "fr"]),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"slug": "comment-creer-un-qr-code-avec-logo-en-2026",
"title": {
"length": 42,
"verdict": "ok"
},
"description": {
"length": 0,
"verdict": "missing"
},
"keywords": [
{
"term": "qr code",
"count": 12,
"density": 2.1
},
{
"term": "logo",
"count": 7,
"density": 1.2
}
],
"word_count": 570,
"reading_time_min": 3,
"readability": {
"score": 62,
"level": "standard"
}
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/pii/redact
Cost: 1 credit(s)Detects and masks emails, phone numbers, IBANs, cards, AHV numbers, IP addresses and URLs. The text is never stored.
Parameters (JSON body)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| text | string | yes | … | Text to process (200,000 characters at most). |
| types | array email | phone | iban | card | ahv | ip | url | no | — | Types to detect among email, phone, iban, card, ahv, ip, url (all by default). |
| mode | string mask | placeholder | remove | no | placeholder | placeholder (default: [EMAIL_1]), mask (characters replaced) or remove. |
| mask_char | string | no | * | Masking character (exactly one, “*” by default). |
| keep_last | integer | no | 0 | mask mode: number of characters kept at the end of the value, 0 to 4. |
Example
curl -X POST https://supercalcula.ch/api/v1/pii/redact \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"text":"Contact : jean@exemple.ch, +41 79 123 45 67, IBAN CH93 0076 2011 6238 5295 7","mode":"placeholder"}'
const res = await fetch("https://supercalcula.ch/api/v1/pii/redact", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({
"text": "Contact : jean@exemple.ch, +41 79 123 45 67, IBAN CH93 0076 2011 6238 5295 7",
"mode": "placeholder"
}),
});
const data = await res.json();
import requests
r = requests.post("https://supercalcula.ch/api/v1/pii/redact",
headers={"Authorization": "Bearer sk_live_…"},
json={"text":"Contact : jean@exemple.ch, +41 79 123 45 67, IBAN CH93 0076 2011 6238 5295 7","mode":"placeholder"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/pii/redact");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["text" => "Contact : jean@exemple.ch, +41 79 123 45 67, IBAN CH93 0076 2011 6238 5295 7", "mode" => "placeholder"]),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"text": "Contact : [EMAIL_1], [PHONE_1], IBAN [IBAN_1]",
"entities": [
{
"type": "email",
"placeholder": "EMAIL_1",
"start": 10,
"end": 25
},
{
"type": "phone",
"placeholder": "PHONE_1",
"start": 27,
"end": 43
},
{
"type": "iban",
"placeholder": "IBAN_1",
"start": 50,
"end": 76
}
],
"count": 3
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/convert/currency
Cost: 1 credit(s)Converts an amount with the ECB reference rates (30 currencies, history since 1999).
Parameters (URL parameters)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| amount | number | yes | 100 | Amount to convert (positive). |
| from | string | yes | CHF | Source currency, three-letter code (CHF, EUR, USD…). |
| to | string | yes | EUR | Target currency, three-letter code. |
| date | string | no | — | Rate date formatted YYYY-MM-DD (optional, latest rate by default). |
Example
curl "https://supercalcula.ch/api/v1/convert/currency?amount=100&from=CHF&to=EUR" \
-H "Authorization: Bearer sk_live_…"
const res = await fetch("https://supercalcula.ch/api/v1/convert/currency?amount=100&from=CHF&to=EUR", {
headers: { Authorization: "Bearer sk_live_…" },
});
console.log(await res.json());
import requests
r = requests.get("https://supercalcula.ch/api/v1/convert/currency",
params={"amount":100,"from":"CHF","to":"EUR"},
headers={"Authorization": "Bearer sk_live_…"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/convert/currency?amount=100&from=CHF&to=EUR");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"amount": 100,
"from": "CHF",
"to": "EUR",
"rate": 1.0738,
"result": 107.38,
"date": "2026-10-09",
"source": "ECB"
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
/v1/convert/unit
Cost: 1 credit(s)Converts a value between units: length, mass, volume, area, temperature, speed, pressure, energy, power, data, time, angle.
Parameters (URL parameters)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| value | number | yes | 12.5 | Value to convert. |
| from | string | yes | km | Source unit (see GET /v1/units). |
| to | string | yes | mi | Target unit, in the same category. |
| precision | integer | no | 6 | Number of decimals in the result, 0 to 12 (default 6). |
Example
curl "https://supercalcula.ch/api/v1/convert/unit?value=12.5&from=km&to=mi" \
-H "Authorization: Bearer sk_live_…"
const res = await fetch("https://supercalcula.ch/api/v1/convert/unit?value=12.5&from=km&to=mi", {
headers: { Authorization: "Bearer sk_live_…" },
});
console.log(await res.json());
import requests
r = requests.get("https://supercalcula.ch/api/v1/convert/unit",
params={"value":12.5,"from":"km","to":"mi"},
headers={"Authorization": "Bearer sk_live_…"})
print(r.json())
$ch = curl_init("https://supercalcula.ch/api/v1/convert/unit?value=12.5&from=km&to=mi");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
Response
{
"ok": true,
"data": {
"value": 12.5,
"from": "km",
"to": "mi",
"result": 7.76714,
"category": "length"
}
}Try it with your key
Paste an API key (preferably an sk_test_ key: canned results, no credits used). It stays in this page: it is neither stored nor sent anywhere except to the API. With an sk_live_ key the call uses your credits.
Changelog
- 2026-10-10
- Version 1.0: QR codes and barcodes, email validation, data conversion, SEO, personal data masking, currencies and units.