Skip to main content

Bulk Operations

For large cohorts — hundreds or thousands of graduates — the API provides bulk endpoints and patterns to minimize the number of requests and reduce processing time.

Batch delete

Most resources support batch deletion via DELETE /resource/batch/destroy with a body of UUIDs:
curl -X DELETE https://api.dokstamp.eu/certificates/batch/destroy \
  -H "Authorization: Bearer {TOKEN}" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: {TENANT}" \
  -d '{ "uuids": ["uuid-1", "uuid-2", "uuid-3"] }'

Batch certificate issuance (pattern)

There is no single “batch create certificates” endpoint — each certificate requires its own unique file. However, you can efficiently pipeline the process:

1. Upload all files in one request

curl -X POST https://api.dokstamp.eu/files \
  -H "Authorization: Bearer {TOKEN}" \
  -H "Accept: application/json" \
  -H "X-Tenant: {TENANT}" \
  -F "files[]=@diploma-1.pdf" \
  -F "files[]=@diploma-2.pdf" \
  -F "files[]=@diploma-3.pdf"
Response includes an array of file objects. Map each file to a student by filename or index.

2. Issue certificates concurrently

Use concurrent HTTP requests (Promise.all in JavaScript, parallel cURL, Guzzle pool in PHP):
JavaScript
const issuances = students.map((student, index) => ({
  institution_uuid: INSTITUTION_UUID,
  course_uuid: COURSE_UUID,
  student_uuid: student.uuid,
  file_uuid: files[index].uuid,
  status: 'issued',
  issued_at: new Date().toISOString(),
}));

const results = await Promise.all(
  issuances.map(payload =>
    fetch('https://api.dokstamp.eu/certificates', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${TOKEN}`,
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'X-Tenant': TENANT,
      },
      body: JSON.stringify(payload),
    }).then(r => r.json())
  )
);

const verificationUrls = results.map(r => r.data.public_verification_url);
PHP (Guzzle pool)
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;

$client = new Client(['base_uri' => 'https://api.dokstamp.eu']);
$headers = [
    'Authorization' => "Bearer $token",
    'Accept'        => 'application/json',
    'Content-Type'  => 'application/json',
    'X-Tenant'      => $tenant,
];

$requests = function () use ($students, $files, $headers) {
    foreach ($students as $i => $student) {
        $body = json_encode([
            'institution_uuid' => INSTITUTION_UUID,
            'course_uuid'      => COURSE_UUID,
            'student_uuid'     => $student['uuid'],
            'file_uuid'        => $files[$i]['uuid'],
            'status'           => 'issued',
            'issued_at'        => now()->toIso8601String(),
        ]);
        yield new Request('POST', 'certificates', $headers, $body);
    }
};

$pool = new Pool($client, $requests(), ['concurrency' => 10]);
$pool->promise()->wait();

Batch resend signature requests

For document signing workflows, resend signature request emails to multiple signers at once:
POST /documents/signatures/batch/resend
curl -X POST https://api.dokstamp.eu/documents/signatures/batch/resend \
  -H "Authorization: Bearer {TOKEN}" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: {TENANT}" \
  -d '{
    "document_ids": [101, 102, 103]
  }'

Batch institutional signing

Sign multiple documents at once with the institutional digital certificate:
POST /documents/batch/sign/{cert_id}
curl -X POST "https://api.dokstamp.eu/documents/batch/sign/1" \
  -H "Authorization: Bearer {TOKEN}" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Tenant: {TENANT}" \
  -d '{
    "document_ids": [101, 102, 103],
    "pin": "123456"
  }'

Pagination for large result sets

When pulling large lists (e.g., all students to find missing certificates), use pagination:
# Pull all completed enrollments in pages of 200
PAGE=1
while true; do
  RESPONSE=$(curl -s "$API/enrollments?where[completion_status]=completed&per_page=200&page=$PAGE" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Accept: application/json" \
    -H "X-Tenant: $TENANT")
  
  TOTAL_PAGES=$(echo $RESPONSE | jq -r '.meta.last_page')
  echo "Processing page $PAGE of $TOTAL_PAGES"
  
  # Process items...
  
  [ "$PAGE" -ge "$TOTAL_PAGES" ] && break
  PAGE=$((PAGE + 1))
done