Helmi

API-ohje

Yksi osoite kertoo, saako sovellus asentua ja saako se jatkaa toimintaansa. Koodi itsessään on avain. Erillistä API-avainta ei ole.

Sovelluksen päätös

Salli asennus ja pidä sovellus käynnissä vain kun vastauksessa valid on true ja status on active.

Jos status on closed tai unknown, estä asennus tai pysäytä sovellus. HTTP 200 ei yksin riitä luvaksi.

Pyyntö

GET tai POST

https://avainhallinta.heso.fi/api/verify.php

code
Pakollinen. Muoto XXXX-XXXX-XXXX-XXXX. Väliviivat ja kirjainkoko saa jättää vapaaksi.
product
Pakollinen. Tuotteen slug hallinnasta, esimerkiksi omasovellus.
client
Vapaaehtoinen teksti, esimerkiksi koneen nimi tai versio. Näkyy hallinnassa. Ei sido koodia yhteen koneeseen.

POST voi olla JSON tai lomake. GET ottaa samat kentät osoitteesta.

Vastaus

ok
Pyyntö ymmärrettiin. Virheellisessä syötteessä tämä on false ja HTTP-tila 400.
valid
True vain kun koodi kuuluu tähän tuotteeseen ja on aktiivinen.
status
active, closed, unknown tai virheessä error.
message
Lyhyt selite ihmiselle.
product_name
Tuotteen nimi, kun koodi löytyi tälle tuotteelle.
checked_at
Aikaleima.

Aktiivinen

{
  "ok": true,
  "valid": true,
  "status": "active",
  "code": "ABCD-EFGH-JKLM-NPQR",
  "product": "omasovellus",
  "product_name": "Oma sovellus",
  "checked_at": "2026-11-05T22:00:00+02:00",
  "message": "Koodi on aktiivinen. Sovellus saa toimia."
}

Suljettu

{
  "ok": true,
  "valid": false,
  "status": "closed",
  "message": "Koodi on suljettu. Sovelluksen pitää pysähtyä."
}

Ei löydy

{
  "ok": true,
  "valid": false,
  "status": "unknown",
  "message": "Koodia ei löydy tai se ei kuulu tähän tuotteeseen."
}

Milloin sovellus kutsuu

Jos verkkoa ei saada, keskus ei vastaa. Sovellus päättää itse, salliiko se lyhyen katkon. Keskus kertoo tilan vain onnistuneessa tarkistuksessa.

Esimerkit

PowerShell
$body = @{
  code = "ABCD-EFGH-JKLM-NPQR"
  product = "omasovellus"
  client = "MyApp 1.0"
} | ConvertTo-Json

$result = Invoke-RestMethod -Method Post -Uri "https://avainhallinta.heso.fi/api/verify.php" -ContentType "application/json; charset=utf-8" -Body $body

if ($result.valid -eq $true -and $result.status -eq "active") {
  "Sallittu"
} else {
  "Estetty: $($result.status)"
}
PHP
$ch = curl_init('https://avainhallinta.heso.fi/api/verify.php');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'code' => 'ABCD-EFGH-JKLM-NPQR',
        'product' => 'omasovellus',
        'client' => 'MyApp 1.0',
    ]),
]);
$data = json_decode((string) curl_exec($ch), true);
$allowed = ($data['valid'] ?? false) === true && ($data['status'] ?? '') === 'active';
C#
using var client = new HttpClient();
var payload = new { code = "ABCD-EFGH-JKLM-NPQR", product = "omasovellus", client = "MyApp 1.0" };
var response = await client.PostAsJsonAsync("https://avainhallinta.heso.fi/api/verify.php", payload);
var data = await response.Content.ReadFromJsonAsync<JsonElement>();
bool allowed = data.GetProperty("valid").GetBoolean()
    && data.GetProperty("status").GetString() == "active";
curl
curl -s -X POST https://avainhallinta.heso.fi/api/verify.php \
  -H "Content-Type: application/json" \
  -d "{\"code\":\"ABCD-EFGH-JKLM-NPQR\",\"product\":\"omasovellus\",\"client\":\"MyApp 1.0\"}"

Kokeile

Vastaus näkyy tähän.

Palvelin

Tietokanta on tiedostossa data/helmi.sqlite. Apache estää data- ja includes-kansiot mukana tulevalla .htaccess-säännöllä. Nginxissä lisää:

location ~ ^/(data|includes)/ { deny all; }

PHP:n sisäinen palvelin: php -S localhost:8080 router.php