8 8
9Use this integration to:9Use this integration to:
10 10
11- Route warning and deactivation notices to your trust and safety, security, or support team.11- Route warning and deactivation notices to your trust and safety or support team.
12- Add case details to an investigation or support ticket.12- Add case info to an investigation or support ticket.
13- Associate a notice with a user through your application's safety-identifier mapping.13- Associate a notice with a user through your application's safety-identifier mapping.
14 14
15The steps in this guide use a warning to illustrate the workflow. You can use the same integration for deactivation notices.15The steps in this guide use a warning to illustrate the workflow. You can use the same integration for deactivation notices.
16 16
17## How it works17## How it works
18 18
19Safety webhooks notify your application that a notice was issued. The Safety Case Read API provides the details for that notice.19[Safety webhooks](https://developers.openai.com/api/reference/resources/webhooks#safety.warning_issued) notify your application that a notice was issued.
20 20
21| Event | Notice |21| Event | Notice |
22| ---------------------------- | ------------------------------------------------------------ |22| ---------------------------- | ------------------------------------------------------------ |
25 25
26Each event contains a case ID. Use it with `GET /v1/safety/cases/{id}` to retrieve the safety identifier, notice type, case creation timestamp, and available policy reason.26Each event contains a case ID. Use it with `GET /v1/safety/cases/{id}` to retrieve the safety identifier, notice type, case creation timestamp, and available policy reason.
27 27
28These organization-level notifications are separate from project-level [misalignment alerts](https://developers.openai.com/api/docs/guides/safety-checks/misalignment-monitoring#receive-project-safety-alerts). Retrieving a case does not change or reverse the enforcement. The API returns case metadata, not the underlying conversation or a full investigation report.28These organization-level notifications are separate from project-level [misalignment alerts](https://developers.openai.com/api/docs/guides/safety-checks/misalignment-monitoring#receive-project-safety-alerts). Retrieving a case does not change or reverse the enforcement.
29 29
30## Integrate with your application30## Integrate with your application
31 31
32Start by configuring an organization-level webhook and a key for case lookups. Then connect the notifications to your review workflow.32Start by configuring an organization-level webhook and a key for case lookups. Then connect the notifications to your review workflow.
33 33
34### 1. Configure your webhook and API key34### Configure your webhook and receive events
35 35
36Use a stable [safety identifier](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers) for each user, and keep your application's mapping from that identifier to the user. Avoid including personal information in the identifier.36Use a stable [safety identifier](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers) for each user, and keep your application's mapping from that identifier to the user. Avoid including personal information in the identifier.
37 37
38Open your [organization webhook settings](https://platform.openai.com/settings/organization/webhooks) and select **Create**. Enter your receiver's HTTPS URL and subscribe to `safety.warning_issued` and `safety.deactivation_issued`. Save the signing secret securely so your receiver can verify incoming events. These events use an organization endpoint, not a project endpoint.38Create an organization-level webhook endpoint in your [organization webhook settings](https://platform.openai.com/settings/organization/webhooks) and subscribe to `safety.warning_issued` and `safety.deactivation_issued`.
39 39
40Your account needs `api.webhooks.read` and `organization.read` to view organization webhooks, plus `api.webhooks.write` and `organization.write` to create them. See [Permissions](https://developers.openai.com/api/docs/guides/rbac) for role configuration.40A warning notification has the following structure:
41
42For case lookups, configure an API key for the same organization with **Restricted** permissions and set **Safety** to **Read** (`api.safety.read`). The API key authenticates case lookups; it is separate from the webhook signing secret.
43
44### 2. Receive and verify the event
45
46A warning notification has this structure. The IDs are illustrative:
47 41
48```json42```json
49{43{
52 "created_at": 1787659200,46 "created_at": 1787659200,
53 "type": "safety.warning_issued",47 "type": "safety.warning_issued",
54 "data": {48 "data": {
55 "id": "C-example"49 "id": "C-abc123"
56 }50 }
57}51}
58```52```
59 53
60Verify the signature before processing the event. Save the verified event for processing, return a successful `2xx` response promptly, and retrieve the case in a background worker. See the Webhooks guide for [signature verification](https://developers.openai.com/api/docs/guides/webhooks#verifying-webhook-signatures) and [acknowledgments, retries, and duplicate deliveries](https://developers.openai.com/api/docs/guides/webhooks#handling-webhook-requests-on-a-server).54For general webhook best practices, see the [Webhooks guide](https://developers.openai.com/api/docs/guides/webhooks).
61 55
62The event's `id` identifies the webhook event. Its `data.id` identifies the safety case to retrieve.56The event's `id` identifies the webhook event. Its `data.id` identifies the safety case to retrieve.
63 57
64### 3. Retrieve the case58### Retrieve the case
59
60For case lookups, configure an API key for the same organization with **Restricted** permissions and set **Safety** to **Read** (`api.safety.read`).
65 61
66Set `OPENAI_API_KEY` to your API key. Replace `C-example` with `data.id` from the verified event:62Look up case metadata through the Safety Case Read API:
67 63
68```bash64```bash
69curl "https://api.openai.com/v1/safety/cases/C-example" \65curl "https://api.openai.com/v1/safety/cases/C-abc123" \
70 -H "Authorization: Bearer ${OPENAI_API_KEY}"66 -H "Authorization: Bearer ${OPENAI_API_KEY}"
71```67```
72 68
74 70
75```json71```json
76{72{
77 "id": "C-example",73 "id": "C-abc123",
78 "object": "safety.case",74 "object": "safety.case",
79 "created_at": 1787659100,75 "created_at": 1787659100,
80 "entity_identifier": "safety-id-example",76 "entity_identifier": "entity_identifier",
81 "reason": "cyber_abuse",77 "reason": "cyber_abuse",
82 "notice": {78 "notice": {
83 "type": "warning"79 "type": "warning"
85}81}
86```82```
87 83
88Use `entity_identifier` to find the affected user in your application. The `reason` can be `null`; continue processing the notice when no reason is available.84The `entity_identifier` represents the affected safety identifier. The case creation timestamp can be used to help with investigation. See the [Safety Case API reference](https://developers.openai.com/api/reference/resources/safety/subresources/cases/methods/retrieve) for field definitions.
89
90The case creation timestamp is not necessarily the event timestamp or the time of an individual request. See the [Safety Case API reference](https://developers.openai.com/api/reference/resources/safety/subresources/cases/methods/retrieve) for field definitions.
91
92### 4. Create a review ticket
93
94Add the case ID, notice type, safety identifier, case creation timestamp, and available policy reason to your internal ticket. Link the matching user record so your team can investigate using its own application records. If you cannot find a matching user, preserve the case details and flag the missing mapping for review.
95 85
96Make ticket creation safe to retry. Follow the [webhook deduplication guidance](https://developers.openai.com/api/docs/guides/webhooks#handling-webhook-requests-on-a-server) so repeated deliveries do not create duplicate tickets. Retries of your own background processing should also reuse the existing ticket.86### Connect to your workflows
97 87
98If an agent helps with triage, limit its access to the records it needs and keep customer-facing actions subject to your existing approval controls.88Use webhooks to receive notifications, then use case metadata to programmatically route those notices into your existing investigation or support systems.
99
100## Confirm it's working
101
102For a real event and an accessible case in your organization, check that:
103
1041. Your receiver verifies the signature and returns a successful acknowledgment.
1052. The lookup returns HTTP `200`, with a case `id` matching the event's `data.id`.
1063. Your application identifies the expected user or flags a missing mapping.
1074. One review ticket contains the available case details. Reprocessing the event does not create another ticket.
108
109Before receiving a real notice, test your processing logic with local example events and mocked case responses. Include both notice types, a `null` reason, a missing user mapping, and duplicate deliveries. Test signature verification separately, including rejection of invalid signatures; keep it enabled on your production receiver.
110
111The example IDs on this page are not retrievable cases. Mocked tests validate your processing logic, not live delivery or API permissions. Do not trigger an actual enforcement to test your integration. An absence of enforcement notifications alone does not indicate a broken integration.
112 89
113## Troubleshoot90## Troubleshoot
114 91
119| Lookup returns `403` | Check that the key has the `api.safety.read` permission. |96| Lookup returns `403` | Check that the key has the `api.safety.read` permission. |
120| Lookup returns `404` | Use `data.id`, not the event ID. Check that the case belongs to the key's organization. |97| Lookup returns `404` | Use `data.id`, not the event ID. Check that the case belongs to the key's organization. |
121| Lookup returns `429` or a transient `5xx` | Retry with backoff and a bounded retry policy. Preserve the event for later processing or investigation. |98| Lookup returns `429` or a transient `5xx` | Retry with backoff and a bounded retry policy. Preserve the event for later processing or investigation. |
122| A ticket is created more than once | Check that ticket creation remains safe across repeated deliveries and worker retries. |
123
124Do not silently discard a verified notification when its case lookup fails. Keep it available for retry or investigation.