> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.fortresstech.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.fortresstech.io/_mcp/server.

# CORA events

Every event uses the [event envelope](/webhooks/webhooks#the-event-envelope) and is signed as described in [Webhooks](/webhooks/webhooks).

| Event                                                                                          | When Fortress sends it                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`application.signed`](/webhooks/webhook-events/webhooks/application-signed)                   | The last adult applicant signs the application. The bundle serves the current definition version for each document type.                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| [`requirement.upload_received`](/webhooks/webhook-events/webhooks/requirement-upload-received) | A document is uploaded to a requirement. The document starts at `NOT_YET_REVIEWED`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| [`requirement.upload_removed`](/webhooks/webhook-events/webhooks/requirement-upload-removed)   | A Fortress user removes a document from a requirement.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| [`compliance_review.opened`](/webhooks/webhook-events/webhooks/compliance-review-opened)       | Staff open a manual compliance review, which blocks the whole application; `documentIds` lists the documents under review (empty means application-wide). The cancel route and the Results API answer `409 COMPLIANCE_REVIEW_OPEN` until it closes.                                                                                                                                                                                                                                                                                                                         |
| [`compliance_review.closed`](/webhooks/webhook-events/webhooks/compliance-review-closed)       | Staff close the manual compliance review, with the same `sessionId` and `documentIds`, a `decision` and the `decidedDocumentIds` it set: `APPROVED` / `DENIED` set every covered document to `APPROVED` / `REJECTED` (`statusSetBy: fortress_user`), `NONE` changes none. The cancel route and the Results API accept writes again.                                                                                                                                                                                                                                         |
| [`application.completed`](/webhooks/webhook-events/webhooks/application-completed)             | The application reaches a final status (`APPROVED`, `CANCELED`, `DENIED`, `ABANDONED` or `WAITLIST`), including after a cancellation CORA requested.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| [`agent.state_changed`](/webhooks/webhook-events/webhooks/agent-state-changed)                 | Staff enable or disable an agent (`cora` or `leslie`) for a property in Fortress' agent configuration. Sent for every agent, so ignore events whose `agentKey` is not `cora`. Sent with `scope: PROPERTY` (`organizationId` and `propertyId` set, `householdId` `null`) to that property's active subscriptions that list the event. `GLOBAL` and `HOUSEHOLD` may also be sent; CORA handles every scope from the payload. Also sent when staff change the CORA cadence policy: CORA re-reads the state route and applies the new `cadencePolicy` from its next touchpoint. |
| [`message.received`](/webhooks/webhook-events/webhooks/message-received)                       | An inbound message from the applicant is received, for example a reply to a touchpoint.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

## Testing your receiver

You do not have to wait for the real flow to test your receiver. Call
[`POST /v1/webhooks/trigger`](/api-reference/webhooks/trigger-webhook-event) with the event you want and the organization and property to
test, for example
`{ "eventType": "application.signed", "organizationId": "1a2b3c4d-5e6f-4a1b-8c2d-3e4f5a6b7c8d", "propertyId": "3a1e2b4c-5d6f-4a7b-8c9d-0e1f2a3b4c5d" }`.
Fortress sends that event's documented example payload only to the active `cora` subscriptions of that property that list
that event type in their `eventTypes`, never to other subscriptions, properties or organizations:

* The delivery uses the normal [event envelope](/webhooks/webhooks#the-event-envelope) and
  [`X-Fortress-*` headers](/webhooks/webhooks#delivery-headers), with a fresh `eventId` and `occurredAt`, and is
  signed with the subscription's signing secret. Verify it exactly as you will verify real deliveries.
* Fortress makes one attempt and does not retry. The `200` response lists each subscription with the HTTP status
  your receiver answered, or `failed` when no response was received or Fortress could not sign the delivery. The
  call returns once every delivery has finished; deliveries run in parallel within the gateway's limit of about
  29 seconds.
* Any of the events above except `message.received` can be sent. `message.received` is delivered for real as soon
  as the applicant replies to a message CORA sent with [Send message](/api-reference/messaging/send-message), so you
  can test it end to end with a real conversation instead of an example. A missing or invalid field, another
  `eventType`, or an event Fortress has no example payload for yet returns `400`. An organization or property your API key does not own returns `404` with `code: NOT_FOUND`, and a
  property none of whose active `cora` subscriptions lists the event type returns `404` with `code: NO_SUBSCRIPTION`.
* Your API key needs the `webhooks` permission with `create`. An all-organizations key works, as long as the property
  belongs to the organization you pass.

> **Warning**
>
> The payloads are examples, not real data. Their ids do not point to records in your organization, so do not act on
> them. This includes `data.organizationId` and `data.propertyId`: they are the documented example values, not the ones
> in your request. If your receiver checks the organization, verify the signature first and do not reject a test
> delivery on that check.