diploma.baVerifikovani Registar
API dokumentacija

Povežite vašu platformu s diploma.ba

Kada korisnik završi kurs, vaš server pošalje jedan zahtjev, a certifikat se automatski upiše na blockchain i stiže primaocu na email. Ne morate se prijavljivati na diploma.ba za svaki certifikat.

Pregled

Osnovna adresa je https://diploma.ba. Zahtjevi i odgovori su u JSON formatu. Svaki poziv se potpisuje vašim API ključem i radi samo s certifikatima vaše ustanove.

MetodaPutanjaŠta radi
POST/api/v1/certificatesIzdaj certifikat
POST/api/v1/certificates/bulkIzdaj više certifikata odjednom (do 100)
GET/api/v1/certificatesLista izdatih certifikata
GET/api/v1/certificates/{hash}Status jednog certifikata
POST/api/v1/certificates/{hash}/revokePoništi certifikat

Brzi početak

  1. Registrujte ustanovu i sačekajte da administrator odobri nalog.
  2. Otvorite Profil, sekcija API pristup, i kliknite na generisanje ključa. Ključ se prikaže samo jednom, pa ga odmah kopirajte.
  3. Spremite ključ na serveru vaše platforme, npr. u varijablu okruženja DIPLOMA_API_KEY.
  4. Pošaljite probni zahtjev (ispod). U odgovoru dobijete verifyUrl: otvorite ga da vidite certifikat.
curl -X POST https://diploma.ba/api/v1/certificates \
  -H "Authorization: Bearer dpl_VAS_KLJUC" \
  -H "Content-Type: application/json" \
  -d '{
    "studentName": "Ime Prezime",
    "studentEmail": "student@example.com",
    "certificateType": "Napredni kurs programiranja",
    "identifier": "kurs-12-korisnik-345"
  }'

Napomena za Windows: u PowerShellu pišite curl.exe umjesto curl, i sve zahtjeve stavite u jednu liniju (bez znaka \ za novi red). Za lokalno testiranje koristite http://localhost:3000, ne https.

Imena sa č, ć, š, ž i đ kada testirate iz terminala

Windows terminal (CMD, PowerShell, Git Bash) često šalje tekst u drugom kodiranju, pa se znakovi č, ć, š, ž i đ ne mogu pročitati. Zato u primjerima s curl na ovoj stranici ne upisujte imena direktno u naredbu. Spremite JSON u datoteku kodiranu kao UTF-8 (npr. podaci.json, u Notepadu „Save as“ i izaberite UTF-8) i pošaljite je ovako:

curl -X POST https://diploma.ba/api/v1/certificates \
  -H "Authorization: Bearer dpl_VAS_KLJUC" \
  -H "Content-Type: application/json" \
  --data-binary @podaci.json

Ako se tekst ipak pošalje pogrešno kodiran, API vraća grešku 400 i ništa ne izdaje, tako da se pokvareno ime ne može upisati u certifikat. Kada API zovete iz vlastite platforme (Node.js, Python i sl.), ovog problema nema, jer ti jezici šalju UTF-8.

Autentikacija

Svaki zahtjev mora imati zaglavlje Authorization s vašim ključem. Ključ počinje s dpl_, a ispred njega mora stajati riječ Bearer i razmak.

Authorization: Bearer dpl_VAS_KLJUC
  • Ključ držite samo na serveru. Nikada ga ne stavljajte u kod koji se izvršava u browseru ili mobilnoj aplikaciji.
  • Mi čuvamo samo hash ključa, pa ga ne možemo ponovo prikazati. Ako ga izgubite, generišite novi (stari odmah prestaje važiti).
  • Ako sumnjate da je ključ procurio, opozovite ga ili zamijenite novim u profilu.

Izdavanje certifikata

POST/api/v1/certificates

Zaglavlja: Authorization i Content-Type: application/json. Tijelo zahtjeva:

PoljeTipObaveznoOpis
studentNamestringdaIme i prezime primaoca, najviše 200 znakova.
studentEmailstringdaEmail primaoca. Na njega stiže obavijest s linkom za provjeru.
certificateTypestringneNaziv certifikata ili kursa (najviše 200 znakova). Zadano: „Diploma o završenom studiju“.
identifierstringne (preporučeno)Vaš interni ID, npr. broj indeksa ili ID kursa i korisnika (najviše 100 znakova). Vidi napomenu ispod.
metadataobjekatneDodatni podaci u JSON obliku, npr. ocjena ili broj sati (najviše 4000 znakova).
expiresAtstringneDatum isteka, npr. 2030-12-31. Bez ovog polja certifikat ne ističe.
sendEmailbooleannefalse ako ne želite da šaljemo email primaocu. Zadano: true.

Odgovor je 201 za novi certifikat, ili 200 s alreadyIssued: true ako taj certifikat već postoji:

{
  "success": true,
  "alreadyIssued": false,
  "certificateId": 123,
  "certificateHash": "3f2a…",
  "txHash": "0x9b1c…",
  "status": "active",
  "verifyUrl": "https://diploma.ba/verifikuj?hash=3f2a…"
}

Upis na blockchain traje nekoliko sekundi, pa postavite vremensko ograničenje zahtjeva na barem 60 sekundi. Sačuvajte certificateHash i verifyUrl uz zapis u vašoj bazi: hash vam treba za status i poništavanje.

Masovno izdavanje

POST/api/v1/certificates/bulk

Izdaje do 100 certifikata u jednom zahtjevu i upisuje ih na blockchain jednom transakcijom, pa je brže i jeftinije nego 100 pojedinačnih poziva. Koristite ga kada završi cijela generacija ili kurs.

PoljeObaveznoOpis
recipientsdaLista primalaca (1 do 100). Svaki primalac ima polja studentName i studentEmail (obavezna) te identifier, metadata i expiresAt (opciona), isto kao kod pojedinačnog izdavanja.
certificateTypeneNaziv certifikata, isti za sve primaoce u zahtjevu.
expiresAtneZajednički datum isteka. Primalac može imati vlastiti expiresAt koji ga zamjenjuje.
sendEmailnefalse ako ne želite da šaljemo emailove. Zadano true.
curl -X POST https://diploma.ba/api/v1/certificates/bulk \
  -H "Authorization: Bearer dpl_VAS_KLJUC" \
  -H "Content-Type: application/json" \
  -d '{
    "certificateType": "Napredni kurs programiranja",
    "recipients": [
      { "studentName": "Ana Anić", "studentEmail": "ana@example.com", "identifier": "kurs-12-korisnik-1" },
      { "studentName": "Ben Benić", "studentEmail": "ben@example.com", "identifier": "kurs-12-korisnik-2" }
    ]
  }'
{
  "success": true,
  "issuedCount": 1,
  "alreadyIssuedCount": 1,
  "txHash": "0x9b1c…",          // null ako ništa nije izdato
  "results": [
    {
      "index": 0,                // mjesto primaoca u vašoj listi
      "alreadyIssued": true,
      "certificateId": 120,
      "certificateHash": "3f2a…",
      "txHash": "0x7e44…",
      "status": "active",
      "verifyUrl": "https://diploma.ba/verifikuj?hash=3f2a…"
    },
    {
      "index": 1,
      "alreadyIssued": false,
      "certificateId": 123,
      "certificateHash": "8c1d…",
      "txHash": "0x9b1c…",
      "status": "active",
      "verifyUrl": "https://diploma.ba/verifikuj?hash=8c1d…"
    }
  ]
}
  • Sigurno za ponavljanje. Certifikati koji već postoje se preskaču i vraćaju s alreadyIssued: true, a izdaju se samo novi. Ako zahtjev padne ili ne znate je li prošao, pošaljite ga ponovo.
  • Odgovor ima isti redoslijed kao lista koju ste poslali (index je mjesto u listi). Sačuvajte certificateHash i verifyUrl za svakog primaoca.
  • Greška u jednom primaocu odbija cijeli zahtjev (status 400), a poruka kaže koji je primalac neispravan, npr. recipients[3].studentEmail. Ništa se tada ne izdaje.
  • Emailovi se šalju nakon odgovora, jedan po jedan, pa za veću grupu mogu stizati i do minut-dvije. Šalju se samo za novoizdate certifikate.
  • Ako testirate iz terminala, spremite JSON u UTF-8 datoteku i pošaljite je s --data-binary @podaci.json (vidi Brzi početak), da se č, ć, š, ž i đ ne pokvare.
  • Ograničenje: 10 masovnih zahtjeva u minuti. Za više od 100 primalaca pošaljite više zahtjeva, kao u primjeru iznad.

Lista izdatih certifikata

GET/api/v1/certificates

Najnoviji certifikati su prvi. Svi parametri su opcioni i pišu se u adresu (query string):

ParametarOpis
limitBroj rezultata po stranici, od 1 do 100. Zadano 50.
cursorVrijednost nextCursor iz prethodnog odgovora, za sljedeću stranicu.
statusactive, revoked ili expired.
emailSamo certifikati s tim emailom primaoca.
identifierSamo certifikati s tim identifikatorom.
curl "https://diploma.ba/api/v1/certificates?limit=50&status=active" \
  -H "Authorization: Bearer dpl_VAS_KLJUC"
{
  "success": true,
  "certificates": [ { … }, { … } ],
  "nextCursor": "98"      // null kada nema više stranica
}

Jedan odgovor sadrži najviše 100 certifikata, ali možete dohvatiti sve: ponavljajte zahtjev s cursor sve dok nextCursor ne bude null (cijeli primjer petlje je u poglavlju „Primjeri koda“).

Status jednog certifikata

GET/api/v1/certificates/{certificateHash}

Umjesto {certificateHash} upišite hash koji ste dobili pri izdavanju (64 znaka).

curl https://diploma.ba/api/v1/certificates/HASH_CERTIFIKATA \
  -H "Authorization: Bearer dpl_VAS_KLJUC"
{
  "success": true,
  "certificate": { … }   // objekat certifikata, vidi iznad
}

Objekat certifikata (isti je i u listi):

{
  "certificateId": 123,
  "certificateHash": "3f2a…",
  "studentName": "Ime Prezime",
  "studentEmail": "student@example.com",
  "certificateType": "Napredni kurs programiranja",
  "identifier": "kurs-12-korisnik-345",
  "metadata": {},
  "status": "active",
  "issuedAt": "2026-11-12T13:10:48.553Z",
  "expiresAt": null,
  "txHash": "0x9b1c…",
  "verifyUrl": "https://diploma.ba/verifikuj?hash=3f2a…"
}
PoljeZnačenje
certificateIdInterni broj certifikata.
certificateHashJedinstveni otisak certifikata. Koristi se za status i poništavanje.
statusactive (važi), revoked (poništen) ili expired (istekao).
issuedAt / expiresAtDatum izdavanja i isteka (expiresAt je null ako ne ističe).
txHashOznaka transakcije na Base blockchainu.
verifyUrlJavni link na kojem svako može provjeriti certifikat i preuzeti PDF.

Poništavanje certifikata

POST/api/v1/certificates/{certificateHash}/revoke

Tijelo zahtjeva nije potrebno.

curl -X POST https://diploma.ba/api/v1/certificates/HASH_CERTIFIKATA/revoke \
  -H "Authorization: Bearer dpl_VAS_KLJUC"
{
  "success": true,
  "alreadyRevoked": false,
  "certificateHash": "3f2a…",
  "status": "revoked"
}
  • Certifikat se poništava na blockchainu i u našoj bazi, a stranica za provjeru ga odmah prikazuje kao poništenog.
  • Poništavanje je trajno i ne može se poništiti.
  • Ako je certifikat već poništen, dobijete status 200 s alreadyRevoked: true.

Greške i ograničenja

Kada nešto nije u redu, odgovor ima odgovarajući HTTP status i poruku u polju error:

{ "error": "Nevažeći ili nedostajući API ključ." }
StatusZnačenjeŠta učiniti
400Neispravni podaciProvjerite polja u zahtjevu. Poruka u polju error kaže šta je pogrešno. Tekst mora biti u UTF-8 kodiranju, inače se č, ć, š, ž i đ ne mogu pročitati.
401Nevažeći ili nedostajući API ključZaglavlje mora biti Authorization: Bearer dpl_... (sa razmakom iza „Bearer“). Ako ste ključ zamijenili novim, stari više ne važi.
403Nalog nije odobrenAdministrator još nije odobrio vašu ustanovu.
404Certifikat nije pronađenHash ne postoji ili pripada drugoj ustanovi.
429Previše zahtjevaSačekajte koliko piše u zaglavlju Retry-After (sekunde) i pokušajte ponovo.
502Greška upisa na blockchainPrivremeno. Ponovite isti zahtjev; zbog idempotentnosti se neće napraviti duplikat.
500Greška na serveruPokušajte ponovo kasnije. Ako se ponavlja, javite nam se.

Ograničenja po ustanovi:

  • Izdavanje: 60 zahtjeva u minuti
  • Masovno izdavanje: 10 zahtjeva u minuti (do 100 primalaca u svakom)
  • Lista i status: 120 zahtjeva u minuti
  • Poništavanje: 30 zahtjeva u minuti

Veći broj pogrešnih ključeva s iste IP adrese privremeno blokira daljnje pokušaje (status 429).

Primjeri koda

Node.js, izdavanje:

// Pozovite sa SERVERA vaše platforme, nikada iz browsera
async function izdajCertifikat(korisnik, kurs) {
  const res = await fetch('https://diploma.ba/api/v1/certificates', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.DIPLOMA_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      studentName: korisnik.punoIme,
      studentEmail: korisnik.email,
      certificateType: kurs.naziv,
      identifier: `kurs-${kurs.id}-korisnik-${korisnik.id}`,
    }),
  });

  const data = await res.json();
  if (!res.ok) throw new Error(data.error);   // 400, 401, 403, 429, 502, 500

  // Sačuvajte ova dva podatka uz zapis "položio kurs" u vašoj bazi
  return { hash: data.certificateHash, verifyUrl: data.verifyUrl };
}

Node.js, masovno izdavanje za cijelu listu polaznika:

// Izdaje certifikate za cijelu listu polaznika, u grupama od po 100
async function izdajSve(polaznici, kurs) {
  const rezultati = [];

  for (let i = 0; i < polaznici.length; i += 100) {
    const grupa = polaznici.slice(i, i + 100);

    const res = await fetch('https://diploma.ba/api/v1/certificates/bulk', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.DIPLOMA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        certificateType: kurs.naziv,
        recipients: grupa.map((p) => ({
          studentName: p.punoIme,
          studentEmail: p.email,
          identifier: `kurs-${kurs.id}-korisnik-${p.id}`,
        })),
      }),
    });

    const data = await res.json();
    if (!res.ok) throw new Error(data.error);   // sigurno je ponoviti istu grupu

    // results ima isti redoslijed kao grupa
    data.results.forEach((r, k) => rezultati.push({ korisnik: grupa[k], ...r }));
  }
  return rezultati;
}

Node.js, dohvat svih certifikata:

// Dohvaća SVE certifikate vaše ustanove, stranicu po stranicu
async function sviCertifikati() {
  const svi = [];
  let cursor = null;

  do {
    const url = new URL('https://diploma.ba/api/v1/certificates');
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('cursor', cursor);

    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.DIPLOMA_API_KEY}` },
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error);

    svi.push(...data.certificates);
    cursor = data.nextCursor;      // null na zadnjoj stranici
  } while (cursor);

  return svi;
}

Node.js, poništavanje:

async function ponistiCertifikat(hash) {
  const res = await fetch(`https://diploma.ba/api/v1/certificates/${hash}/revoke`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.DIPLOMA_API_KEY}` },
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error);
  return data;   // { success: true, alreadyRevoked: false|true, status: 'revoked' }
}

Python, izdavanje:

import os, requests

res = requests.post(
    "https://diploma.ba/api/v1/certificates",
    headers={"Authorization": f"Bearer {os.environ['DIPLOMA_API_KEY']}"},
    json={
        "studentName": "Ime Prezime",
        "studentEmail": "student@example.com",
        "certificateType": "Napredni kurs programiranja",
        "identifier": "kurs-12-korisnik-345",
    },
    timeout=60,   # upis na blockchain može potrajati nekoliko sekundi
)
data = res.json()
res.raise_for_status()
print(data["verifyUrl"])

Česta pitanja

Šta ako isti zahtjev pošaljem dvaput?+

Ništa loše: ne pravi se duplikat. Drugi put dobijete status 200 i alreadyIssued: true, bez novog upisa na blockchain i bez novog emaila. Zato je sigurno ponoviti zahtjev nakon greške mreže ili isteka vremena.

Zašto je identifier preporučen, a nije obavezan?+

Certifikat se prepoznaje po hashu izračunatom iz ustanove, imena, emaila, naziva certifikata, identifikatora i metadata. Ako se sve to poklopi, riječ je o istom certifikatu. Ako ista osoba treba dva certifikata s istim nazivom (npr. isti kurs u dva ciklusa), pošaljite različit identifier ili metadata. Dvije osobe s istim imenom, a različitim emailom, uvijek dobijaju različite certifikate.

Imam 500 polaznika. Kako da izdam sve certifikate?+

Koristite masovno izdavanje: podijelite listu u grupe od po 100 i pošaljite svaku grupu posebnim zahtjevom (primjer u poglavlju „Primjeri koda“). Ako neka grupa padne, ponovite je: već izdati certifikati se preskaču.

Kako da izdam certifikat bez da primalac dobije email?+

Pošaljite sendEmail: false. Link za provjeru svejedno dobijate u odgovoru (verifyUrl), pa ga možete sami poslati ili prikazati u svojoj aplikaciji.

Dobija li primalac PDF u emailu?+

Ne. Email sadrži link za provjeru. PDF se preuzima tek kada osoba na stranici za provjeru klikne „Preuzmi PDF Certifikat“.

Imam hiljade certifikata. Mogu li ih sve dohvatiti?+

Da. Jedan odgovor ima najviše 100 certifikata, ali možete čitati stranicu po stranicu preko nextCursor (vidi primjer iznad). Ograničenje je 120 zahtjeva u minuti.

Mogu li poništen certifikat ponovo aktivirati?+

Ne. Poništavanje je trajno jer se upisuje i na blockchain. Ako je greška, izdajte novi certifikat (uz drugačiji identifier, jer će isti podaci dati isti hash).

Kako da testiram a da ne pravim prave certifikate?+

Za sada ne postoji poseban testni način: svaki uspješan poziv izdavanja pravi stvaran certifikat i upis na blockchain. Za probu koristite svoj email i sendEmail: false, pa po potrebi poništite probni certifikat. Pozive za čitanje (lista i status) možete slobodno testirati.

Izgubio sam ili otkrio API ključ. Šta da radim?+

U profilu, u sekciji API pristup, generišite novi ključ ili opozovite postojeći. Stari ključ odmah prestaje važiti.

Treba vam pomoć s integracijom? Pišite nam na info@diploma.ba.