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.
| Metoda | Putanja | Šta radi |
|---|---|---|
| POST | /api/v1/certificates | Izdaj certifikat |
| POST | /api/v1/certificates/bulk | Izdaj više certifikata odjednom (do 100) |
| GET | /api/v1/certificates | Lista izdatih certifikata |
| GET | /api/v1/certificates/{hash} | Status jednog certifikata |
| POST | /api/v1/certificates/{hash}/revoke | Poništi certifikat |
Brzi početak
- Registrujte ustanovu i sačekajte da administrator odobri nalog.
- Otvorite Profil, sekcija API pristup, i kliknite na generisanje ključa. Ključ se prikaže samo jednom, pa ga odmah kopirajte.
- Spremite ključ na serveru vaše platforme, npr. u varijablu okruženja
DIPLOMA_API_KEY. - 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.jsonAko 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
/api/v1/certificatesZaglavlja: Authorization i Content-Type: application/json. Tijelo zahtjeva:
| Polje | Tip | Obavezno | Opis |
|---|---|---|---|
studentName | string | da | Ime i prezime primaoca, najviše 200 znakova. |
studentEmail | string | da | Email primaoca. Na njega stiže obavijest s linkom za provjeru. |
certificateType | string | ne | Naziv certifikata ili kursa (najviše 200 znakova). Zadano: „Diploma o završenom studiju“. |
identifier | string | ne (preporučeno) | Vaš interni ID, npr. broj indeksa ili ID kursa i korisnika (najviše 100 znakova). Vidi napomenu ispod. |
metadata | objekat | ne | Dodatni podaci u JSON obliku, npr. ocjena ili broj sati (najviše 4000 znakova). |
expiresAt | string | ne | Datum isteka, npr. 2030-12-31. Bez ovog polja certifikat ne ističe. |
sendEmail | boolean | ne | false 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
/api/v1/certificates/bulkIzdaje 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.
| Polje | Obavezno | Opis |
|---|---|---|
recipients | da | Lista primalaca (1 do 100). Svaki primalac ima polja studentName i studentEmail (obavezna) te identifier, metadata i expiresAt (opciona), isto kao kod pojedinačnog izdavanja. |
certificateType | ne | Naziv certifikata, isti za sve primaoce u zahtjevu. |
expiresAt | ne | Zajednički datum isteka. Primalac može imati vlastiti expiresAt koji ga zamjenjuje. |
sendEmail | ne | false 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 (
indexje mjesto u listi). SačuvajtecertificateHashiverifyUrlza 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
/api/v1/certificatesNajnoviji certifikati su prvi. Svi parametri su opcioni i pišu se u adresu (query string):
| Parametar | Opis |
|---|---|
limit | Broj rezultata po stranici, od 1 do 100. Zadano 50. |
cursor | Vrijednost nextCursor iz prethodnog odgovora, za sljedeću stranicu. |
status | active, revoked ili expired. |
email | Samo certifikati s tim emailom primaoca. |
identifier | Samo 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
/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…"
}| Polje | Značenje |
|---|---|
certificateId | Interni broj certifikata. |
certificateHash | Jedinstveni otisak certifikata. Koristi se za status i poništavanje. |
status | active (važi), revoked (poništen) ili expired (istekao). |
issuedAt / expiresAt | Datum izdavanja i isteka (expiresAt je null ako ne ističe). |
txHash | Oznaka transakcije na Base blockchainu. |
verifyUrl | Javni link na kojem svako može provjeriti certifikat i preuzeti PDF. |
Poništavanje certifikata
/api/v1/certificates/{certificateHash}/revokeTijelo 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č." }| Status | Značenje | Šta učiniti |
|---|---|---|
400 | Neispravni podaci | Provjerite 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. |
401 | Nevaž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. |
403 | Nalog nije odobren | Administrator još nije odobrio vašu ustanovu. |
404 | Certifikat nije pronađen | Hash ne postoji ili pripada drugoj ustanovi. |
429 | Previše zahtjeva | Sačekajte koliko piše u zaglavlju Retry-After (sekunde) i pokušajte ponovo. |
502 | Greška upisa na blockchain | Privremeno. Ponovite isti zahtjev; zbog idempotentnosti se neće napraviti duplikat. |
500 | Greška na serveru | Pokuš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.