# Integration workflows

Common end-to-end patterns that repeat across the Namirial Notify APIs.

Use it together with the service reference pages when you are designing a
production integration.

## Shared integration pattern

Regardless of service, the recommended lifecycle is:

1. Submit the transaction and store the returned identifier.
2. Store your own correlation key, typically `LookupKey`.
3. Configure callbacks when you need near-real-time status updates.
4. Use Query or Get operations to reconcile state and retrieve evidence.
5. Download or request affidavit content only when your workflow needs it.


| Step | What to persist in your system |
|  --- | --- |
| Submit | Request timestamp, environment, service, returned transaction ID |
| Correlation | `LookupKey` and any internal business identifier |
| Tracking | Last known state, outcome, callback event identifiers |
| Evidence retrieval | Affidavit IDs, attachment IDs, download timestamps |


## Workflow 1: EviMail and EviSMS

Use this pattern when the certified content is the delivered message itself.

### Recommended flow

1. Submit the message with `POST /v1/EviMail/Submit` or
`POST /v1/EviSms/Submit`. Include `X-Evi-IdempotencyToken` to protect
against duplicate submissions when your client retries.
2. Persist the returned `eviId`.
3. Configure `PushNotificationUrl`, `PushNotificationFilter`, and optionally
`PushNotificationExtraData` if you want asynchronous updates.
4. Process callbacks as state changes arrive.
5. Reconcile with `GET /v1/EviMail/Query` or `GET /v1/EviSms/Query` using
`WithUniqueIds` or `WithLookupKeys`.
6. Request affidavit metadata from the query response only when needed by using
`IncludeAffidavits`.
7. For EviMail on-demand affidavits: if the original submit included
`AffidavitKinds: [OnDemand]`, request a custom affidavit with
`POST /v1/EviMail/AffidavitRequest`.


### Good production pattern

- Use callbacks as the primary signal for progress.
- Use Query as a reconciliation step, a recovery path, or a scheduled audit.
- Avoid requesting affidavit or attachment metadata on every poll.
- Treat EviMail on-demand affidavits as a separate asynchronous workflow from
normal state tracking.


## Workflow 2: EviNotice

Use this pattern when the certified content is hosted on the platform and the
recipient interacts with that hosted notice.

### Recommended flow

1. Submit the notice with `POST /v2/EviNotice/Submit`. Include
`X-Evi-IdempotencyToken` to protect against duplicate submissions when
your client retries.
2. Persist the returned `Id`.
3. Configure callback fields if you need asynchronous updates.
4. Process notice callbacks such as `Processed`, `Delivered`, `Received`,
`Read`, `Replied`, and `Closed`.
5. Retrieve the current record with `GET /v2/EviNotice/{Id}` when
you need the latest full object.
6. Use `IncludeAffidavits` or `IncludeAttachments` on the Get endpoint for
metadata-driven retrieval.
7. Download ZIP archives from `/Affidavits` or `/Attachments` only when your
process actually needs the files.


The legacy `/api/v2/...` form is still accepted for backward compatibility. For new integrations, use the `/v2/...` routes shown here.

### Pagination pattern

When reconciling many notices, use `POST /v2/EviNotice/Query` with
`Limit` and `Cursor` rather than repeatedly fetching single notices.

## Workflow 3: EviPost

Use this pattern when physical postal delivery is part of the certified process.

### Recommended flow

1. Submit with `POST /v1/EviPost/Submit`.
2. Include `X-Evi-IdempotencyToken` to protect against duplicate submits when
your client retries.
3. Persist the returned `uniqueId`.
4. Configure `PushNotificationUrl` and `PushNotificationFilter` when you need
asynchronous state tracking.
5. Reconcile with `GET /v1/EviPost/Query`.
6. If you need a custom affidavit after submission, call
`POST /v1/EviPost/AffidavitRequest`. This requires `AffidavitsOnDemandEnabled: true`
and an advanced `AffidavitProfile` in the original Submit.
7. When the affidavit is ready, the platform fires an `AffidavitPublished` callback
to the `PushNotificationUrl` configured at submission, provided `AffidavitPublished`
is included in `PushNotificationFilter`.


### Good production pattern

- Treat on-demand affidavit generation as a separate asynchronous workflow.
- Keep the main delivery lifecycle and the affidavit-request lifecycle as two
distinct processes in your integration.


## Workflow 4: Batch sending (EviNotice, EviMail, EviSMS)

Use this pattern when you need to send the same certified communication to many recipients as a single managed job.

### Recommended flow

1. Create an empty batch with `POST /v2/Evi{Service}/Batches`. You receive a `BatchId`.
2. Set the content — for EviNotice and EviMail, upload the HTML body with `PUT .../Body`; for EviSMS, set the `Text` field via `PATCH`.
3. Upload recipients with `POST .../Recipients` as a `text/csv` file.
4. Optionally add attachments with `POST .../Attachments` (EviNotice and EviMail only).
5. Configure per-message options (`PATCH .../{BatchId}`) — certification level, callbacks, scheduling, etc.
6. Start processing by setting `State` to `Submitted` via `PATCH`, or schedule it with `ScheduledDate`.
7. Poll `GET .../{BatchId}` to follow progress (`SentCount`, `FailedCount`, `ProgressPercentage`).


See the service reference pages for the CSV column format and the full option set: [EviNotice batch](/products/namirialnotify/apis/evinotice-api#batch-operations), [EviMail batch](/products/namirialnotify/apis/evimail-api#batch-operations), [EviSMS batch](/products/namirialnotify/apis/evisms-api#batch-operations).

The batch API is under the **v2** base path (`/v2/Evi{Service}/Batches`), even for EviMail and EviSMS whose single-send operations use `/v1`.

## Callback-first, query-second

Across EviNotice, EviMail, EviSMS, and EviPost:

- Prefer callbacks for near-real-time updates.
- Use Query or Get endpoints for reconciliation, backfilling, and auditing.
- Make callback handling idempotent, because retries can happen if your
endpoint is unavailable or slow.
- Do not assume callbacks arrive in lifecycle order. Deduplicate by `Identifier`,
use `Date` as the event time, and reconcile with Query or Get.


See [Callbacks and webhooks](/products/namirialnotify/dev/callbacks) for payload examples and retry
behavior.

## Polling-based status tracking

If your integration cannot receive callbacks, you can track status by polling the
Query or Get endpoints. Interpret the results using the **timestamp fields** rather
than the live `State` or `Outcome`. `State` changes as the transaction advances,
while `Outcome` may remain `None` until closure. Neither should be treated as the
final result until `State` is `Closed`; at that point, `Outcome` is final. See
[State, outcome, and timestamp fields](/products/namirialnotify/user-guides/states-outcomes#state-outcome-and-timestamp-fields)
for the full model.

### Submission: 20x versus 4xx

- A **4xx** response means the request was rejected and the transaction never
entered the system. The error body lists the reasons. Nothing is created and
there is nothing to poll.
- A **20x** response means the request was accepted. The transaction is created
and processed asynchronously in the background. The applicable submission
timestamp (`NewOn` or `SubmittedOn`) is set first, followed by `ReadyOn` or
`ProcessedOn`, then `DispatchedOn`, and later milestones as processing advances.


A successful 20x does **not** guarantee final success. After acceptance, the
transaction can still fail during asynchronous processing — for example, an
EviNotice with an unparseable or encrypted PDF attachment whose
`IncludeOnAffidavits` is enabled is accepted first and only later transitions to
`State = Closed`, `Outcome = Failed`. There is no dedicated error-detail field in
the API for these cases; the detail is available in the web interface and the
affidavits.

### Deriving status flags by polling

Map your business flags to timestamp fields:

| Flag | Field to check |
|  --- | --- |
| Processed and certified by the platform | `ReadyOn` is present (`ProcessedOn` for EviNotice) |
| Handed to the sending process or channel | `DispatchedOn` is present |
| Accepted by the recipient's server / operator | `SentOn` is present |
| Delivered | `DeliveredOn` is present |
| Read | `ReadOn` is present. For EviSMS, read tracking requires RCS delivery; plain SMS cannot report reads. |
| Downloaded (EviNotice) | the content/attachment download affidavit is present — there is no timestamp for downloads, and the affidavit is only generated if it was requested at submit time |


**Transmission diagnostics**

Where exposed, `XmissionResult` and `XmissionSummary` provide the recorded
transmission result and human-readable diagnostic details. These fields can be
updated as sending attempts are processed. Do not parse `XmissionSummary` or use
either field as a lifecycle state. Derive business flags from the milestone
timestamps, and use the final `Outcome` after the state becomes `Closed`.

### Recommended polling loop

1. Submit and store the returned ID and your `LookupKey`.
2. Poll Query or Get on a backoff interval until `State` is `Closed`.
3. On each poll, update your flags from the timestamp fields.
4. When `State` is `Closed`, read the final `Outcome` and stop polling.
5. For EviNotice, EviMail, and EviSMS, keep polling within the transaction's
`TimeToLive` window; once it elapses the state moves to `Closed` and no further
timestamps will appear. EviPost has no submit-configurable `TimeToLive` — its
lifecycle follows postal-operator timelines instead.


Query, Get, and Download endpoints are rate-limited. Use a backoff interval
rather than tight polling, and reconcile in batches where the endpoint supports
it. Pre-production rate limits are lower than production — size your polling
accordingly.

## Common implementation checklist

- Store the service-specific transaction ID returned by Submit.
- Store your own stable `LookupKey` so you can correlate business events.
- Separate operational status tracking from large file retrieval.
- Design callback processing to be idempotent.
- Reconcile state periodically, even when callbacks are enabled.
- Download affidavit blobs, attachment blobs, or ZIP archives only in the steps
that require them.


## Related

- [API documentation](/products/namirialnotify/dev/api-documentation)
- [Callbacks and webhooks](/products/namirialnotify/dev/callbacks)
- [Error handling](/products/namirialnotify/dev/error-handling)
- [Performance and scaling](/products/namirialnotify/dev/performance-guidelines)
- [States and outcomes](/products/namirialnotify/user-guides/states-outcomes)
- [EviMail API](/products/namirialnotify/apis/evimail-api)
- [EviSMS API](/products/namirialnotify/apis/evisms-api)
- [EviNotice API](/products/namirialnotify/apis/evinotice-api)
- [EviPost API](/products/namirialnotify/apis/evipost-api)