> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Shared link one-time passcode events

> Audit one-time passcode (OTP) settings changes, access decisions, and passcode challenges on public shared links with enterprise events.

One-time passcode (OTP) protection requires anonymous recipients of a public shared link (`access` set to `open`) to verify their email address with a code sent to their inbox before they can access the content. To audit who accessed OTP-protected links, which codes were sent and to whom, and how OTP settings changed, use the following events in the enterprise event stream:

| Event type | Triggered when |
| - | - |
| `ITEM_SHARED_UPDATE` | The shared link settings are updated. OTP changes are included in `additional_details.sharedLinkSettings`. |
| `SHARED_LINK_ONE_TIME_PASSCODE_ACCESS` | A viewer opens an OTP-protected shared link and Box decides whether to grant access, deny access, or request a passcode. |
| `SHARED_LINK_ONE_TIME_PASSCODE_CHALLENGE` | A recipient submits an email address to receive a passcode, or submits a passcode for verification. |

These events follow the standard event object schema and are available in both the `admin_logs` and `admin_logs_streaming` stream types. Only admins of the enterprise that owns the shared item can see them.

> [!WARNING]
>
> OTP events contain email addresses of recipients, including people outside your enterprise. The `email`, `grantedEmail`, and Access List `value` fields are personally identifiable information. Handle them according to your organization's data protection policies.

## OTP modes

The `mode` and `otpMode` fields use the same values as the `one_time_passcode.mode` field of a shared link. In the Box web app, the `allowlist` mode is labeled **Only people added to the link's Access List**.

| Value | Description |
| - | - |
| `none` | OTP protection is turned off. Anyone with the link can access it without a passcode. |
| `open` | Any recipient can request a passcode and access the link after verifying their email address. |
| `allowlist` | Only recipients whose email address matches an entry on the link's Access List can access the link. |

## OTP settings updated

The existing `ITEM_SHARED_UPDATE` event includes the OTP configuration before and after each change in `additional_details.sharedLinkSettings`, alongside the other shared link settings, such as `oldVisibilityStatus` and `newIsPasswordProtected`. The event captures turning OTP on or off, switching between `open` and `allowlist` modes, and adding or removing Access List entries. The event is triggered by changes made in the Box web app and through the shared link endpoints, such as add shared link to file.

When a shared link update doesn't involve OTP, the OTP fields are `null`.

| Field | Description |
| - | - |
| `oldOneTimePasscodeSettings` | The OTP settings before the update. |
| `newOneTimePasscodeSettings` | The OTP settings after the update. |
| `oldOneTimePasscodeSettings.mode`, `newOneTimePasscodeSettings.mode` | The OTP mode: `none`, `open`, or `allowlist`. |
| `oldOneTimePasscodeSettings.allowlist`, `newOneTimePasscodeSettings.allowlist` | The Access List entries. `null` when `mode` is `none` or `open`. |
| `allowlist[].type` | `email` for a single email address, or `domain` for every email address at a domain. |
| `allowlist[].value` | The email address, or the domain without the `@` symbol. For example, `example.com`. |

The following example shows an owner removing a domain from a link's Access List:

```json theme={null}
{
  "source": {
    "item_type": "file",
    "item_id": "1234567890123",
    "item_name": "Q3 pricing proposal.pdf",
    "parent": {
      "type": "folder",
      "name": "Sales",
      "id": "998877665544"
    },
    "owned_by": {
      "type": "user",
      "id": "5544332211",
      "name": "Owner Name",
      "login": "owner@example.com"
    }
  },
  "created_by": {
    "type": "user",
    "id": "5544332211",
    "name": "Owner Name",
    "login": "owner@example.com"
  },
  "action_by": null,
  "created_at": "2026-09-14T09:15:22-07:00",
  "event_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c01",
  "event_type": "ITEM_SHARED_UPDATE",
  "ip_address": "198.51.100.7",
  "type": "event",
  "session_id": null,
  "additional_details": {
    "shared_link_id": "l07r8kq89kna2qhjaaurkv4cey6boyjp",
    "sharedLinkSettings": {
      "oldVisibilityStatus": "Open",
      "newVisibilityStatus": "Open",
      "oldIsPasswordProtected": false,
      "newIsPasswordProtected": false,
      "oldCanPreview": true,
      "newCanPreview": true,
      "oldCanEdit": false,
      "newCanEdit": false,
      "oldCanDownload": true,
      "newCanDownload": true,
      "oldIsExpirationDateSet": false,
      "newIsExpirationDateSet": false,
      "oldOneTimePasscodeSettings": {
        "mode": "allowlist",
        "allowlist": [
          { "type": "email", "value": "alice@example.com" },
          { "type": "domain", "value": "partner.example.com" }
        ]
      },
      "newOneTimePasscodeSettings": {
        "mode": "allowlist",
        "allowlist": [
          { "type": "email", "value": "alice@example.com" }
        ]
      }
    }
  }
}
```

The following example shows the `additional_details` of an owner switching from `allowlist` to `open` mode:

```json theme={null}
{
  "additional_details": {
    "sharedLinkSettings": {
      "oldOneTimePasscodeSettings": {
        "mode": "allowlist",
        "allowlist": [
          { "type": "email", "value": "alice@example.com" },
          { "type": "domain", "value": "partner.example.com" }
        ]
      },
      "newOneTimePasscodeSettings": {
        "mode": "open",
        "allowlist": null
      }
    }
  }
}
```

## OTP access decision

A `SHARED_LINK_ONE_TIME_PASSCODE_ACCESS` event is triggered each time someone opens an OTP-protected shared link, for both signed-in Box users and anonymous recipients. The `decision` and `reason` fields describe the outcome. The event stores the access decision in a `sharedLinkOneTimePasscodeAccess` object inside the event's `additional_details` field, with the following fields:

| Field | Description |
| - | - |
| `otpMode` | The OTP mode when access was evaluated: `open` or `allowlist`. |
| `decision` | The outcome: `granted`, `denied`, or `otp_required`. |
| `reason` | The reason for the decision. See the following table. |
| `grantedEmail` | The email address that was granted access. Only included when `decision` is `granted`. For other decisions, the viewer's identity is in `created_by`. |

Fields without a value are omitted from `sharedLinkOneTimePasscodeAccess`, rather than set to `null`.

| `decision` | `reason` | Description |
| - | - | - |
| `granted` | `owner_or_collab` | The viewer is the owner or a collaborator on the item. |
| `granted` | `session_reuse` | An anonymous recipient already verified their email address within the last hour. |
| `granted` | `auto_verified_allowlist` | A signed-in Box user's email address matches an entry on the Access List. |
| `granted` | `exempt_open` | A signed-in Box user opened a link in `open` mode. |
| `denied` | `allowlist_miss` | The viewer's email address doesn't match any entry on the Access List. |
| `denied` | `evaluation_failure` | Box couldn't evaluate access. |
| `otp_required` | `otp_required` | The viewer must verify their email address with a passcode. |

The following example shows an anonymous recipient who verified their email address earlier in the session:

```json theme={null}
{
  "source": {
    "item_type": "file",
    "item_id": "1234567890123",
    "item_name": "Q3 pricing proposal.pdf",
    "parent": {
      "type": "folder",
      "name": "Sales",
      "id": "998877665544"
    },
    "owned_by": {
      "type": "user",
      "id": "5544332211",
      "name": "Owner Name",
      "login": "owner@example.com"
    }
  },
  "created_by": {
    "type": "user",
    "id": "2",
    "name": "Unknown User",
    "login": ""
  },
  "action_by": null,
  "created_at": "2026-09-14T14:22:37-07:00",
  "event_id": "12345678-abcd-4321-8765-abcdef012345",
  "event_type": "SHARED_LINK_ONE_TIME_PASSCODE_ACCESS",
  "ip_address": "203.0.113.42",
  "type": "event",
  "session_id": null,
  "additional_details": {
    "shared_link_id": "l07r8kq89kna2qhjaaurkv4cey6boyjp",
    "sharedLinkOneTimePasscodeAccess": {
      "otpMode": "allowlist",
      "decision": "granted",
      "reason": "session_reuse",
      "grantedEmail": "recipient@partner.example.com"
    }
  }
}
```

The following example shows the `created_by` and `additional_details` of a signed-in user whose email address isn't on the Access List:

```json theme={null}
{
  "created_by": {
    "type": "user",
    "id": "88776655",
    "name": "Viewer Name",
    "login": "viewer@partner.example.com"
  },
  "event_type": "SHARED_LINK_ONE_TIME_PASSCODE_ACCESS",
  "additional_details": {
    "shared_link_id": "l07r8kq89kna2qhjaaurkv4cey6boyjp",
    "sharedLinkOneTimePasscodeAccess": {
      "otpMode": "allowlist",
      "decision": "denied",
      "reason": "allowlist_miss"
    }
  }
}
```

## OTP challenge

A `SHARED_LINK_ONE_TIME_PASSCODE_CHALLENGE` event is triggered at each step of the passcode challenge: when a recipient submits an email address to receive a code (`send` phase), and when they submit a code (`verify` phase). The event stores the challenge details in a `sharedLinkOneTimePasscodeChallenge` object inside the event's `additional_details` field, with the following fields:

| Field | Description |
| - | - |
| `otpMode` | The OTP mode when the challenge was processed: `open` or `allowlist`. |
| `phase` | The challenge step: `send` or `verify`. |
| `result` | The outcome of the step. See the following table. |
| `email` | The email address the recipient submitted. Present for every phase and result. |

| `result` | Description |
| - | - |
| `ok` | In the `send` phase, the code was sent. In the `verify` phase, the code was correct and the email address is verified. |
| `invalid_code` | The submitted code is incorrect. |
| `expired_code` | The submitted code has expired. |
| `allowlist_miss` | The email address doesn't match any entry on the Access List. |
| `rate_limited` | The request exceeded a passcode request or verification limit. |
| `captcha_required` | The recipient must complete a CAPTCHA before continuing. |
| `service_unavailable` | Box couldn't process the request. |

The following example shows a code sent to a recipient:

```json theme={null}
{
  "source": {
    "item_type": "file",
    "item_id": "1234567890123",
    "item_name": "Q3 pricing proposal.pdf",
    "parent": {
      "type": "folder",
      "name": "Sales",
      "id": "998877665544"
    },
    "owned_by": {
      "type": "user",
      "id": "5544332211",
      "name": "Owner Name",
      "login": "owner@example.com"
    }
  },
  "created_by": {
    "type": "user",
    "id": "2",
    "name": "Unknown User",
    "login": ""
  },
  "action_by": null,
  "created_at": "2026-09-14T14:22:07-07:00",
  "event_id": "9f1c3a8b-4e7d-4b21-9c19-2a2f5a6c1a01",
  "event_type": "SHARED_LINK_ONE_TIME_PASSCODE_CHALLENGE",
  "ip_address": "203.0.113.42",
  "type": "event",
  "session_id": null,
  "additional_details": {
    "shared_link_id": "l07r8kq89kna2qhjaaurkv4cey6boyjp",
    "sharedLinkOneTimePasscodeChallenge": {
      "otpMode": "allowlist",
      "phase": "send",
      "result": "ok",
      "email": "alice@example.com"
    }
  }
}
```

The following example shows the `additional_details` of the same recipient submitting an incorrect code:

```json theme={null}
{
  "additional_details": {
    "shared_link_id": "l07r8kq89kna2qhjaaurkv4cey6boyjp",
    "sharedLinkOneTimePasscodeChallenge": {
      "otpMode": "allowlist",
      "phase": "verify",
      "result": "invalid_code",
      "email": "alice@example.com"
    }
  }
}
```

## Preview and download events

When an anonymous recipient previews or downloads content through an OTP-protected link, the `PREVIEW` and `DOWNLOAD` events still identify the recipient as an anonymous user, with a `created_by.id` of `2`. These events don't include the verified email address. To find out which email addresses accessed a link, use `SHARED_LINK_ONE_TIME_PASSCODE_ACCESS` and `SHARED_LINK_ONE_TIME_PASSCODE_CHALLENGE` events.

**RELATED APIS**

**RELATED GUIDES**
