Skip to main content

Issue Your First Certificate

This guide walks through the full certificate issuance workflow — from institution setup to issuing a verifiable credential with all optional entities included. By the end, you will have a live certificate with a public verification URL.

Before you start

Make sure you have:
  • API credentials (email + password)
  • Your X-Tenant identifier
  • A signed PDF of the certificate
Set these environment variables for the examples below:
export API=https://api.dokstamp.eu
export TENANT=your-tenant-domain
export TOKEN=""  # Will be set after Step 1

Step 1 — Authenticate

TOKEN=$(curl -s -X POST $API/auth/login \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@myschool.edu","password":"secret"}' \
  | jq -r '.access_token')

echo "Token: $TOKEN"

Step 2 — Create the Institution

INSTITUTION=$(curl -s -X POST $API/institutions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d '{
    "name": "Federal University of Technology",
    "country": "Brazil",
    "status": "active"
  }')

INSTITUTION_UUID=$(echo $INSTITUTION | jq -r '.data.uuid')
echo "Institution UUID: $INSTITUTION_UUID"

Step 3 — Create a Module

MODULE=$(curl -s -X POST $API/modules \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"name\": \"Software Engineering\",
    \"code\": \"SE301\",
    \"institution_uuid\": \"$INSTITUTION_UUID\",
    \"workload\": 60,
    \"credits\": 3,
    \"modality\": \"hybrid\",
    \"level\": \"undergraduate\"
  }")

MODULE_UUID=$(echo $MODULE | jq -r '.data.uuid')

Step 4 — Create the Course

COURSE=$(curl -s -X POST $API/courses \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"name\": \"Bachelor of Computer Science\",
    \"code\": \"BCS-2024\",
    \"institution_uuid\": \"$INSTITUTION_UUID\",
    \"workload_hours\": 3200,
    \"status\": \"active\"
  }")

COURSE_UUID=$(echo $COURSE | jq -r '.data.uuid')

Step 5 — Attach the Module to the Course

curl -X POST "$API/courses/$COURSE_UUID/attach/modules" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"modules\": [
      { \"uuid\": \"$MODULE_UUID\", \"order\": 1, \"is_required\": true }
    ]
  }"

Step 6 — Create a Cohort

COHORT=$(curl -s -X POST $API/cohorts \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"course_uuid\": \"$COURSE_UUID\",
    \"code\": \"BCS-2024-1\",
    \"modality\": \"hybrid\",
    \"start_date\": \"2024-02-01T00:00:00Z\",
    \"end_date\": \"2027-12-31T00:00:00Z\"
  }")

COHORT_UUID=$(echo $COHORT | jq -r '.data.uuid')

Step 7 — Create the Student

# Check if student already exists
EXISTING=$(curl -s "$API/students?where[email]=maria@email.com" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "X-Tenant: $TENANT")

STUDENT_UUID=$(echo $EXISTING | jq -r '.data[0].uuid // empty')

if [ -z "$STUDENT_UUID" ]; then
  STUDENT=$(curl -s -X POST $API/students \
    -H "Authorization: Bearer $TOKEN" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -H "X-Tenant: $TENANT" \
    -d '{
      "name": "Maria Fernanda Silva",
      "email": "maria@email.com",
      "date_of_birth": "1998-05-20",
      "gender": "female"
    }')
  STUDENT_UUID=$(echo $STUDENT | jq -r '.data.uuid')
fi

echo "Student UUID: $STUDENT_UUID"

Step 8 — Create an Enrollment

ENROLLMENT=$(curl -s -X POST $API/enrollments \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"student_uuid\": \"$STUDENT_UUID\",
    \"course_uuid\": \"$COURSE_UUID\",
    \"cohort_uuid\": \"$COHORT_UUID\",
    \"enrolled_at\": \"2024-02-01\",
    \"completion_status\": \"completed\",
    \"grade\": 9.0,
    \"completed_at\": \"2027-12-20\"
  }")

ENROLLMENT_UUID=$(echo $ENROLLMENT | jq -r '.data.uuid')

Step 9 — Upload the PDF

FILE=$(curl -s -X POST $API/files \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "X-Tenant: $TENANT" \
  -F "files[]=@/path/to/diploma-maria.pdf")

FILE_UUID=$(echo $FILE | jq -r '.data[0].uuid')
echo "File UUID: $FILE_UUID"

Step 10 — Issue the Certificate

CERTIFICATE=$(curl -s -X POST $API/certificates \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: $TENANT" \
  -d "{
    \"institution_uuid\": \"$INSTITUTION_UUID\",
    \"course_uuid\": \"$COURSE_UUID\",
    \"student_uuid\": \"$STUDENT_UUID\",
    \"cohort_uuid\": \"$COHORT_UUID\",
    \"enrollment_uuid\": \"$ENROLLMENT_UUID\",
    \"file_uuid\": \"$FILE_UUID\",
    \"status\": \"issued\",
    \"issued_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
  }")

echo "Certificate:"
echo $CERTIFICATE | jq '.data | {uuid, status, public_verification_url}'
Output:
{
  "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "issued",
  "public_verification_url": "https://verificar.dokstamp.eu/a1b2c3d4"
}
The public_verification_url is ready to share — no authentication needed to access it.

Next steps

  • Batch issuance — process hundreds of certificates at once → Bulk Operations
  • Digital badges — emit Open Badges alongside certificates → Open Badges
  • Student portfolio — let the student publish their certificate → Student Portfolio