> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://contentful.com/developers/docs/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/_mcp/server. # Set up Audit logs > Learn how to set up Audit logs which allow customers to track and view all the changes made in their organization. ## Overview Audit logs allow customers to track and view all the changes made in their organization. They provide visibility and are useful for investigating an incident or getting a detailed report on relevant events (such as changes to roles and permissions, users invited, spaces deleted, etc.). > **Info** > > This is only available on specific plans. [Reach out](https://www.contentful.com/contact/sales/) to your Sales representative for more information. > **Info** > > Looking for a continuous, low-latency feed instead of a daily export? See [Near real-time audit logs](/concepts/near-real-time-audit-logs). The audit logs feature securely transfers this information to your own storage (an AWS S3 bucket or Azure Blob Store), ensuring that you have a clear and accessible history of actions for monitoring and analysis purposes. ## Audit log delivery Audit logs are shipped to your AWS S3 bucket, Azure Blob Store or Google Cloud bucket. Maintaining audit logs in your own storage gives you full control over how long they're kept and how they're managed. This setup helps you meet your organization's retention needs and offers the following benefits: * **Consistency**: This way you can apply the same rules and policies to this as you do for other similar data. You can control who has access to it. * **Data retention**: This enables you to store it for as long as you need to maintain compliance for your company. * **Data analysis**: It allows you to serve this data to the tools you already use for analysis. > **Info** > > Audit logs are updated and delivered on a daily schedule. ### Audit log delivery failures Audit log deliveries can fail when Contentful cannot deliver audit logs to your configured cloud storage provider. These issues occur entirely on the customer side and usually relate to authentication, permissions, or storage configuration. Every time an audit log delivery failure occurs, an email notification is sent to the **organization admins** and **owners**, and a list of failed days is displayed on the "Audit logs" page of the Contentful web app. > **Info** > > You can retry and recover failed deliveries for up to 30 days after the original delivery attempt. ### Potential causes Audit log delivery failures can occur for several reasons, including but not limited to the following: * **Expired or invalid access credentials**. For example, an expired SAS token or other authentication key that needs renewal. * **Insufficient permissions on your storage destination**. For example, the used credentials don't have write access for the specified bucket, container, or storage path. * **Cross-account or trust-relationship configuration errors**. For example, access policies or trust relationships between accounts or services are misconfigured, preventing write access. * **Transient cloud service issues**. Occasionally, cloud providers may return temporary errors even if your configuration is correct. If you suspect this, retry the delivery with your existing configuration. ### How to resolve delivery failures To resolve delivery failures: 1. Review your cloud storage configuration in your provider's console (AWS S3 bucket, Azure Blob Store or Google Cloud). 2. Check that your credentials are valid and have write access to the configured destination. 3. Update any expired tokens or incorrect policy settings. 4. Return to the "Audit logs" page in the organization settings of the Contentful web app and retry delivery for each failed day. ![Audit log delivery failures modal](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/5968e2454a9a45ce0217cb888300aaa4a79748276b0f804553eb5bce67f86125/docs/assets/images/audit-log-delivery-failure.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260929T234804Z&X-Amz-Expires=604800&X-Amz-Signature=0c24d5ddf19184e6aa43cd25372a3d64c980ea6e4bedcac60739e3be0ad040da&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) > **Info** > > If there is no configuration in place, the **Retry** option is grayed out. ## Events captured by the audit log Audit logs capture all changes made through the [Content Management API](/references/content-management-api/overview), focusing on actions and modifications across the entire Contentful organization. This includes any content that has been recently created, updates, deletions, and configuration adjustments performed by users or apps interacting with the CMA. | **Entities** | **Actions logged** | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | 1. Spaces 2. Environments 3. UI config 4. Content model templates 5. References across spaces 6. Space enablements 7. Editor interface 8. UI Extensions 9. Entries 10. Assets 11. Locales 12. Tags 13. Webhooks 14. Roles 15. Snapshots 16. Space membership 17. API Keys 18. Comments 19. Workflows 20. Tasks 21. Releases 22. App installations 23. Organization settings 24. Teams 25. Apps 26. Taxonomy 27. Audit logs 28. SSO configuration 29. Authentication events | * Update of entities * Deletion of entities * Creation of entities * Importing of entities * User logins (with SSO, MFA, username and password) | ## Audit log file naming convention Each audit log file received by customers follows a standardized naming format to provide essential details at a glance. The file name structure is as follows: `contentful-audit-{organization_id}-{datetime}.json` ### Components of the file name 1. `contentful-audit`: Prefix indicating the file type as an audit log. 2. `{organization_id}`: Unique identifier for the organization. This ensures the file is specific to your Contentful organization. 3. `{datetime}`: Each log file is given a name containing a data-time timestamp in the ISO variation `YYYYMMDDTHHMMSSsssZ` format. It usually represents the export date-time but it also serves as an identifier indicating the file contains the audit log data for the previous day (not including the date in filename). Given the current per day audit data delivery frequency, this file name convention should make it easy to infer the contents of the file. 4. `.json`: File extension, indicating the file format as JSON. ### Example file name `contentful-audit-7BLDDu2FYCNoN4QIWys1BR-20251009T040839978Z.json` In this example: * `7BLDDu2FYCNoN4QIWys1BR` is the organization ID. * `20251009T040839978Z` is the export `{datetime}` timestamp, also serving as an identifier for the file data content, the data covered is for the **previous** day (in this case, 8th of October 2025). ## Data retention period Contentful sends daily audit log files to the customer's configured storage location (e.g., S3 bucket or Azure Blob storage). This ensures that customers always have access to a daily record of audit logs in their own storage environment. In their own storage, customers have full control over how long they want to retain the data. If a customer needs to recover logs due to an issue, Contentful can re-send audit log files for actions that occurred within the past 30 days. ## Static IP addresses for audit logs Contentful uses static IP addresses to deliver audit logs, ensuring consistent and secure communication with your systems. You can use these IPs to configure allowlists or firewall rules for uninterrupted log delivery. If your organization requires IP allowlisting, you can configure your firewall or network settings to include the following static IP addresses used by Contentful for audit log delivery. The addresses vary by data residency region. **Default data residency Static IP addresses** ```typescript 100.29.211.234 98.90.149.146 44.217.33.9 3.217.146.187 44.210.188.180 34.231.49.171 3.93.41.89 44.198.98.111 100.25.104.227 ``` **EU data residency Static IP addresses** For organizations with EU data residency, audit logs are delivered from the following IP addresses: ```typescript 54.74.39.15 52.48.136.149 52.212.106.22 54.73.106.64 34.248.166.79 54.76.222.59 18.203.70.57 52.212.190.182 54.155.36.255 ``` ## Event details Audit event logs adhere to the [OCSF](https://github.com/ocsf) standard. Currently all logs are logged under the [Application Activity](https://schema.ocsf.io/1.3.0/categories/application?extensions=) category and more specifically the [Web Resource Activity](https://schema.ocsf.io/1.3.0/classes/web_resources_activity?extensions=) sub-category. This enables seamless integrations and will be the stable schema from now on, meaning these logs are safe to use in integrations. An example of an audit log when an entry is updated can be found below. ```typescript { "activity_name": "Update", "activity_id": 3, "category_uid": "6", "class_uid": "6001", "type_uid": "600101", "time": "yyyy-MM-dd hh:mm:ss.SSS", "actor": { "type": "user", "id": "" }, "enrichments": [ { "name": "http_request.url.path", "type": "Space", "value": "/spaces//environments//entries//published", "data": { "id": "" } }, { "name": "redacted_token", "type": "RedactedToken", "value": "abcd1234***REDACTED***wxyz5678", "data": { "token": "abcd1234***REDACTED***wxyz5678" } } ], "severity_id": 0, "http_request": { "http_method": "PUT", "referrer": "https://app.contentful.com/", "url": { "path": "/spaces//environments//entries//published" } }, "http_response": { "code": 200 }, "web_resources": [{ "type": "Entry", "uid": "entry_id" }], "metadata": { "version": "1.3.0", "uid": "" } }, ``` ### How to read an audit log Since audit logs abide by the OCSF standards some common parameters will always be the same. However, some properties have specific nuances due to being generated from the Contentful platform. The following guide will explain what each piece of the audit logs means and how to read it. #### Activity The properties prefixed with activity describe the type of event that occurred, and whether a resource (e.g. a space, environment, or locales) was updated, created, or deleted. Below is a table mapping the IDs to their names as well as their descriptions. | **Activity Id** | **Activity Name** | **Description** | | | | | --------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------- | - | - | - | | `0` | Unknown | The event activity is unknown | | | | | `1` | Create | One or more resources were created. | | | | | `2` | Read | One or more resources were read / viewed. | | | | | `3` | Update | One or more resources were updated. | | | | | `4` | Delete | One or more resources were deleted. | | | | | `5` | Search | A search was performed on one or more resources. | | | | | `6` | Import | One or more resources were imported into an Application. | | | | | `7` | Export | One or more resources were exported from an Application. | | | | | `8` | Share | One or more resources were shared. | | | | | `99` | Other | The event activity is not mapped. See the `activity_name` attribute, which contains a data source specific value. | | | | #### Category The category properties refer to the OCSF categories and subcategories under which a specific log falls. As stated earlier at this moment all audit logs fall under the [Application Activity](https://schema.ocsf.io/1.3.0/categories/application?extensions=) category and more specifically the [Web Resource Activity](https://schema.ocsf.io/1.3.0/classes/web_resources_activity?extensions=) sub-category this may expand in the future but for now integrations can be built around this type of log specifically. Below is a description for each property that is relevant to the category in this log. | **Property** | **Description** | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `category_uid` | The category unique identifier of the event.`6` - Application Activity Application Activity events report detailed information about the behavior of applications and service | | `class_uid` | The unique identifier of a class. A class describes the attributes available in an event.`6001` - Web Resources Activity Web Resources Activity events describe actions executed on a set of Web Resources. | | `type_uid` | The event/finding type ID. It identifies the event's semantics and structure. The value is calculated by the logging system as: `class_uid * 100 + activity_id`.- `600100` - Web Resources Activity: Unknown - `600101` - Web Resources Activity: Create One or more resources were created. - `600102` - Web Resources Activity: Read One or more resources were read / viewed. - `600103` - Web Resources Activity: Update One or more resources were updated. - `600104` - Web Resources Activity: Delete One or more resources were deleted. - `600105` - Web Resources Activity: Search A search was performed on one or more resources. - `600106` - Web Resources Activity: Import One or more resources were imported into an Application. - `600107` - Web Resources Activity: Export One or more resources were exported from an Application. - `600108` - Web Resources Activity: Share One or more resources were shared. - `600199` - Web Resources Activity: Other | #### Actor details The actor object provides metadata about the entity that performed the action captured in the audit log event. This can be either a user or an app. The structure follows the [Open Cybersecurity Schema Framework (OCSF)](https://github.com/ocsf/ocsf-docs/blob/main/overview/understanding-ocsf.md) for [actor](https://schema.ocsf.io/1.3.0/objects/actor) and [user](https://schema.ocsf.io/1.3.0/objects/user) objects. Included fields: * `user.email_addr`: The user's email address. Only present if actor type is "User". * `user.full_name`: The user's full name. Only present if actor type is "User". * `user.type`: Type of actor ("User", "App"). * `user.type_id`: Numeric ID representing the actor type. This follows the OCSF standard. * `user.uid`: Unique identifier of the actor. **Note**: `actor.type` and `actor.id` are top-level fields currently present in the actor object. They are being deprecated in favor of the nested user structure, which aligns with the Open Cybersecurity Schema Framework (OCSF). Please migrate to using `user.type` and `user.uid`. When a request is authenticated with a bearer token (for example, a [personal access token](/references/authentication/#getting-a-personal-access-token)), the audit log may also include a `redacted_token` enrichment. Use this value to correlate the event with a specific token without exposing the full secret. See [Redacted token enrichment](#redacted-token-enrichment) below. Example: ```typescript "actor": { "type": "User", // deprecated, use user.type "id": "2EHL4afAmn1k10yd6dJxcl", // deprecated, use user.uid "user": { "email_addr": "jane.smith@company.com", "full_name": "Jane Smith", "type": "User", "type_id": 1, "uid": "2EHL4afAmn1k10yd6dJxcl" } } ``` #### Severity As quoted in the OCSF documentation the `severity_id` is "The normalized severity is a measurement of the effort and expense required to manage and resolve an event or incident. Smaller numerical values represent lower impact events, and larger numerical values represent higher impact events." Below is a table mapping each ID to its description. | **Severity ID** | **Description** | | --------------- | ------------------------------------------------------------------------------------------------------------------------------ | | `0` | **Unknown** The event/finding severity is unknown. | | `1` | **Informational** Informational message. No action required. | | `2` | **Low** The user decides if action is needed. | | `3` | **Medium** Action is required but the situation is not serious at this time. | | `4` | **High** Action is required immediately. | | `5` | **Critical** Action is required immediately and the scope is broad. | | `6` | **Fatal** An error occurred but it is too late to take remedial action. | | `99` | **Other** The event/finding severity is not mapped. See the `severity` attribute, which contains a data source specific value. | > **Info** > > At this stage all logs are marked as `0` severity as we look to gather feedback and overtime identify the estimated severity of each request. #### HTTP Request The `http_request` object describes the original HTTP request that resulted in the log, the below table provides further details on what each property means. | **Property** | **Description** | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `http_method` | The type of [HTTP Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) used in the request. At this time GET requests aren't supported. During the current Beta the focus is only on requests that alter state on the Contentful platform. | | `referer` | The [referer](https://en.wikipedia.org/wiki/HTTP_referer) identifies which url the request came from. | | `url` | An object containing details about the url requested in the log. | | `url.path` | The full path that was called in the request. | #### HTTP Response This http\_response object contains the code referring to the [HTTP Response code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) that the query resulted allowing for it to be established if the request was successful or not. #### Enrichments The enrichments property provides an array of objects that enrich other properties in the logs. More details can be found in the [OCSF docs](https://schema.ocsf.io/1.3.0/objects/enrichment?extensions=). Given the example log above each property would mean the following: | **Property** | **Meaning** | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `"name": "http_request.url.path"` | This means that the `path` property from inside the `url` property which is inside `http_request` property is being enriched with additional data. | | `"type": "Space"` | This means that the enrichment will be providing some information about a space. The types will refer to entity names in the Contentful API documentation. | | "value": "/spaces/\/environments/\ /entries/\/published" | The original value without any enrichment. | | `"data":` | The object containing the additional data that will enrich the original value. | | `{'{ "space_id": "" }'}` | In this scenario the space\_id is provided meaning that there is no need to parse the URL to retrieve this value. | #### Redacted token enrichment Some audit events include a pipeline enrichment that identifies which [bearer token](https://www.contentful.com/developers/docs/references/content-management-api/access-tokens/) authenticated the request. This helps security and compliance teams trace API activity to a specific token (for example, a personal access token or CMA token) without storing the full secret in the audit log. The enrichment is present only when the request included a bearer token. If no token was used, the `redacted_token` enrichment is omitted. | **Property** | **Meaning** | | -------------------------- | ------------------------------------------------------------------------------------------------------- | | `"name": "redacted_token"` | Identifies this enrichment as the partially redacted bearer token used on the request. | | `"type": "RedactedToken"` | Contentful-specific enrichment type for token correlation. | | `"value"` | The redacted token string (same value as `data.token`). | | `"data.token"` | The redacted token string. Match this against your token inventory using the visible prefix and suffix. | The redacted value shows the first four and last four characters of the token secret, with the middle replaced by `***REDACTED***`. Token type prefixes such as `cfpat-` and `cfw-` are removed before redaction. Example: ```typescript { "name": "redacted_token", "type": "RedactedToken", "value": "abcd1234***REDACTED***wxyz5678", "data": { "token": "abcd1234***REDACTED***wxyz5678" } } ``` > **Info** > > The full token secret is never written to audit logs. Use the redacted form only for correlation and investigation. #### Web Resources The web\_resources property contains an array of entities that were affected by this request these can be environments, locales, content types or entries, etc. The properties of the objects contained in the array are as described below: | **Property** | **Meaning** | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `type` | This will be the name of entity the entity type of the affected resource represented in the Contentful API documentation for example an `Entry` or a `ContentType` | | `uid` | The id of the affected resource for example the id of the entry or the name of the content type. | #### Metadata The `metadata` property contains miscellaneous data that doesn't fit well in the rest of the log but may still be useful. At this moment only two properties can be found in this object and the below table describes them. | **Property** | **Meaning** | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `version` | The version of the OCSF schema this log adheres to. | | `uid` | This is a unique Contentful request ID that can be provided to Contentful support when investigating a log entry and would be useful to the Support person in tracing more information internally about what happened. | ## Requirements **AWS or Azure account**: An active AWS or Azure account is necessary. #### Stopping the audit logs delivery To stop the delivery of the audit logs, please contact our [support](https://www.contentful.com/support/) ## Audit logs set up To set up your infrastructure to receive Audit Logs, you will need to make some configuration changes and share some information with Contentful. ### Security of your configuration and credentials Credentials provided for audit log delivery (such as AWS IAM Role ARN, Azure SAS tokens, or Google Cloud service account keys) are encrypted both in transit and at rest. Access to decrypt and use these credentials is strictly scoped to systems responsible for delivering audit logs, following Contentful's internal security controls and standard access management practices. These controls align with industry expectations for cloud-native infrastructure and enterprise-grade data handling. ### Audit logs Google Cloud Storage configuration To set up streaming to Google Cloud storage, create a service account in Google Cloud with the appropriate credentials and permissions, then configure audit log streaming in Contentful using the service account's credentials for authentication. ![Audit logs Google Cloud Storage](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/ca44febdf537c49f25839e7735d3a07b26b06ef953846563809f26e8554ccaed/docs/assets/images/audit-logs-storage-gcp.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260929T234804Z&X-Amz-Expires=604800&X-Amz-Signature=f67e5839df8e07e75235a026d64350d2d0beb685767f92419325115c0541719e&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) #### Prerequisites * A Google Cloud project with permissions to create and manage service accounts and storage buckets. * Google Cloud Storage API enabled in your project. #### Step 1: Create a GCS bucket You can create a new GCS bucket to hold the logs, or you can use an existing bucket. Be sure to note the name of the bucket as you will need it later. To learn how to create a GCS bucket, refer to Google's guide on [creating a bucket](https://cloud.google.com/storage/docs/quickstart-console#create_a_bucket). #### Step 2: Create a service account Google Cloud Storage (GCS) uses [service accounts](https://cloud.google.com/iam/docs/service-account-overview) for third-party application authentication and role-based access to Google Cloud resources. To create a new service account, follow the instructions in the [Google Cloud documentation](https://cloud.google.com/iam/docs/creating-managing-service-accounts#creating). #### Step 3: Create a JSON key Create a JSON key for the service account, and store the key securely. See [Creating and managing service account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating) in the Google Cloud documentation. #### Step 4: Assign the Storage Object Creator role Give the service account the Storage Object Creator role for the bucket. See [Using Cloud IAM permissions](https://cloud.google.com/storage/docs/access-control/using-iam-permissions#bucket-add) in the Google Cloud documentation. 1. Go to **Cloud Storage > Buckets** and select the bucket you created in Step 1. 2. Navigate to the "Permissions" tab, click **Grant access**. 3. In the "Add principals" section, add the service account's email (e.g., `contentful-audit-logs@your-project.iam.gserviceaccount.com`). 4. Under "Assign roles," select the role: **Cloud Storage > Storage Object User**. #### Step 5: Configure Google Cloud Storage in Contentful NOTE: Only organization owners and admins can configure storage settings. 1. In Contentful, go to "Organization settings > Audit logs". 2. Select Google Cloud as your storage provider. 3. Fill out the form with the following: * Google Cloud bucket name: name of the bucket you created. * GCP email: the service account's email address. * GCP private key: the private key from your downloaded JSON key file. 4. Click **Test connection** to verify access. Contentful will upload a test file to your bucket. 5. If test is successful, click **Save** to complete the configuration. If the test is unsuccessful, check if: * The service account has the **Storage Object User** role. * The bucket name is correct. * The private key is valid and corresponds to the correct service account. ### Audit logs AWS Configuration As part of enabling audit log shipping to your AWS S3 bucket, you need to create an AWS IAM role that Contentful can assume. This will allow Contentful to securely transfer audit logs to your AWS S3 bucket without the need to store any credentials. #### Security of IAM role assumption Contentful uses AWS IAM role assumption to securely deliver audit logs to your specified S3 bucket. This approach follows AWS's recommended best practices for granting third-party access to your resources. With IAM role assumption: * No credentials are shared: Contentful does not require or store your AWS credentials. Instead, a secure trust relationship is established through the IAM role. * Explicit permissions: You maintain full control by explicitly defining which actions Contentful can perform (e.g., `s3:PutObject`) and on which resources (e.g., specific S3 buckets). * Control over the trust policy: The trust policy for the IAM role allows access only to Contentful's AWS account and requires an external ID for added security. * Industry standard: Role assumption is widely adopted by leading SaaS platforms, ensuring a secure, scalable, and traceable approach. For more details, refer to the [AWS IAM documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html). #### Prerequisites * An AWS account with permissions to create IAM roles and edit S3 bucket policies. * Contentful's AWS account IDs: * For US customers: `606137763417` * For [EU data residency](/platform/eu-data-residency) customers: `101997328120` #### Step 1: Create an S3 Bucket 1. Log in to your AWS Management Console. 2. Navigate to S3, click **Create bucket**. 3. Enter a unique bucket name and select the region where you want the bucket to reside. Note: you will need to enter this name later. 4. Configure options as required (e.g., versioning, logging, tags, object lock). 5. Review and create the bucket. #### Step 2: Create a New IAM Policy 1. Log in to your AWS Management Console. 2. Navigate to IAM -> Policies -> Create policy. 3. Select the JSON tab and paste the following policy, replacing `` with the name of your S3 bucket (from Step 1). Make sure to keep the `/*` at the end: ```typescript { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::/*" } ] } ``` 4. Click **Next**, give it a meaningful name and description, and then click **Create**. #### Step 3: Create a New IAM Role for Cross-Account Access 1. In the IAM dashboard, go to Roles -> Create role. 2. Select **AWS Account** under the "Trusted entity type" section, then in the section below select Another AWS account and enter Contentful's AWS account ID: * For US customers: `606137763417` * For [EU data residency](/platform/eu-data-residency) customers: `101997328120` 3. Enable the option **Require external ID** and insert your Contentful organization ID. The primary function of the external ID is to address and prevent [the confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html). You can find the organization ID in the Contentful web app. 4. Click **Next**, skip attaching permissions policies now (we will attach the policy created in Step 2). 5. Review, name the role, and then create it. #### Step 4: Attach the Policy to the IAM Role 1. Go to the newly created role in IAM -> Roles. 2. Under "Permissions" in the **Add permissions** dropdown, click **Attach policies**. 3. Find the policy you created in Step 2, select it, and then click **Add permission**. #### Step 5: Configure Your S3 Bucket Policy 1. Go to S3, find your bucket from Step 1, and then click **Permissions**. 2. Edit the **Bucket policy** and add the following statement, replacing `` with the ARN of the IAM role you created in Step 3 and `` with the name of your S3 bucket. Make sure to keep the `/*` at the end of the bucket ARN: ```typescript { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::/*" } ] } ``` 3. Save the changes. #### Step 6: Configure AWS S3 storage in the Contentful web application Note: Only organization owners and organization admins can add and edit the storage details in Contentful. 1. In Contentful, navigate to **Organization settings** -> **Audit logs**. 2. Select **Amazon AWS** as a **Storage provider** option and fill in the form with the following details: * **S3 bucket name**: The name of the S3 bucket you've created for storing audit logs. * **ARN of IAM Role**: The Amazon Resource Name (ARN) of the IAM role that Contentful will assume to send logs to your bucket. * **AWS Region**: The AWS region where your S3 bucket is located. 3. Click **Test connection** to verify that the connection to your AWS S3 bucket is working correctly. During this test, Contentful sends a file to ensure the configuration is valid. If the test succeeds, you'll see a confirmation message. 4. If the connection test is successful, click **Save** to finalize the configuration. Note: If the test fails, double-check that your bucket permissions, IAM Role, and policy configurations match the requirements outlined earlier in this guide. By following these steps, you've securely enabled Contentful to ship logs to your AWS S3 bucket. Contentful will use AWS STS to assume the role you've created, ensuring a secure and efficient transfer of audit log data. ![Audit logs configuration](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/4b87bfc9b786c4eb4713893d8e501894139c9f0a668e98093c112a0e301e126f/docs/assets/images/audit-logs-configuration.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260929T234804Z&X-Amz-Expires=604800&X-Amz-Signature=5a4f7d5c76af19069f80698d00b22897c4f04da0a51e26eb89d5159a468518c1&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) ### Audit logs Azure configuration As part of enabling audit log shipping to your Azure Blob Storage container, you need to create a Shared Access Signature (SAS) user that Contentful can use. This will allow Contentful to securely transfer audit logs directly to your Azure Storage Account container. This guide will help you create a Shared Access Signature (SAS) user specifically for Contentful. A shared access signature (SAS) provides secure delegated access to resources in your storage account. With a SAS, you have granular control over how a client can access your data. For example: * What resources the client may access * What permissions they have to those resources * How long the SAS is valid #### Prerequisites An Azure account with access to create a Blob Store and a SAS Token. #### Step 1: Create an Azure Storage Account 1. Log in to your Azure Portal. 2. Navigate to **Storage Accounts** -> **Create** 3. Select the **Subscription** under which to create the Storage Account. 4. Select or Create the Resource Group for the Storage Account. 5. Enter a unique storage account name and select the region where you want the account to reside. Note this name, you will need it later. 6. Configure options as required (e.g., performance, redundancy, etc). 7. Click **Review + create** 8. On the Review + create page check that everything correct and if you're satisfied click **Create** to create the storage account. #### Step 2: Create a Container 1. Log in to your Azure Portal. 2. Navigate to **Storage Accounts** and click the one you created in Step 1 to open it. 3. On the left sidebar, under **Data storage**, click **Containers**. 4. In the top toolbar click the **+ Container** button to create a new container. 5. Enter a unique container name. > **Info** > > Note this name, you will need it later. 6. Configure options as required (e.g., encryption scope, versioning, etc). 7. Review and click **Create** to create the container. #### Step 3: Create the SAS Token 1. Log in to your Azure Portal. 2. Navigate to **Storage Accounts** and click the one you created in Step 1 to open it. 3. On the left sidebar, under **Data storage**, click **Containers**. 4. Click the name of the container you create in the steps above. 5. On the left sidebar, under **Settings**, click **Shared access tokens** 6. Select the **Permissions** dropdown, deselect **Read**, then select **Create** and **Write**. 7. Set an expiry date that complies with your secret rotation policy. 8. Click **Generate SAS token and URL** 9. Copy the value of the **Blob SAS URL** field that's displayed. You will use this URL in the next steps. #### Step 4: Configure Microsoft Azure storage in the Contentful web application **Note**: Only organization owners and organization admins can add and edit the storage details in Contentful. 1. In Contentful, navigate to **Organization settings** -> **Audit logs**. 2. Select **Microsoft Azure** as a **Storage provider** option. 3. Paste the Blob SAS URL from the previous step into **Blob SAS URL** field. 4. Click **Test the connection** to verify that the connection to your Microsoft Azure storage is working correctly. During this test, Contentful sends a file to ensure the configuration is valid. If the test succeeds, you'll see a confirmation message. 5. If the connection test is successful, click **Save** to finalize the configuration. ![Audit logs Storage Option](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/9f5c44502e6721a653597b5deb453466627f53941ae616f9dd01c59c9641c1bf/docs/assets/images/audit-logs-storage-option.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260929T234804Z&X-Amz-Expires=604800&X-Amz-Signature=8882efe32095269299c9176c5dab16292f5bd090c8551b4bc7e2d9ecae243e4e&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) ### Enrichments in audit logs The enrichments section of the audit event (defined by OCSF standard) is a flexible way to add various additional context data and information that can enhance the audit event. It allows us to add more information that does not fit in the prescribed OCSF event structure (as example, see the AI actions enrichment below). An audit event can have many enrichments (i.e. the enrichments property itself is an array of objects). Generally, the enrichment objects you will find in our events will each have a `type`, `type_version`, and `data`. We recommend using the `type` value as a hint for processing the `data` section (as the shape of `data` is not fixed by OCSF and will vary by type). Additionally, the `type_version` can be used as well, but we recommend only matching the major version part of it and not the full version (non-major changes should be backwards compatible). #### AI Actions enrichment Provides traceability for AI-generated content changes by capturing metadata about each AI Action invocation, including model used and affected entries. This helps with compliance, observability, and accountability when adopting AI in content operations. Included fields: * `invocationId`: Unique ID for the AI Action execution. * `createdBy`: User who initiated the AI Action (in Link object format). * `entryAffected`: Entry ID, field ID, source locale. * `aiActionId`: The ID and version of the AI Action used. * `modelName`: Model used for AI generation (e.g. `claude-3-sonnet`). * `modelProvider`: Provider for the model (e.g. `aws_bedrock`). * `modelTemperature`: Temperature value used for generation. * `outputFormat`: Format of the output content (e.g. Markdown). Example: ```typescript { "type": "AiActionEnrichment", "type_version": "1.0.0", "version": "1.0", "data": [ { "invocationId": "5lFBfOSRXf98MZYF8WtPx0", "createdBy": { "sys": { "type": "Link", "linkType": "User", "id": "6PT2TwX4KsLhYhbH0FeMGg" } }, "entryAffected": { "entityId": "58joNskXjB4KTfBBOclLXB", "entityType": "Entry", "fieldId": "body", "sourceLocale": "en-US" }, "aiActionId": { "sys": { "type": "Link", "linkType": "AiAction", "id": "4LiCwmt1V7ZJKFlzRirMg2", "version": 2 } }, "modelName": "anthropic.claude-3-sonnet", "modelTemperature": 0.1, "modelProvider": "aws_bedrock", "outputFormat": "Markdown" } ] } ``` #### Bulk Actions enrichment Bulk actions (e.g. publish/unpublish) capture metadata showing the action taken and which entries or assets were affected. This helps security teams and developers trace content workflows at scale and analyze the impact of changes across multiple entities. Included fields: * `action`: one of `publish`, `unpublish` and `validate`. * `entities`: array of impacted entries or assets, each as a sys Link object. Example: ```typescript { "type": "BulkActionEnrichment", "type_version": "1.0.0", "version": "1.0.0", "data": [ { "action": "publish", "entities": [ { "sys": { "type": "Link", "linkType": "Entry", "id": "", "version": 5 } }, { "sys": { "type": "Link", "linkType": "Asset", "id": "", "version": 23 } } ] } ] } ``` > Learn how to set up Audit logs which allow customers to track and view all the changes made in their organization.