Certificates

A certificate is a template that can be issued to employees — optionally with a validity period after which it expires. Use these endpoints to manage certificate templates, assign them to users, and inspect who holds them. Certificate categories are managed via Certificate Types.

Required scope: read:certificates, write:certificates.

Endpoints

GET
/api/open/v1/certificates

List certificate templates (paginated)

GET
/api/open/v1/certificates/{id}

Get a single certificate template

POST
/api/open/v1/certificates

Create a certificate template (draft by default)

PUT|PATCH
/api/open/v1/certificates/{id}

Update a certificate template

DELETE
/api/open/v1/certificates/{id}

Soft delete a certificate template (returns 204)

GET
/api/open/v1/certificates/{id}/users

List users who hold this certificate, with their state

POST
/api/open/v1/certificates/assign

Assign certificates to users

POST
/api/open/v1/certificates/{id}/reset

Reset / expire a certificate for users (returns 204)

GET
/api/open/v1/users/{id}/certificates

List all certificates held by a user

GET
/api/open/v1/users/{id}/certificates/{certificate_id}

Get a single certificate held by a user

List

curl "https://customer.monotree.com/api/open/v1/certificates?is_published=true" \
  -H "Authorization: Bearer mono_your_token_here"
Query paramNotes
is_publishedtrue returns published templates only, false returns drafts only. Omit for all.
titleFilter by title (partial match, any locale).
sinceISO 8601 — filter by created_at.
page, per_pageStandard pagination — per_page max 50.

Create

A certificate is created as a draft by default. Pass is_published: true to publish it immediately.

curl -X POST https://customer.monotree.com/api/open/v1/certificates \
  -H "Authorization: Bearer mono_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Food Safety",
    "description": "Awarded on completion of the food safety course.",
    "validity_months": 12,
    "reset_days_before_expiry": 30,
    "certificate_type_id": 3,
    "is_published": true
  }'

Request body

FieldTypeNotes
titlestringRequired.
descriptionstringOptional.
validity_monthsintegerOptional. Months until an issued certificate expires. Omit / null = never expires.
reset_days_before_expiryintegerOptional. 14–365.
certificate_type_idintegerOptional. A certificate type id.
is_publishedbooleanOptional. true publishes immediately. Defaults to false (draft).

PUT and PATCH accept the same fields — all optional — and only change what you send. Setting is_published toggles the published state.

Assign certificates to users

Mirrors the in-app bulk assignment. Each user is issued the certificate as of their completed_at date; the expiry is derived from the template's validity_months. Users who already hold an active (non-expired) certificate are skipped.

curl -X POST https://customer.monotree.com/api/open/v1/certificates/assign \
  -H "Authorization: Bearer mono_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "assignments": [
      {
        "certificate_id": 12,
        "users": [
          { "user_id": 501, "completed_at": "2026-06-01" },
          { "user_id": 502, "completed_at": "2026-06-01" }
        ]
      }
    ]
  }'

Returns 204 No Content.

Reset / remove for users

Resets the certificate's linked completion for the given users, and — with expire: true — pulls any future expiry back to now, so the users no longer hold a valid certificate. This is how a certificate is revoked for a user; the platform keeps the issuance history rather than hard-deleting it. If user_ids is omitted, every user who holds the certificate is targeted.

curl -X POST https://customer.monotree.com/api/open/v1/certificates/12/reset \
  -H "Authorization: Bearer mono_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "user_ids": [501], "expire": true, "notify": false }'
FieldTypeNotes
user_idsarray of integersOptional. Defaults to all holders.
expirebooleanOptional. Pull future expiry to now (revoke).
notifybooleanOptional. Notify affected users (only with expire).

Returns 204 No Content.

Response

{
  "data": {
    "id": 12,
    "title": "Food Safety",
    "description": "Awarded on completion of the food safety course.",
    "validity_months": 12,
    "reset_days_before_expiry": 30,
    "active_users_count": 14,
    "is_published": true,
    "certificate_type": { "id": 3, "title": "Compliance", "is_published": true, "published_at": "2026-05-01T10:00:00+00:00", "created_at": "2026-05-01T10:00:00+00:00", "updated_at": "2026-05-01T10:00:00+00:00" },
    "published_at": "2026-06-01T10:00:00+00:00",
    "created_at": "2026-06-01T10:00:00+00:00",
    "updated_at": "2026-06-01T10:00:00+00:00"
  }
}

A user's certificates

GET /users/{id}/certificates returns the certificates a user holds, each with the issuance dates from their assignment and any earlier issuances under history.

{
  "data": [
    {
      "id": 12,
      "title": "Food Safety",
      "description": "Awarded on completion of the food safety course.",
      "validity_months": 12,
      "issued_at": "2026-06-01T00:00:00+00:00",
      "expires_at": "2027-06-01T00:00:00+00:00",
      "is_expired": false,
      "certificate_type": { "id": 3, "title": "Compliance", "is_published": true, "published_at": "2026-05-01T10:00:00+00:00", "created_at": "2026-05-01T10:00:00+00:00", "updated_at": "2026-05-01T10:00:00+00:00" },
      "history": []
    }
  ]
}

GET /certificates/{id}/users returns the holders of a certificate with their user_state (has_certificate, issued_at, expires_at, is_expired, completables, history).