TL;DR: Merit Aktiva API on REST API aadressil https://aktiva.merit.ee/api/v2/, mis autendib iga päringu HMAC-SHA256 allkirjaga. Allkiri on base64 väärtus funktsioonist HMAC-SHA256(apiKey, apiId + timestamp + body), ajatempel (timestamp) peab olema kujul yyyyMMddHHmmss UTC ajavööndis ja päringu keha (body) tuleb allkirjastatava stringi lõppu lisada isegi siis, kui see on tühi. Kui need kolm asja on õigesti, suudab iga HTTPS päringuid tegev klient - olgu selleks AI agent nagu Claude või ChatGPT, n8n töövoog või Make'i stsenaarium - sinu Aktiva andmeid lugeda ja kirjutada. See leht näitab reaalset allkirjastatud päringut, tagastatavat JSON-it, valmis nelja sõlmega n8n töövoogu ja seda ühte allkirjastamise viga, mis annab peaaegu igal esimesel katsel vastuseks 401.
Aluslabs ehitab Merit Aktiva API-liidestusi ja automatiseerib raamatupidamise töövooge. Selle juhendi aluseks olev HMAC-allkirjastamise ja v2 lõpp-punktide kate on avaldatud avatud lähtekoodiga: merit-aktiva-skills. Kui tahad sama asja oma ettevõttes töösse panna, vaata Merit Aktiva integratsiooni lehte.
Kuidas Merit Aktiva API autentimine tegelikult töötab?
Iga päring sisaldab kolme URL-i parameetrit: ApiId, timestamp ja signature. Allkiri on base64(HMAC-SHA256(apiKey, apiId + timestamp + body)). API võti on HMAC saladus ja see ei lahku kunagi sinu serverist. API ID ja ajatempel liiguvad URL-is. Kui paned stringide ühendamise järjekorraga mööda, saad vastuseks 401.
Merit dokumenteerib seda skeemi oma pseudokoodis:
dataToSign := utf8_to_bytes( string_concat(apiId, timestamp, httpBody) )
hmacKey := ascii_to_bytes(apiKey)
signatureBytes := hmac_sha256(hmacKey, dataToSign)
signature := base64(signatureBytes)
Järjekord on kindlalt paigas: esmalt apiId, siis timestamp ja seejärel toores HTTP keha. Nende vahel ei ole eraldajaid. Kui lisad tühiku, reavahetuse või mõne muu eraldusmärgi, ei kattu allkiri sellega, mida Merit oma poolel arvutab, ja päring ebaõnnestub.
Mis on see üks allkirjastamise viga, mis tagastab 401?
Ajatempli formaat ja tühi päringu keha on need, mis esimesed katsed katki teevad. Merit ootab formaati yyyyMMddHHmmss UTC ajavööndis ilma eraldajateta, seega 20260115143022 töötab, aga 2026-01-15T14:30:22Z mitte. GET päringu puhul on keha tühi string ", mis tuleb ikkagi allkirjastatava andmestiku lõppu lisada, mitte ära jätta.
Peaaegu iga 401 vea taga on üks neljast põhjusest (tõenäosuse järjekorras):
- Ajatempel on ISO 8601 formaadis, kohalikus ajas või sisaldab eraldajaid. See peab olema
yyyyMMddHHmmssUTC ajavööndis. - HMAC arvutamisel jäeti päringu keha lisamata. GET päringu puhul on keha
"ja see läheb ikkagi allkirjastatava stringi sisse. Kui annad"asemelnull, tekib teistsugune allkiri. - Keha serialiseeriti allkirjastamise ja saatmise vahel uuesti, nii et allkirjastatud baidid ja saadetud baidid erinevad. See on n8n-is ja Make'is kõige sagedasem põhjus.
- API võti kopeeriti koos lõpus oleva reavahetusega, mistõttu on HMAC saladus ühe baidi võrra vale.
Veel üks kellaga seotud reegel: allkirjasta päring vahetult enne selle saatmist. Kui sinu ajatempel erineb Meriti serveri kellast rohkem kui paar minutit, lükatakse päring tagasi isegi siis, kui allkirja matemaatika on õige.
Milline näeb välja reaalne allkirjastatud päring?
Allpool on reaalne, redigeeritud GET päring endpointi getcustomers. API ID ja võti on asendatud, ajatempel arvutatakse saatmise hetkel ning keha on tühi string, mis ikkagi allkirjastatakse. Täpselt sellise kujuga päringu loob AI agent, n8n HTTP sõlm või Make'i moodul.
API_ID="REDACTED-API-ID"
API_KEY="REDACTED-API-KEY"
BASE="https://aktiva.merit.ee/api/v2"
# GET: body is the empty string, but it is still part of the signed data
BODY="
TS=$(date -u +%Y%m%d%H%M%S)
SIG=$(printf '%s' "${API_ID}${TS}${BODY}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary \
| base64)
curl -s -G "${BASE}/getcustomers" \
--data-urlencode "ApiId=${API_ID}" \
--data-urlencode "timestamp=${TS}" \
--data-urlencode "signature=${SIG}"
Parameeter --data-urlencode allkirja juures on oluline: base64 väljund võib sisaldada märke +, / ja = ning Meriti enda dokumentatsioon hoiatab, et allkiri peab olema URL-kodeeritud. Kui jätad selle tegemata, muutub + märk serveris vaikimisi tühikuks ja oledki tagasi 401 vea juures.
Siin on sama allkirjastamine Pythonis, mida enamik AI agendi tööriistade wrappereid lõpuks välja kutsub:
import hmac, hashlib, base64
from datetime import datetime, timezone
import requests
API_ID = "REDACTED-API-ID"
API_KEY = "REDACTED-API-KEY"
BASE = "https://aktiva.merit.ee/api/v2"
def sign(body: str) -> tuple[str, str]:
ts = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
msg = (API_ID + ts + body).encode("utf-8")
sig = base64.b64encode(
hmac.new(API_KEY.encode("utf-8"), msg, hashlib.sha256).digest()
).decode("utf-8")
return ts, sig
ts, sig = sign(") # GET -> empty body, still signed
r = requests.get(
f"{BASE}/getcustomers",
params={"ApiId": API_ID, "timestamp": ts, "signature": sig},
)
r.raise_for_status()
print(r.json())
Milline näeb välja JSON vastus ja miks maksu GUID on kõige olulisem?
getcustomers tagastab JSON massiivi kliendi objektidega. Väljad, mida agent või töövoog vajab kliendi dublikaatide vältimiseks ja viitamiseks, on GUID CustomerId, Name ja Eesti registrikood RegNo. Redigeeritud vastus:
[
{
"CustomerId": "8a1f3c2e-0000-4a11-9c7d-REDACTED",
"Name": "Estonian Design OU",
"RegNo": "1234567",
"VatRegNo": "EE100000000",
"CountryCode": "EE",
"Gln": ",
"NotTDCust": false
}
]
Arve loomiseks on vaja ka TaxId välja, mis on GUID, mitte protsent. Sa pead pärima kehtivad maksumäärade GUID-id endpointist gettaxes kord sessiooni või töövoo käivitamise kohta ja vastendama "24% standardmäära" selle GUID-iga. See on 2026. aastal kõige olulisem asi, mis peab õigesti olema: standardmäär tõusis 24% peale, seega iga töövoog või agent, mis kasutab sissekirjutatud (hardcoded) vana maksu GUID-i või vana protsenti, teeb iga arve valesti. Loe maksu GUID alati ettevõtte andmetest, mitte kunagi mudeli mälust ega koodikommentaarist.
Kuidas luua API kaudu müügiarve?
Saada POST päring JSON kehaga endpointi sendinvoice. Keha sisaldab Customer objekti, välju DocDate ja DueDate, InvoiceRow massiivi ning TaxAmount massiivi. Iga rida vajab Item objekti, millel on Code, Quantity, Price ja TaxId GUID, mille said gettaxes päringust. Kui jätad TaxId lisamata, salvestub arve vale käibemaksuga.
Reaalne, redigeeritud sendinvoice päring, mis on allkirjastatud samamoodi, kuid mittetühja kehaga:
BODY='{
"Customer": { "Name": "Estonian Design OU", "RegNo": "1234567" },
"DocDate": "2026-01-31",
"DueDate": "2026-02-14",
"InvoiceNo": "2026-0042",
"InvoiceRow": [
{
"Item": { "Code": "CONS", "Description": "Consulting, January 2026" },
"Quantity": 40,
"Price": 95.00,
"TaxId": "REDACTED-TAX-GUID-24"
}
],
"TaxAmount": [
{ "TaxId": "REDACTED-TAX-GUID-24", "Amount": 912.00 }
],
"TotalAmount": 3800.00
}'
TS=$(date -u +%Y%m%d%H%M%S)
SIG=$(printf '%s' "${API_ID}${TS}${BODY}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary \
| base64)
curl -s "${BASE}/sendinvoice?ApiId=${API_ID}×tamp=${TS}&signature=${SIG}" \
-H "Content-Type: application/json" \
--data-raw "$BODY"
Siin tehakse tavaliselt kaks viga. BODY string, mida sa allkirjastad, peab olema baidi täpsusega sama string, mille sa teele saadad. Seega koosta JSON üks kord ja taaskasuta muutujat, ära kunagi serialiseeri seda uuesti allkirjastamise ja saatmise vahel. Teiseks, TotalAmount on summa ilma käibemaksuta; käibemaks asub TaxAmount massiivis ja ei ole kogusumma sisse arvestatud.
Vastus tagastab loodud dokumendi GUID-i ja numbri. Kui Merit lõi kliendi lennult, tulevad kaasa ka CustomerId ja NewCustomer. Loe InvoiceId tagasi kasutajale või oma järgmisesse sammu tõestusena, et müügiarve on sisestatud:
{
"InvoiceId": "b7c9e5a1-0000-4f22-8d3a-REDACTED",
"CustomerId": "8a1f3c2e-0000-4a11-9c7d-REDACTED",
"InvoiceNo": "2026-0042",
"NewCustomer": false
}
Kus asub autentimise voog agendi sees?
Allkirjastamise samm on ainus keeruline osa ja see peaks asuma ühes taaskasutatavas funktsioonis, mida läbivad kõik tööriista väljakutsed. Voog on iga endpointi jaoks sama: koosta keha, lisa UTC ajatempel, allkirjasta, saada.

See joonis tasub endale selgeks teha, sest see selgitab, miks sama allkirjastamise viga ilmneb nii GET kui ka POST päringute puhul: päringu keha küll muutub, aga stringide ühendamise järjekord ja ajatempli reegel jäävad alati samaks.
Kuidas panna sama allkiri kokku n8n-is nelja sõlmega?
Kui trigger ja andmete vastendamine on fikseeritud, ei ole agenti vaja: neli n8n sõlme teevad sama töö ära. Trigger võtab sündmuse vastu, Code sõlm ehitab JSON keha ja UTC ajatempli, Crypto sõlm allkirjastab apiId + timestamp + body ning HTTP Request sõlm saadab POST päringu, kus allkiri on päringu parameetrites (query string).

Rollid konkreetselt:
- Trigger sõlm (Webhook, Schedule või Stripe/Typeform trigger). See annab sulle toored arve väljad: kliendi nimi, registrikood, arve rida, summa.
- Code sõlm. See paneb kokku Meriti JSON keha, lisab
yyyyMMddHHmmssUTC ajatempli ja serialiseerib keha ühe korra stringiks. See string ongi see, mida sa nii allkirjastad kui ka saadad. - Crypto sõlm. Action
HMAC, algoritmSHA256, kodeeringbase64, saladuseks (secret) sinu API võti. See allkirjastab kokku pandud stringi. - HTTP Request sõlm. Meetod POST, URL
.../api/v2/sendinvoice, kolm päringu parameetrit (ApiId,timestamp,signature) ja toores JSON keha.
Sul ei ole vaja ühte HTTP sõlme autentimiseks ja teist päringu tegemiseks. Merit nõuab iga päringu eraldi allkirjastamist, seega allkirjastamine ja saatmine toimuvad samas kahes viimases sõlmes.
Code sõlm: keha ja ajatempel
Ehita keha JavaScripti objektina, serialiseeri see ühe korra JSON.stringify abil ja loo ajatempel kujul yyyyMMddHHmmss UTC ajavööndis ilma eraldajateta. Salvesta serialiseeritud string elemendi külge, et järgmised kaks sõlme saaksid taaskasutada täpselt samu baite.
const input = $json.body || $json;
const body = {
Customer: { Name: input.customerName, RegNo: input.regNo },
DocDate: input.docDate,
DueDate: input.dueDate,
InvoiceNo: input.invoiceNo,
InvoiceRow: [
{
Item: { Code: input.itemCode, Description: input.description },
Quantity: input.quantity,
Price: input.price,
TaxId: input.taxId
}
],
TaxAmount: [ { TaxId: input.taxId, Amount: input.taxAmount } ],
TotalAmount: input.totalAmount
};
const d = new Date();
const p = (n) => String(n).padStart(2, '0');
const timestamp = `${d.getUTCFullYear()}${p(d.getUTCMonth()+1)}${p(d.getUTCDate())}${p(d.getUTCHours())}${p(d.getUTCMinutes())}${p(d.getUTCSeconds())}`;
const bodyString = JSON.stringify(body);
const apiId = $vars.MERIT_API_ID;
const signBase = apiId + timestamp + bodyString;
return [{ json: { apiId, timestamp, bodyString, signBase, body } }];
Pane tähele, et TaxId on GUID, mitte protsent. Päri kehtiv 24% käibemaksu GUID üks kord gettaxes endpointist ja sööda see sisse triggeri kaudu.
Crypto sõlm: allkiri ilma krüptograafiakoodita
Kasuta n8n-i sisseehitatud Crypto sõlme. See toodab täpselt base64(HMAC-SHA256(apiKey, apiId + timestamp + body)), mis ongi see, mida Merit ootab, ilma et sa kirjutaksid ridagi krüptograafiakoodi. Seadistus väli-väljalt:
Action: HMAC
Type: SHA256
Value: ={{ $json.signBase }}
Property Name: signature
Secret: ={{ $vars.MERIT_API_KEY }}
Encoding: base64
Saladus on HMAC võti ja see ei lahku kunagi n8n-ist. Salvesta see n8n-i muutuja või mandaadina (credential), mitte otse sõlme sisse, et see ei satuks eksporditud töövoogudesse ega logidesse. Väärtus, mida sa allkirjastad, on string, mille Code sõlm juba ehitas, seega allkiri ja payload ei saa kunagi teineteisest erineda.
HTTP Request sõlm: toores keha, mitte JSON ehitaja
Määra n8n-is HTTP Request keha tüübiks raw / application/json ja seo see väärtusega ={{ $json.bodyString }}. Ära kasuta siin JSON keha ehitajat nime/väärtuse väljadega, sest n8n serialiseeriks selle uuesti ja sinu allkiri ei klapiks enam saadetud baitidega.
Siin on samaväärne päring toore allkirjastatud curl-ina, et saaksid täpselt näha, mida n8n väljastab, ja seda silumiseks väljaspool n8n-i reprodutseerida:
API_ID="REDACTED-API-ID"
API_KEY="REDACTED-API-KEY"
BASE="https://aktiva.merit.ee/api/v2"
BODY='{"Customer":{"Name":"Estonian Design OU","RegNo":"1234567"},"DocDate":"2026-07-01","DueDate":"2026-07-15","InvoiceNo":"2026-0042","InvoiceRow":[{"Item":{"Code":"CONS","Description":"Consulting, June 2026"},"Quantity":40,"Price":95.00,"TaxId":"REDACTED-TAX-GUID-24"}],"TaxAmount":[{"TaxId":"REDACTED-TAX-GUID-24","Amount":912.00}],"TotalAmount":3800.00}'
TS=$(date -u +%Y%m%d%H%M%S)
SIG=$(printf '%s' "${API_ID}${TS}${BODY}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary \
| base64)
curl -s "${BASE}/sendinvoice?ApiId=${API_ID}×tamp=${TS}&signature=${SIG}" \
-H "Content-Type: application/json" \
--data-raw "$BODY"
Laadi n8n töövoog alla
Impordi see ja ühenda oma trigger ning muutujad. See sisaldab kõiki nelja eelnevalt ühendatud sõlme, kus Code, Crypto ja HTTP sõlmed on seadistatud täpselt nii, nagu ülal kirjeldatud. Asenda Webhook oma tegeliku triggeriga ja määra MERIT_API_ID ning MERIT_API_KEY n8n-i muutujatena.
Kopeeri allolev töövoo JSON ja kleebi see n8n kanvaale (Ctrl/Cmd+V), et see importida:
{
"name": "Merit Aktiva - loo muugiarve triggeri pealt",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "merit-invoice",
"responseMode": "lastNode",
"options": {}
},
"id": "b1a1e100-0000-4000-9000-000000000001",
"name": "Trigger (Webhook)",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-320,
320
],
"webhookId": "merit-invoice-demo"
},
{
"parameters": {
"jsCode": "// Ehita arve keha ja UTC ajatempel. Keha string, mille sa allkirjastad,\n// PEAB olema baithaaval sama, mille sa saadad. Serialiseeri korra siin.\nconst input = $json.body || $json;\n\nconst body = {\n Customer: { Name: input.customerName, RegNo: input.regNo },\n DocDate: input.docDate,\n DueDate: input.dueDate,\n InvoiceNo: input.invoiceNo,\n InvoiceRow: [\n {\n Item: { Code: input.itemCode, Description: input.description },\n Quantity: input.quantity,\n Price: input.price,\n TaxId: input.taxId\n }\n ],\n TaxAmount: [\n { TaxId: input.taxId, Amount: input.taxAmount }\n ],\n TotalAmount: input.totalAmount\n};\n\n// yyyyMMddHHmmss UTC-s, ilma eraldajateta\nconst d = new Date();\nconst p = (n) => String(n).padStart(2, '0');\nconst timestamp = `${d.getUTCFullYear()}${p(d.getUTCMonth() + 1)}${p(d.getUTCDate())}${p(d.getUTCHours())}${p(d.getUTCMinutes())}${p(d.getUTCSeconds())}`;\n\n// Tapselt see string laheb allkirjastamisele: apiId + timestamp + bodyString\nconst bodyString = JSON.stringify(body);\nconst apiId = $vars.MERIT_API_ID;\nconst signBase = apiId + timestamp + bodyString;\n\nreturn [{ json: { apiId, timestamp, bodyString, signBase, body } }];"
},
"id": "b1a1e100-0000-4000-9000-000000000002",
"name": "Ehita keha + ajatempel",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-80,
320
]
},
{
"parameters": {
"action": "hmac",
"type": "SHA256",
"value": "={{ $json.signBase }}",
"dataPropertyName": "signature",
"secret": "={{ $vars.MERIT_API_KEY }}",
"encoding": "base64"
},
"id": "b1a1e100-0000-4000-9000-000000000003",
"name": "HMAC-SHA256 allkiri",
"type": "n8n-nodes-base.crypto",
"typeVersion": 1,
"position": [
180,
320
]
},
{
"parameters": {
"method": "POST",
"url": "https://aktiva.merit.ee/api/v2/sendinvoice",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "ApiId",
"value": "={{ $json.apiId }}"
},
{
"name": "timestamp",
"value": "={{ $json.timestamp }}"
},
{
"name": "signature",
"value": "={{ $json.signature }}"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ $json.bodyString }}",
"options": {}
},
"id": "b1a1e100-0000-4000-9000-000000000004",
"name": "Merit sendinvoice",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
320
]
}
],
"connections": {
"Trigger (Webhook)": {
"main": [
[
{
"node": "Ehita keha + ajatempel",
"type": "main",
"index": 0
}
]
]
},
"Ehita keha + ajatempel": {
"main": [
[
{
"node": "HMAC-SHA256 allkiri",
"type": "main",
"index": 0
}
]
]
},
"HMAC-SHA256 allkiri": {
"main": [
[
{
"node": "Merit sendinvoice",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
},
"pinData": {}
}
Allkirjastamine asub ühes kohas, seega iga teine Meriti endpoint (getcustomers, gettaxes, getinvoices) taaskasutab sama Code ja Crypto paari.
Millal kasutada API-t otse, millal n8n-i ja millal Make'i?
Vali tööriist vastavalt töö iseloomule, mitte haibile. Kasuta n8n-i kindlate ja korduvate töövoogude jaoks, kus allkirjastamine peab olema puhas. Kasuta Make'i, kui vajad palju valmis liideseid ja haldaja ei ole arendaja. Kutsu API-t otse agendi tööriistast, kui sisend varieerub ja ülesanne nõuab otsustusvõimet. Enamik ettevõtteid kasutab lõpuks kahte neist kolmest.
| n8n töövoog | Make töövoog | AI agent + API | |
|---|---|---|---|
| Millal valida | Kindel trigger, stabiilne vastendamine, vaja on krüptot | Palju SaaS-liideseid, haldaja pole arendaja | Ettearvamatu sisend, vaja on otsustada |
| HMAC allkirjastamine | Sisseehitatud Crypto node, koodi pole vaja | Kohandatud kood Tools/function sammus | Üks korduvkasutatav sign() funktsioon |
| Kes haldab | See, kes töövoo ehitas | See, kes töövoo ehitas | See, kes kirjutas agendi reeglid |
| Millal katki läheb | Lähte-API või vastendamine muutub | Lähte-API või vastendamine muutub | Maksureeglid muutuvad, vajab ümberõpetamist |
| Kulude struktuur | Majutus (hosting), püsitasu | Operatsioonipõhine, astmeline | Tokenid, kasvab koos kasutusega |
Crypto sõlm on praktiline põhjus, miks n8n on just Merit Aktiva fikseeritud töövoogude puhul parim valik. Make'is tuleb HMAC käsitsi base64 ja SHA-256 funktsioonidest kokku panna ning esimese töötava versiooni saamine võtab terve pärastlõuna katsetamist. n8n-is võtab Crypto sõlm kokku pandud stringi, SHA-256 algoritmi ja API võtme ning väljastab otse base64 allkirja. Vali n8n ka siis, kui soovid hoida töövoo JSON-it versioonihalduses või majutad lahendust ise (self-hosting), et hoida finantsandmeid EL-is.
Aus soovitus, millal midagi MITTE kasutada: ära vali AI agenti töövoo jaoks, mille struktuur ei muutu kunagi. Stripe'ist müügiarve loomise protsess, mis käivitub iga kord täpselt samamoodi, ei vaja mudelit, vaid n8n töövoogu, millest saab ühe pilguga aru. Samuti ei tasu suruda jäika n8n stsenaariumi peale tõeliselt muutuvale sisendile, muidu veedad kogu oma elu uusi harusid lisades iga uue PDF-formaadi jaoks, mille tarnija välja mõtleb.

Agent on õige valik siis, kui töö nõuab otsustamist, mida staatiline töövoog ei suuda lahendada. Segane uue kujundusega PDF, vabas vormis juhis nagu "tee Estonian Design OÜ-le arve 40 tunni konsultatsiooni eest hinnaga 95 eurot" või jooksev küsimus nagu "kui palju me kulutasime esimeses kvartalis majutusele" nõuavad kõik struktureerimata sisendi analüüsimist. Agent ei asenda allkirjastamist, vaid mässib selle enda sisse: pane eelnev sign() funktsioon ühte korduvkasutatavasse tööriista (tool), anna agendile lõpp-punktide nimekiri, Eesti käibemaksukoodid ja kontoplaan ning see suudab Aktivat algusest lõpuni juhtida.
Ausad piirangud kehtivad endiselt: piiramata agent teeb müügiarve valele kliendile, sest nimed on sarnased, või rakendab 22% käibemaksu, sest selle treeningandmed ütlevad nii. Sea agendile piirangud, sunni teda enne arveldamist klienti otsima ja enne allkirjastamist reaalajas maksu GUID-i pärima. Valmis Eesti reeglistik, nagu avatud lähtekoodiga merit-aktiva-skills plugin, on olemas just selleks, et sa ei peaks seda kõike nullist õpetama.
Viga, mida vältida, on nende kolme tööriista käsitlemine konkurentidena. Need teevad erinevaid töid ja enamik ettevõtteid jooksutab fikseeritud n8n töövoogu stabiilse osa jaoks ning agenti ülejäänud struktureerimata osa jaoks.
Kui sa pole veel kontot ja API kasutajat seadistanud, siis täielik Merit Aktiva seadistamise juhend katab Pro-paketi nõude ja näitab, kus API võti asub.
Mida Merit Aktiva API ei tee
Webhooke ei ole. Puudub "arve makstud" push-teavitus. Sündmuspõhise käitumise saavutamiseks tuleb pärida getinvoices endpointi kuupäevafiltri abil ja võrrelda tulemust oma viimati nähtud seisuga.
Puuduvad otsesed kanded pearaamatusse. Ei ole olemas endpointi, mis lubaks teha tooreid pearaamatu kandeid korrigeerimiste jaoks. Sa saadad äritehinguid (arved, maksed) ja lased Aktival nende põhjal pearaamatu kanded ise tuletada. See on tahtlik disain ja üllatab sageli inimesi, kes tulevad süsteemidest, kus kandeid tehakse otse pearaamatusse.
Kehtivad päringusageduse piirangud. Agendi kasutuse jaoks on need piirangud helded, kuid tuhandete ajalooliste arvete massiline importimine tuleb jagada osadeks.
Seotud aruandlus- ja e-arvete vood loevad samu arveandmeid uuesti välja just nende endpointide kaudu: KMD käibedeklaratsiooni automatiseerimine, e-arvete saatmine Eestis ja laiem e-arvete automatiseerimise võrdlus, kus on lahti kirjutatud ka see, kus Aktiva enda liidesed piiriks saavad.
Mis saab siis, kui andmed on kättesaadavad?
Allkirjastatud päring on alles uks. Kui Aktiva andmed on API kaudu loetavad, saab nende peale ehitada asju, mida programm ise ei näita: elava töölaua, mis näitab kasumit ja rahavoogu reaalajas, ilma et keegi peaks kuu lõpus numbreid Excelisse käsitsi kokku panema.
Aluslabs ehitab just seda kihti - fikseeritud n8n automaatika, AI-agendid ja elav töölaud Merit Aktiva ja Directo peale API kaudu, ilma majandustarkvara vahetamata. Kui sul on Aktiva kasutuses ja tahaksid näha, kus ettevõttel raha päriselt liigub, siis majandustarkvara automatiseerimine ja töölauad katab, mida sellise kihi ehitamine tähendab.
FAQ
Kuidas arvutatakse Merit Aktiva API allkirja?
See on base64(HMAC-SHA256(apiKey, apiId + timestamp + body)). API võti on HMAC saladus, need kolm stringi ühendatakse täpselt selles järjekorras ilma eraldajata ning päringu keha lisatakse isegi siis, kui see on GET päringu puhul tühi. Baas-URL on Eesti jaoks https://aktiva.merit.ee/api/v2/.
Miks minu Merit Aktiva päring tagastab 401?
Peaaegu alati on põhjuseks see, et ajatempel ei ole yyyyMMddHHmmss UTC ajavööndis, päringu keha ei lisatud allkirjastatavale andmestikule, keha serialiseeriti allkirjastamise ja saatmise vahel uuesti või API võti kopeeriti koos reavahetusega lõpus. Allkirjasta päring vahetult enne saatmist, et kellad ei läheks sünkroonist välja.
Kas ma pean allkirja URL-kodeerima?
Jah. Base64 võib sisaldada märke +, / ja = ning kodeerimata + muutub serveris tühikuks, mis teeb allkirja katki. Kasuta curlis parameetrit --data-urlencode või lase oma HTTP kliendil URL-i parameetrid ise kodeerida.
Milline n8n sõlm allkirjastab HMAC-SHA256 päringu?
Crypto sõlm, mille Action on HMAC, Type on SHA256 ja Encoding on base64. Selle väärtus on kokkupandud apiId + timestamp + body string ja saladus (secret) on sinu Meriti API võti. HTTP Request sõlm peab seejärel saatma toore (raw) bodyString väärtuse, mitte JSON nime/väärtuse ehitajat, mis payloadi uuesti serialiseeriks.
Kuidas ma saan 24% käibemaksu GUID-i?
Tee üks kord päring gettaxes endpointi ja kaardista 24% standardmäär selle GUID-iga, seejärel anna see GUID sisse triggeri kaudu või agendi tööriista kaudu. Ära kunagi kirjuta protsenti või vana käibemaksu GUID-i koodi sisse; standardmäär tõusis 24% peale ja vananenud koodid teevad iga arve valesti.
Kas Merit Aktiva toetab webhooke?
Ei. Sündmuste (näiteks makstud arve) kohta puuduvad push-teavitused. Sündmuspõhise käitumise saavutamiseks päri andmeid getinvoices endpointist kuupäevafiltri abil ja võrdle tulemust oma viimati nähtud seisuga.