# EviMail API

The EviMail API lets you submit certified emails, query the status of previously submitted messages, and request on-demand affidavits for eligible transactions. It is a REST API that uses HTTP Basic authentication and returns JSON responses.

For end-to-end lifecycle, callback semantics, and integration guidance, see the [EviMail service guide](/products/namirialnotify/services/evimail).

## Environments

| Environment | Base URL |
|  --- | --- |
| Production | `https://api.evicertia.com` |
| Pre-production / QA | `https://api.ecertia.com` |


For the public Namirial Notify API environments, this V1 service is exposed under the `/v1` base path. Use public routes such as `/v1/EviMail/Submit`, `/v1/EviMail/Query`, and `/v1/EviMail/AffidavitRequest`.

Some lower-level technical artifacts may show these V1 routes without the `/v1` prefix. For customer integrations, use the public `/v1` base path shown in this documentation.

For shared environment guidance across services, see [API documentation](/products/namirialnotify/dev/api-documentation#environments).

## Authentication

All endpoints require **HTTP Basic authentication**. Pass your Namirial Notify credentials as the username and password in the `Authorization` header.


```
Authorization: Basic <base64(username:password)>
```

The authenticated account must also hold the appropriate API permission grants. Contact your Namirial Notify account manager to confirm provisioning if you receive unexpected `403 Forbidden` responses.

For credential handling, callback hardening, and production security checks, see [Security and authentication](/products/namirialnotify/dev/security-best-practices).

## Idempotency

EviMail Submit supports idempotent submission. Include the `X-Evi-IdempotencyToken` header with a unique value per logical operation (a UUID is recommended).

The server signals the idempotency outcome in the response header `X-Evi-IdempotencyStatus`, which takes one of these values:

| `X-Evi-IdempotencyStatus` | Meaning |
|  --- | --- |
| `New` | First time the token is seen. The request executes normally and the response is cached for future replays. |
| `Replay` | The token matches a cached `200 OK` submission. The original response body is returned, with HTTP `202 Accepted`. The message is **not** resubmitted. |
| `Conflict` | Another request with the same token is currently in flight. The response is HTTP `409 Conflict`. Back off and retry the same Submit with the same token. |


The following response codes are **not** cached and will re-execute the request regardless of token: `400`, `401`, `408`, `409`, `429`, and `5xx` responses.

## Endpoints

### Submit a certified email


```
POST /v1/EviMail/Submit
```

Submits a new certified email. On success, returns an `eviId` that uniquely identifies the submitted message and can be used to query its status later.

**Required fields:** `Subject`, `Body`, `Recipient` (with `EmailAddress`).

Optional fields include `IssuerName`, `Options`, `From`, `ReplyTo`, `DisableSenderHeader`, `LookupKey`, `CarbonCopy` (array of recipients), and `Attachments`. `Recipient.LegalName` is also optional.

| Response | Description |
|  --- | --- |
| `200 OK` | Email accepted. Body contains `{ "eviId": "..." }`. |
| `202 Accepted` | Returned when an idempotent replay matches a previously `200 OK` submission. The original response body is returned unchanged. See [Idempotency](#idempotency) above. |
| `400 Bad Request` | Invalid request or business rule failure. The response body contains a `responseStatus` object with `errorCode`, `message`, and an optional `errors` array of field-level details. |
| `401 Unauthorized` | Authentication failed. |
| `403 Forbidden` | The authenticated account lacks the required API permission, has specified a `From` address that is not permitted for this account, or has attempted to set a restricted request header. |
| `409 Conflict` | Another Submit with the same `X-Evi-IdempotencyToken` is currently in flight. See [Idempotency](#idempotency) above. |


**Example request:**


```json
POST /v1/EviMail/Submit HTTP/1.1
Authorization: Basic <base64(username:password)>
Content-Type: application/json
X-Evi-IdempotencyToken: 550e8400-e29b-41d4-a716-446655440000

{
  "LookupKey": "ORDER-12345",
  "Subject": "Your certified policy update",
  "Body": "<html><body><p>Please review the attached policy update.</p></body></html>",
  "IssuerName": "Acme Corp",
  "Recipient": {
    "LegalName": "Alice Martin",
    "EmailAddress": "alice@example.com"
  },
  "Options": {
    "CertificationLevel": "Advanced_EU",
    "TimeToLive": 10080,
    "PushNotificationUrl": "https://your-endpoint.example.com/callbacks/evimail",
    "PushNotificationFilter": ["Delivered", "Closed", "AffidavitPublished"],
    "AffidavitKinds": ["Submitted", "TransmissionResult", "DeliveryResult", "Closed"]
  }
}
```

**Example response (`200 OK`):**


```json
{
  "eviId": "2aca3ea1-49f9-4387-9726-a87000c1f704"
}
```

### Query certified emails


```
GET /v1/EviMail/Query
```

Returns a list of certified emails matching the specified filters. Results are paginated using `Limit` and `Offset`.

**Query parameters:**

| Parameter | Type | Description |
|  --- | --- | --- |
| `WithUniqueIds` | string | Filter by one or more unique IDs (comma-separated). |
| `WithLookupKeys` | string | Filter by one or more lookup keys (comma-separated). |
| `WithLinkedId` | string (UUID) | Filter by linked ID. |
| `OnState` | string | Filter by current state. |
| `WithOutcome` | string | Filter by outcome. |
| `OrderResultsBy` | string | Sort field for results. Supported value: `CreationDate`. |
| `Limit` | integer | Maximum number of results to return. |
| `Offset` | integer | Number of results to skip. |
| `IncludeAffidavits` | boolean | Include affidavit metadata in results. |
| `IncludeAttachments` | boolean | Include attachment metadata in results. |


If `Limit` is omitted, the API uses a default limit of `100`. The default becomes `25` when the request includes affidavit or attachment metadata.

| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "totalMatches": N, "results": [...] }`. |
| `401 Unauthorized` | Authentication failed. |


### Request an on-demand affidavit


```
POST /v1/EviMail/AffidavitRequest
```

Generates a custom affidavit for a previously submitted EviMail. To use this endpoint, the original submit request must have included `AffidavitKinds` with the `OnDemand` value. The communication must still be eligible for on-demand affidavits.

Requests are rejected when the communication is `Draft`, already `Closed`, not enabled for on-demand affidavits, over the configured maximum request count, or requested by a non-owner.

**Request body:**

| Field | Type | Description |
|  --- | --- | --- |
| `UniqueId` | string (UUID) | Required. Unique ID of the EviMail to generate an affidavit for. |
| `IncludeBody` | boolean | Optional. Include the email body in the affidavit. |
| `IncludeAttachments` | boolean | Optional. Include email attachments in the affidavit. Attachments must have been submitted with `IncludeOnAffidavits: true`. |
| `IncludeEvents` | boolean | Optional. Include detailed event information in the affidavit. |


| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "requestId": "..." }`. The affidavit is generated asynchronously. |
| `400 Bad Request` | Business rule or validation failure. The response body contains a `responseStatus` object with `errorCode`, `message`, and `errors`. |
| `401 Unauthorized` | Authentication failed. |


## Batch operations

Batch operations let you send the same certified email to many recipients as a single managed job.

:::note Base path
The batch endpoints are part of the **v2** API and live under the `/v2/EviMail/Batches` base path — not under the `/v1` base path used by the rest of the EviMail API.
:::

The typical workflow is:

1. **Create** an empty batch with a `Description` — you receive a `BatchId`.
2. **Set the body** (`PUT .../Body`) — the HTML email content.
3. **Add recipients** (`POST .../Recipients`) — uploaded as a `text/csv` file.
4. *(Optional)* **Add attachments** (`POST .../Attachments`) — uploaded as `multipart/form-data`.
5. **Configure options** (`PATCH .../{BatchId}`) — certification level, commitment, callbacks, scheduling, and so on. Also set the `Subject` here.
6. **Start processing** by setting the batch `State` (via `PATCH`) once the batch is ready.


Poll `GET .../{BatchId}` to follow progress (`SentCount`, `FailedCount`, `ProgressPercentage`). Batch lifecycle states are `Draft`, `Submitted`, `Scheduled`, `Processing`, `Processed`, `Invalid`, and `Failed`.

:::note HTTP QUERY method
The two list endpoints (**Query batches** and **Query batch recipients**) are implemented with the HTTP `QUERY` method and accept their filters in a JSON request body. Because OpenAPI cannot express the `QUERY` method, they are documented as `GET` with the filter fields shown as query parameters. In practice, send the request with the HTTP `QUERY` verb and the fields in a JSON body.
:::

### Create an email batch


```
POST /v2/EviMail/Batches
```

Creates a new, empty batch. Only `Description` is required; the body, recipients, attachments, and options are set with the subsequent batch endpoints.

| Field | Type | Description |
|  --- | --- | --- |
| `Description` | string | Required. Human-readable batch description (max 255 chars). |


| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "BatchId": "<uuid>" }`. |
| `401 Unauthorized` | Authentication failed. |


### Query email batches


```
QUERY /v2/EviMail/Batches
```

Lists email batches owned by the caller (or the caller's site), with cursor pagination. Filters are sent in a JSON request body: `States` (array), `Cursor`, `Limit` (required, 1–100), `SortBy` (`LastUpdated`/`ScheduledFor`/`StartedOn`), `SortOrder` (`Ascending`/`Descending`), `Direction` (`Forward`/`Backward`), `TextSearch`.

| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "Cursor": "...", "HasMoreResults": bool, "Results": [...] }`. |
| `400 Bad Request` | Malformed request. |
| `401 Unauthorized` | Authentication failed. |


### Get an email batch


```
GET /v2/EviMail/Batches/{BatchId}
```

Retrieves the full state of a batch, including its configured email template (nested `EviMail`) and processing progress.

| Response | Description |
|  --- | --- |
| `200 OK` | Returns the full batch object. |
| `400 Bad Request` | `BatchId` is missing or a default (empty) UUID. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Update an email batch


```
PATCH /v2/EviMail/Batches/{BatchId}
```

Updates batch metadata and the email template options. All fields are optional; only the fields supplied are changed. Setting `State` transitions the batch; setting `ScheduledDate` schedules it.

**Request body (all fields optional):** `IssuerName`, `Subject`, `ScheduledDate`, `State`, `Description`, `From`, `DisableSenderHeader`, `ReplyTo`, `TimeToLive`, `CostCentre`, `CertificationLevel`, `AffidavitKinds`, `Language`, `AffidavitLanguage`, `OnlineRetentionPeriod`, `LtaStorage`, `PushNotificationUrl`, `PushNotificationFilter`, `PushNotificationExtraData`, `CommitmentOptions`, `CommitmentCommentsAllowed`, `RejectReasons`, `AcceptReasons`, `RequireRejectReason`, `RequireAcceptReason`, `DeliveryAppearance`, `BatchPushNotificationUrl`, `OwnerNotificationTemplate`.

| Response | Description |
|  --- | --- |
| `200 OK` | Batch updated. |
| `400 Bad Request` | Invalid request. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Delete an email batch


```
DELETE /v2/EviMail/Batches/{BatchId}
```

| Response | Description |
|  --- | --- |
| `204 No Content` | Batch deleted. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Set the batch body


```
PUT /v2/EviMail/Batches/{BatchId}/Body
```

Sets the HTML body of the email for this batch. The body is sent as the raw request payload with `Content-Type: text/html`, not as a JSON field. Set the `Subject` with `PATCH .../{BatchId}`.

| Response | Description |
|  --- | --- |
| `202 Accepted` | Body accepted and queued for update. Poll `GET .../{BatchId}` to check status. |
| `400 Bad Request` | The request has no valid body. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Add batch recipients


```
POST /v2/EviMail/Batches/{BatchId}/Recipients
```

Adds recipients by uploading a `text/csv` file (`Content-Type: text/csv`). The CSV uses `;` as the column separator.

- **Mandatory columns:** `emailaddress`, `legalname`
- **Optional columns:** `lookupkey`, `displayname`, `evidenceaccesscontrolchallenge`, `evidenceaccesscontrolchallengeresponse`
- **Custom fields:** add extra columns prefixed with `*` (for example, `*orderid`); they are surfaced per recipient as `ExtraFields`.


**Example request body:**


```
emailaddress;legalname;displayname;*orderid
jane@example.com;Acme Corp;Jane Doe;ORD-001
john@example.com;Beta Ltd;John Roe;ORD-002
```

| Response | Description |
|  --- | --- |
| `200 OK` | Recipients accepted. No response body is returned. |
| `400 Bad Request` | The payload is empty or the `Content-Type` is not `text/csv`. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |
| `409 Conflict` | The recipient list failed validation (for example, missing mandatory columns). |


### Query batch recipients


```
QUERY /v2/EviMail/Batches/{BatchId}/Recipients
```

Lists the recipients of a batch, with cursor pagination. Filters are sent in a JSON request body: `Cursor`, `Limit` (1–1000), `SortDirection` (`Ascending`/`Descending`).

| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "Cursor": "...", "Results": [...] }`. Each result includes the recipient fields and, once processed, the `EvidenceUniqueId` of the generated email. |
| `400 Bad Request` | Malformed request. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Delete all batch recipients


```
DELETE /v2/EviMail/Batches/{BatchId}/Recipients
```

| Response | Description |
|  --- | --- |
| `204 No Content` | Recipients removed. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Add a batch attachment


```
POST /v2/EviMail/Batches/{BatchId}/Attachments
```

Adds a single attachment as `multipart/form-data`. The attachment is included in every email generated from the batch. Send the file in the `Content` part; the remaining metadata fields (`DisplayName`, `Filename`, `ContentId`, `MimeType`, `ContentDescription`, `ContentDisposition`, `ContentLocation`, `ContentEncoding`, `IncludeOnAffidavits`) are optional form fields.

| Response | Description |
|  --- | --- |
| `200 OK` | Returns `{ "AttachmentId": "<uuid>" }`. |
| `400 Bad Request` | No file was supplied, or more than one file was supplied. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### List batch attachments


```
GET /v2/EviMail/Batches/{BatchId}/Attachments
```

| Response | Description |
|  --- | --- |
| `200 OK` | Returns an array of attachment metadata (`Id`, `DisplayName`, `FileName`, `MimeType`, `Size`, `ContentEncoding`, `ContentId`). |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Delete all batch attachments


```
DELETE /v2/EviMail/Batches/{BatchId}/Attachments
```

| Response | Description |
|  --- | --- |
| `204 No Content` | Attachments removed. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No batch with the given `BatchId` was found. |


### Download a batch attachment


```
GET /v2/EviMail/Batches/{BatchId}/Attachments/{AttachmentId}
```

| Response | Description |
|  --- | --- |
| `200 OK` | Attachment content (`application/octet-stream`). |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No attachment or batch with the given IDs was found. |


### Delete a batch attachment


```
DELETE /v2/EviMail/Batches/{BatchId}/Attachments/{AttachmentId}
```

| Response | Description |
|  --- | --- |
| `204 No Content` | Attachment removed. |
| `401 Unauthorized` | Authentication failed. |
| `404 Not Found` | No attachment or batch with the given IDs was found. |


## States and outcomes

For a cross-service explanation of lifecycle terminology, see [States and outcomes](/products/namirialnotify/user-guides/states-outcomes). For a visual lifecycle reference, see the [EviMail evidence lifecycle](/products/namirialnotify/user-guides/states-outcomes#evimail-evidence-lifecycle).

**States** represent the current step in the message lifecycle.

| State | Description |
|  --- | --- |
| `Draft` | Message is being prepared. |
| `New` | Message has been accepted by the platform. |
| `Ready` | Message has been validated, certified, and is ready for sending. |
| `Dispatched` | Sending has been requested; the message is ready for the sender component. |
| `Sent` | The recipient's mail server accepted the message. |
| `Delivered` | Delivery confirmation was received. |
| `Read` | Recipient opened the message (where supported and configured). |
| `Replied` | Recipient replied to the message (where configured). |
| `Closed` | Message lifecycle is complete. |
| `Failed` | A recoverable processing or delivery failure occurred. The platform may retry or advance to a later state. |


**Outcomes** represent the overall result of the certification process.

| Outcome | Description |
|  --- | --- |
| `None` | No outcome determined yet. |
| `Certified` | Message certified with the configured certification level. |
| `Sent` | Message was sent. |
| `Delivered` | Message was delivered. |
| `Read` | Recipient opened the message. |
| `Accepted` | Recipient explicitly accepted the message. |
| `Rejected` | Recipient explicitly rejected the message. |
| `Failed` | Delivery failed permanently. |


## Key request fields

### `Subject`

The email subject line. Maximum 1024 characters. Non-printable control characters are not accepted.

### `Body`

The HTML body of the certified email. Accepts HTML content. Maximum 10 MB.

### `IssuerName`

The legal name or identifier for the sending organisation, used in the certified communication record. Maximum 50 characters.

### `LookupKey`

Your own correlation key. Maximum 35 characters. Filterable in Query. No uniqueness is enforced server-side — make it unique within your own domain.

### `CertificationLevel`

Defines the legal framework and geographic variant for certification. The API accepts `Standard`, `Advanced`, and regional values such as `Standard_EU`, `Advanced_EU`, and other country-specific codes. The values available on your account depend on your subscription and configuration — confirm the enabled levels with your Namirial Notify contact or refer to the OpenAPI spec for the machine-readable enum.

### `TimeToLive`

The time in minutes during which the platform will attempt delivery before the message expires. Range: 60–86,400 (1 hour to 60 days).

### `Language`

The language used for notification emails sent to the recipient. Accepted values: `ca`, `de`, `en`, `es`, `fr`, `it`, `pt`, `pt-BR`, `ro`. Defaults to the account's configured language when omitted.

### `AffidavitLanguage`

The language of generated affidavit PDFs. Accepted values: `ca`, `de`, `en`, `es`, `fr`, `it`, `pt`, `pt-BR`, `ro`, `el`.

### `CarbonCopy`

An array of additional recipients (each with `Name` and `EmailAddress`) to receive a copy of the email. Carbon copy recipients are recorded in the transaction but do not generate independent evidence events.

### `Attachments`

An array of files to attach to the email. Each attachment requires a `Filename` and base64-encoded `Data`, and optionally a `DisplayName`, content-metadata fields (`ContentId`, `MimeType`, `ContentDescription`, `ContentDisposition`, `ContentLocation`, `ContentEncoding`), and an `Attributes` array of key-value pairs. Use the `IncludeOnAffidavits` attribute key with value `"true"` to reference the attachment in generated affidavits (PDF attachments only).

Limits: maximum 15 attachments per submission; maximum 8 MB per attachment; maximum 25 MB total across all attachments.

### `PushNotificationFilter`

An array of state names that trigger a callback to `PushNotificationUrl`. Valid values for EviMail: `Ready`, `Sent`, `Dispatched`, `Delivered`, `Read`, `Replied`, `Failed`, `Closed`, `AffidavitPublished`.

`AffidavitPublished` is not a lifecycle state — it is a platform meta-event that fires when affidavit generation for this message completes.

### `PushNotificationExtraData`

A free-text string echoed back inside every callback for this communication as `AdditionalData.ExtraData`. Maximum 1024 characters. Use it to pass correlation data your system needs to route the notification without looking up the `eviId`.

### `AffidavitKinds`

Preferred way to select the evidence events for which affidavits should be generated. Supported values: `Submitted`, `SubmittedAdvanced`, `TransmissionResult`, `DeliveryResult`, `Read`, `Committed`, `CommittedAdvanced`, `Closed`, `ClosedAdvanced`, `Complete`, `CompleteAdvanced`, `OnDemand`, `Event`, `Failed`.

To enable on-demand affidavits via `POST /v1/EviMail/AffidavitRequest`, include `OnDemand` in this array.

### `DeliveryAppearance`

Controls the visual appearance of the notification page shown to the recipient. Accepted values: `Certified` (default, shows the standard Namirial Notify branded delivery UI) or `AsIs` (plain appearance without certification branding). EviNotice exposes the same concept through a field named `NotificationLayout`.

### `EvidenceAccessControlMethod`

Controls how recipients access the evidence. Supported values: `Public`, `Challenge`, `AutoChallenge`. When omitted, the account's configured default method applies.

`Challenge` requires the corresponding `EvidenceAccessControlChallenge` and `EvidenceAccessControlChallengeResponse` fields to be present. `AutoChallenge` uses a platform-generated challenge based on known recipient data and does not require those fields.

### Commitment reason fields

When using `CommitmentOptions`, accept/reject reason fields are only valid when `CommitmentCommentsAllowed` is `true`. Accept-only reason fields are not valid with reject-only mode, and reject-only reason fields are not valid with accept-only mode. EviNotice exposes the same behaviour through a field named `CommitmentChoice`.

## Error responses

Submit and AffidavitRequest endpoints return a `responseStatus` object for `400 Bad Request` failures:


```json
{
  "responseStatus": {
    "errorCode": "ValidationError",
    "message": "Validation failed for the submitted request.",
    "errors": [
      {
        "errorCode": "NotEmpty",
        "fieldName": "Body",
        "message": "Body must not be empty."
      },
      {
        "errorCode": "MaximumLength",
        "fieldName": "LookupKey",
        "message": "LookupKey must not exceed 35 characters."
      }
    ]
  }
}
```

`errors` is an array of field-level validation failures. Each entry includes the `fieldName` that failed, an `errorCode` identifying the rule, and a human-readable `message`. Fix each reported field and retry with a new idempotency token.

## OpenAPI specification

The OpenAPI 3.0.3 specification for the EviMail API provides a machine-readable definition of the documented service endpoints, request and response schemas, authentication method, and error responses. Some legacy or account-gated fields may still require source confirmation or Namirial support guidance before use.

**Covered in the specification:**

- **Submit endpoint** (`POST /v1/EviMail/Submit`) — detailed request and response schemas, validation rules, and HTTP status codes
- **Query endpoint** (`GET /v1/EviMail/Query`) — pagination parameters, filtering options, and result structure
- **Affidavit request endpoint** (`POST /v1/EviMail/AffidavitRequest`) — on-demand affidavit generation
- **Authentication** — HTTP Basic authentication requirements
- **Error handling** — EviMail V1 endpoints use service-style error responses with a `responseStatus` object for validation and business-rule failures
- **Data types** — schema definitions for documented messages, recipients, attachments, and affidavits


The OpenAPI spec can be used to generate client libraries, integration tests, or interactive API documentation.

[View OpenAPI spec →](/products/namirialnotify/apis/oas/evimail-api)

## Related

- [EviMail](/products/namirialnotify/services/evimail)
- [EviSMS API](/products/namirialnotify/apis/evisms-api)
- [EviNotice API](/products/namirialnotify/apis/evinotice-api)
- [EviPost API](/products/namirialnotify/apis/evipost-api)
- [API documentation](/products/namirialnotify/dev/api-documentation)
- [Callbacks and webhooks](/products/namirialnotify/dev/callbacks)
- [Error handling](/products/namirialnotify/dev/error-handling)
- [Integration workflows](/products/namirialnotify/dev/integration-patterns)
- [Security and authentication](/products/namirialnotify/dev/security-best-practices)
- [States and outcomes](/products/namirialnotify/user-guides/states-outcomes)
- [Evidence and affidavits](/products/namirialnotify/user-guides/evidences-affidavits)