Update Certificate
Change the certificate template. Only the keys you send are written. content merges the same way. The first successful update stores the template. The write does not publish: on a published course it saves pending edits. The response is the full template plus preview_url. See Certificate Object and Updates.
Request
PATCH /players/{id}/certificate
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Course UUID. See Identifiers. |
Request Body
draft_version is required. Every other field is optional.
| Parameter | Type | Required | Description |
|---|---|---|---|
draft_version | integer | Yes | Current counter from Get Course. Minimum 1. Missing, not an integer, or below 1 is 422. A value that is not current is 409. |
is_active | boolean|null | No | Whether the template is active. null clears it. |
progress_threshold_percent | integer | No | From 0 to 100. 0 is valid. |
available_from | string|null | No | YYYY-MM-DD, or null to clear |
template | string | No | light-image, light-waves, light-stripes, dark-stripes, dark-dots, or custom |
content | object | No | Content Object. null on a content key clears that key. |
Example Request
curl -X PATCH "https://app.easy.tools/api/v1/players/8f3c1a62-d047-4e89-9b25-1c6a4d8e0f71/certificate" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"draft_version": 1,
"is_active": true,
"available_from": "2026-03-01",
"template": "custom",
"content": {
"course_name": "Course intro",
"text_color": "#111827"
}
}'
Response
Success Response (200)
{
"data": {
"is_active": true,
"progress_threshold_percent": 80,
"available_from": "2026-03-01",
"template": "custom",
"content": {
"course_name": "Course intro",
"course_description": null,
"course_image_url": null,
"background_image_url": null,
"color": null,
"text_color": "#111827"
},
"preview_url": "https://app.easy.tools/players/8f3c1a62-d047-4e89-9b25-1c6a4d8e0f71/preview?expires=1768478400&signature=7d2e9c41a6b85f03e1c7d94a2b6f80e35c1a9d7b4e2f60c8a3d5b1e9f7c2a046",
"draft_version": 2,
"draft_updated_at": "2026-01-15T11:05:00.000Z"
}
}
Response Fields
See Certificate Object. preview_url is minted for this response. draft_version is the counter after this write. draft_updated_at is when the draft was last saved — on a draft course, the course's updated_at.
Error Responses
Not Found Error (404)
See Identifiers.
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found"
}
}
Conflict Error (409)
draft_version is not the current counter. Read the course and retry with that value.
{
"error": {
"code": "CONFLICT",
"message": "The draft was edited elsewhere. GET the draft and retry with the current draft_version."
}
}
Validation Error (422 Unprocessable Entity)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The given data was invalid",
"details": {
"template": ["template must be one of the following values: light-image, light-waves, light-stripes, dark-stripes, dark-dots, custom"]
}
}
}
Authentication, permission, and rate-limit errors are described in Authorization.