---
title: "Issue a single certificate"
method: POST
path: "/batches/{batchId}/recipients"
tags: ["Recipients"]
---

# Issue a single certificate

`POST /batches/{batchId}/recipients`

## Request

- Base URL: `https://services.certseal.com/api/v1`
- URL: `https://services.certseal.com/api/v1/batches/{batchId}/recipients`
- Auth: HTTP bearer

Creates one recipient (= one certificate) in the batch. A new
`certificateId` and `shareToken` are minted automatically unless
you supply your own. Set `send: true` to enqueue the
certificate email immediately — the batch must have an
`emailTemplateId` and the server must have Resend configured.

Consumes one unit of plan quota.

## Path parameters

- `batchId` string, required

## Request body

- RecipientInput: Body of `POST /batches/{batchId}/recipients`. All fields are optional except that you usually want at least `name` or `email`.
  - `name` string, nullable
  - `email` string, email, nullable
  - `certificateId` string, nullable: Override the auto-generated certificate id. Must be unique across the whole system; duplicates return 409.
  - `issueDate` string, date, nullable: ISO date (or full ISO timestamp).
  - `expiryDate` string, date, nullable
  - `data` object: Free-form key/value bag interpolated into the certificate template wherever `{{key}}` appears.
  - `send` boolean: When `true`, also queue the certificate email immediately. Requires the batch to have `emailTemplateId` set and the server to have Resend configured.

## Response `201`

The created recipient.

- object
  - `recipient` Recipient, required
    - `id` string, required
    - `batchId` string, required
    - `name` string, nullable
    - `email` string, email, nullable
    - `certificateId` string, nullable: Human-readable id, e.g. CERT-2026-003843-000001.
    - `shareToken` string, nullable: Opaque token used in public viewer URLs.
    - `certUrl` string, uri, nullable: Fully-qualified public viewer URL. Null when `PUBLIC_APP_URL` isn't configured on the server.
    - `issueDate` string, date-time, nullable
    - `expiryDate` string, date-time, nullable
    - `data` object, required: All free-form fields preserved from the original input; interpolated into the certificate template at render time.
    - `emailStatus` 'pending' | 'queued' | 'sending' | 'sent' | 'failed', required
    - `emailSentAt` string, date-time, nullable
    - `createdAt` string, date-time, required

## Other responses

- `400`: The request body or query was invalid.
- `401`: Missing, malformed, expired, or revoked API key.
- `402`: Plan quota exhausted (`QUOTA_EXCEEDED`) or a non-period plan limit was hit (`PLAN_LIMIT_EXCEEDED`, e.g. `maxBatches`). Upgrade the plan to lift the limit.
- `404`: The requested resource was not found in this workspace.
- `409`: Request collided with the current state of the resource. The `error` code disambiguates the cause: - `CONFLICT` — duplicate `certificateId`, recipient already queued, etc. The `detail` shape varies per cause. - `BATCH_ARCHIVED` — the target batch has been archived. Unarchive it via `POST /batches/{id}/unarchive` before retrying any write (recipient create / update / delete / send).
- `429`: Too many requests for this API key. Honour the `Retry-After` response header (seconds) or the `detail.retryAfter` field.
- `503`: Email sending was requested but the server has no Resend API key configured. Either omit `send` / `POST .../send` or ask the operator to set `RESEND_API_KEY`.

---

[API](https://skmtc.dev/certseal/apis/certseal-com-api.md) · [All operations](https://skmtc.dev/certseal/apis/certseal-com-api/llms.txt) · [OpenAPI document](https://skmtc.dev/certseal/apis/certseal-com-api/revisions/9097f49f49f5?raw)
