# Provider integration handoff — API 1.1.0

API: https://imessage.velroi.com
Reference: https://documentation-production-4b29.up.railway.app
Machine-readable contract: https://documentation-production-4b29.up.railway.app/openapi.json

The relay now implements enrolled-recipient inbound events, durable STOP suppression, signed webhooks, and observed native sent/delivered/read/failed status. Describing version 1.1 as outbound-only is no longer accurate. It remains a Mac Messages relay, with no guaranteed SMS delivery receipts.

## Adapter contract

| Application operation | Relay operation |
| --- | --- |
| Check transport readiness | GET /v1/capabilities and GET /v1/readiness |
| Prepare to receive a verification or opt-in reply | POST /v1/recipients with recipient and consent:true before the reply is expected |
| Send after application controls pass | POST /v1/messages with stable Idempotency-Key; persist requestId/providerMessageId |
| Observe delivery/read/error | GET /v1/requests/{requestId}, or message.status events; inspect delivery independently from submission status |
| Receive replies and codes | Signed message.received webhook, or durable GET /v1/events cursor |
| Process STOP | recipient.opted_out event; cancel application jobs and suppress linked identities. Relay already blocks this address and containing groups. |
| Confirm opt-out | Caller-triggered fixed opt_out_confirmation request, once per opt-out event; keep the same key on retry |
| Record revocation elsewhere | POST /v1/recipients/{recipient}/suppress |
| Re-consent | Capture fresh evidence, then POST /v1/recipients/{recipient}/restore with its reference |
| Recover receiver outage | Replay from last durably processed cursor; deduplicate event.id |

Configure POST /v1/webhooks with your public HTTPS receiver URL and a separate random signing secret. Verify timestamp and HMAC over the raw body before JSON parsing; atomically persist/deduplicate and queue before returning 2xx. No receiver is automatically registered. Return 2xx for already accepted duplicates. A failed webhook blocks subsequent events on that subscription, so monitor backlog and use the event polling endpoint for recovery.

Do not map HTTP 202, submission status submitted, or delivery status sent to delivered. API providerMessageId is the request UUID; delivery.nativeMessageId is the separately correlated Messages GUID. An incoming providerMessageId is the native GUID. SMS may never expose delivered/read. Unknown or ambiguous sends require reconciliation; never create a fresh idempotency key just to retry an uncertain send.

## Application acceptance work

Keep the provider interface and fake-provider tests. Test consent/identity controls, disclosures, quiet hours, expiry, queued-job cancellation, HELP/HUMAN/REPORT handling, receiver signature rejection/replay, and receipt normalization. The relay does not implement those product workflows. Check readiness and current application consent/suppression immediately before dispatch, and keep jobs durably queued while the Mac is unavailable.

The adapter must prioritize recognized STOP and reasonable revocations, handle the fixed confirmation under the application's timing requirements, and never restore consent automatically from START. An undecodable inbound record without attachments blocks that sender pending review. Registration only exposes future replies; pre-upgrade conversations are not imported.

This transport upgrade does not approve a consumer launch or change a product's permitted channels. If a product requires CPaaS, Apple Messages for Business, guaranteed carrier callbacks, or prohibits Mac relays, those requirements still apply. iMessage is not Apple Messages for Business. Keep the consumer provider gate closed until the product's channel policy and acceptance criteria are satisfied.

## Verification scope

The relay's automated suite covers fake native input, STOP and group blocking, explicit restoration, one-time confirmations, idempotency, crash recovery, webhook signatures/retries, and observed receipt transitions. A read-only check of a previously authorized owner test can validate the Mac's native decoder and receipt correlation without sending another message. Synthetic webhook tests are not proof of a deployed application's receiver or student M2 controls. A fresh live reply/STOP round trip needs the receiver configured and an authorized participant during the applicable notification window.
