Mataki

API migration guide: v1 to v2

Mataki’s server answers on two API versions side by side: /api/v1/ and /api/v2/. Version 1 is deprecated and stops working after 30 April 2027. Every client should use /api/v2/.

Dates

  • Deprecated: 11 October 2026. From this date every v1 reply carries a Deprecation header (RFC 9745), a Sunset header (RFC 8594) and a Link header pointing to this guide and to /api/v2/.
  • Sunset: 30 April 2027, at the end of the day (UTC). After it, every v1 request answers 410 Gone with the address of this guide.
  • GET /api/ lists the versions, their status and these dates as JSON.

The Mataki app itself already uses v2. Copies of the app opened before release 52 update themselves when they next go online.

Replies

v1 replied with a flat object: {"ok":true, ...fields} or {"ok":false, "error":"message", "reason":"code"}. v2 always uses one envelope: {"ok":true, "data":{...}} or {"ok":false, "error":{"code":"...", "message":"..."}}. Branch on error.code; the message is for people and may change.

The account object

  • role is now title (the job title).
  • scopeRole, scopeLga and scopeFacility are replaced by level (facility, ward, lga, state or national), state, lga, ward and facility. The same names are used at registration.
  • admin (true or false) is replaced by access: user, admin or superadmin.
  • New fields: verified (email confirmed) and sso (signed in through an organization).

Sealed password fields

v2 refuses a request that carries password, old or new in plain JSON, with the code payload_required. Put those fields in a JSON object, seal it, and send it as enc:

  1. Call status. Its key gives the server’s P-256 public key (kid, x, y, base64url).
  2. Make a fresh P-256 key pair and derive the shared secret with the server key (ECDH).
  3. Derive a 32-byte key with HKDF-SHA-256, salt = the kid string, info = mataki-payload-v1.
  4. Add two fields to the JSON: op, the name of the request it travels with, and at, the server’s time in Unix seconds (the now from status plus the seconds since). The server refuses a sealed object used with another request or more than 15 minutes away from its own time, so a copy cannot be replayed.
  5. Encrypt the JSON with AES-256-GCM, a random 12-byte IV and additional data = the kid. Append the 16-byte tag to the ciphertext.
  6. Send enc: {kid, epk:{x, y}, iv, ct}, all base64url. A reply field named sealed is encrypted with the same key and IV rules, additional data = reply.

If the server has replaced its key, or the time is too far out, it answers stale_key: fetch status again, seal again and repeat once.

Registration

v2 registration expects the account fields above and treats a request with the hidden form field filled in, or completed implausibly fast, as automated. A client that registers people must show them the form.

Requests that moved or are new

  • Administration (v1 setup, admin_users, admin_set) answers 410 on v1. It is available only to administrators at the address the server gives them after they sign in.
  • New in v2: resend, account, account_update, account_delete, and the single sign-on requests sso_lookup, sso_start, sso_finish and sso_register.
  • The tracking relay, /api/v2/track.php, takes the same requests as v1 with the v2 reply envelope.

Help

Questions about moving a client: info@scalentric.org.