> For the complete documentation index, see [llms.txt](https://docs.kernel.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kernel.ai/integrations/s3-integration.md).

# S3 file exchange

<details>

<summary><strong>Required setup and information to send Kernel</strong></summary>

Complete these three steps before Kernel configures the connection.

**1. Get these environment-specific values from Kernel**

* Kernel customer integrations IAM role ARN
* Tenant-specific External ID
* IAM trust policy template containing both values

**2. Set up these resources in your AWS account**

* One customer-owned S3 input bucket containing one complete CSV at a fixed object key
* One customer-owned S3 output destination, either in the same bucket or a different bucket
* One IAM role for both endpoints, or separate input and output roles
* A trust relationship on each role that uses the Kernel role ARN and External ID
* `s3:ListBucket` and `s3:GetObject` access for the input location
* `s3:PutObject` access for the output location
* KMS permissions and key policy access when either location uses a customer-managed KMS key
* A representative input CSV uploaded at the exact object key Kernel will read

**3. Send Kernel this completed configuration**

```
Environment: production | sandbox

Input IAM role ARN:
Input bucket name:
Input AWS region:
Exact input object key, including filename:
Input prefix, if used:
Input KMS key ARN: none | <key ARN>
Source account ID column header:
CSV header to Kernel field mapping:

Output IAM role ARN: same as input | <role ARN>
Output bucket name:
Output AWS region:
Output prefix or path:
Output base filename:
Delivery mode: overwrite | timestamped
Output KMS key ARN: none | <key ARN>
Output join key:
Output fields to include:

Representative input CSV uploaded at the exact key: yes
```

Do not send AWS access keys, secret access keys, session tokens, or KMS key material.

</details>

## What it is

The S3 file exchange lets your team send account data to Kernel and receive enriched results as CSV files. The files remain in Amazon S3 buckets that your team owns, and no CRM installation is required.

The connection has two logical endpoints:

* **Input:** one bucket and one exact CSV object that Kernel reads.
* **Output:** one bucket and one configured location where Kernel writes a CSV object.

The input and output endpoints can use the same physical bucket or different buckets. They can also use one IAM role for both directions or separate read and write roles.

{% hint style="info" %}
Each pull and export is started manually in Kernel. Use S3 for bulk, complete-file exchanges. Use the [Kernel API](/developer/api-getting-started.md) for record-level or near-real-time workflows.
{% endhint %}

## At a glance

* Customer-hosted S3 buckets only.
* Cross-account IAM role assumption with a Kernel-provided External ID.
* No AWS access keys or other long-lived credentials are shared with Kernel.
* Kernel reads one exact input object on every pull.
* Rows are created or updated using your configured source account ID.
* A row missing from a later file remains unchanged.
* Every export writes one complete CSV object.
* Output can overwrite one stable object or create a timestamped object for each export.

## How it works

```mermaid
sequenceDiagram
    autonumber
    participant You as Your team
    participant Input as Input S3 object
    participant K as Kernel
    participant Output as Output S3 location

    You->>Input: Write complete account CSV
    You->>K: Click Pull file now
    K->>Input: Read the exact configured object
    Note over K: Resolve identity, hierarchy,<br/>cleaning, and enrichment
    You->>K: Click Export to S3
    K->>Output: Write one complete results CSV
    Output->>You: Ingest using your source account ID
```

## Information exchange

### Kernel provides

Kernel provides these values separately for each environment:

* The Kernel customer integrations IAM role ARN.
* A tenant-specific External ID.
* A trust policy template containing both values.

Add the Kernel role ARN as the trusted AWS principal. The External ID must match exactly.

### Your team provides

For the input endpoint:

* Environment: production or sandbox.
* Input IAM role ARN.
* Input bucket name and AWS region.
* Exact input object key, including its prefixes and `.csv` filename.
* Input prefix, when the setup screen is used to browse for the object.
* Customer-managed KMS key ARN, when the object uses SSE-KMS.
* Source account ID column header.
* Mapping from your CSV headers to Kernel fields.
* A representative CSV at the exact input object key.

For the output endpoint:

* Output IAM role ARN, or confirmation that the input role is also used for output.
* Output bucket name and AWS region. The bucket may be the same as the input bucket.
* Output prefix or path.
* Base filename.
* Delivery mode: **Overwrite** or **Timestamped**.
* Customer-managed KMS key ARN, when the destination uses SSE-KMS.
* Output join key and selected output fields.

{% hint style="warning" %}
Do not send AWS access keys, secret access keys, session tokens, or KMS key material.
{% endhint %}

## IAM setup

### Role trust policy

Use the trust policy generated in Kernel. It allows the Kernel customer integrations role to assume your role using the tenant-specific External ID.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<KERNEL_CUSTOMER_INTEGRATIONS_ROLE_ARN>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<KERNEL_EXTERNAL_ID>"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<KERNEL_CUSTOMER_INTEGRATIONS_ROLE_ARN>"
      },
      "Action": "sts:TagSession"
    }
  ]
}
```

### Input role permissions

The input role must be able to list the configured prefix during setup and read the exact configured object.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListInputPrefix",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::<INPUT_BUCKET>",
      "Condition": {
        "StringLike": {
          "s3:prefix": [
            "<INPUT_PREFIX>",
            "<INPUT_PREFIX>/*"
          ]
        }
      }
    },
    {
      "Sid": "ReadExactInputObject",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::<INPUT_BUCKET>/<EXACT_INPUT_KEY>"
    }
  ]
}
```

When the input object uses a customer-managed KMS key, the input role also needs `kms:Decrypt` on that key. The KMS key policy must allow the role.

If the input object is at the bucket root, omit the `s3:prefix` condition from the list statement.

### Output role permissions

The output role must be able to write beneath the configured output prefix.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "WriteOutputObjects",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<OUTPUT_BUCKET>/<OUTPUT_PREFIX>/*"
    }
  ]
}
```

The output role does not need `s3:ListBucket`, `s3:GetObject`, or `s3:DeleteObject`.

When the output uses a customer-managed KMS key, the output role also needs `kms:GenerateDataKey` on that key. The KMS key policy must allow the role.

If the output is written at the bucket root, scope `s3:PutObject` to `arn:aws:s3:::<OUTPUT_BUCKET>/*`.

If one role is used for both directions, combine the input and output permission statements. Existing bucket policies, service control policies, permission boundaries, and KMS key policies must not deny these operations.

## Input object

Kernel reads exactly one configured object:

```
s3://<INPUT_BUCKET>/<EXACT_INPUT_KEY>
```

For example:

```
s3://acme-data-exchange/kernel/input/accounts.csv
```

Write each new dataset to the same object key. Start **Pull file now** only after the upload has completed. You may enable S3 versioning for your own audit and recovery requirements, but Kernel reads the current object version.

Kernel does not scan the bucket, combine files, select the newest file or partition, read a manifest, calculate a diff, or poll for changes.

## Input CSV contract

The input file must meet these requirements:

* UTF-8 encoded CSV with a `.csv` filename.
* One header row followed by one row per source account.
* Comma-delimited with standard double-quote escaping.
* Unique, non-empty headers that remain stable between pulls.
* One configured source account ID column.
* A non-empty, unique, stable source account ID on every row.
* Identifiers represented as strings so leading zeroes are preserved.
* ISO 8601 dates, preferably `YYYY-MM-DD` for date-only values.
* Empty cells for unavailable values.

Mapped column names must continue to exist under the same header. If the schema changes, refresh the available columns and correct renamed or removed mappings before pulling.

Kernel validates the complete file before applying the pull. An unreadable object, malformed CSV, missing mapped column, or invalid source account ID blocks the pull and leaves the previous successful state unchanged.

### Input fields

Your physical CSV header names are configurable. During setup, map each header to its logical Kernel field.

| Logical field            | Requirement                                                               |
| ------------------------ | ------------------------------------------------------------------------- |
| Source account ID        | Required and non-empty on every row. Must be unique and stable.           |
| Account name             | Required column. Provide a value wherever available.                      |
| Website                  | Required column. May be empty where unavailable.                          |
| Parent source account ID | Required column. Leave empty for top-level accounts or an unknown parent. |
| Owner ID                 | Required column. Leave empty where no owner is applicable.                |
| Last activity date       | Required column. Use ISO 8601 or leave empty.                             |
| Company legal name       | Recommended for identity resolution.                                      |
| Country and address      | Recommended for identity resolution and hierarchy decisions.              |
| LinkedIn company URL     | Recommended identity signal.                                              |
| Related domains          | Recommended identity signal.                                              |
| Alternative website      | Recommended identity signal.                                              |

Additional supported columns can be mapped in Kernel.

Example:

```csv
source_account_id,account_name,website,parent_source_account_id,owner_id,last_activity_date,legal_name,country,linkedin_url
A001,Acme Ltd,https://acme.com,,OWNER-17,2026-08-10,Acme Holdings Limited,GB,https://www.linkedin.com/company/acme
A002,Beta GmbH,https://beta.example,A001,OWNER-22,2026-08-09,Beta GmbH,DE,https://www.linkedin.com/company/beta
```

## Pull behavior

Each click of **Pull file now** performs one whole-file upsert:

* Kernel reads the exact configured object.
* The CSV and configured field mappings are validated.
* A new source account ID creates an account.
* An existing source account ID updates its mapped fields.
* An account absent from a later file remains unchanged.
* Row absence never deletes, deactivates, tags, or otherwise changes an account.
* Only one pull can run for the connection at a time.

The completed pull shows its object key, completion time, and counts for total, created, updated, unchanged, skipped, and failed rows.

## Output configuration

Configure the output endpoint separately from input:

* Output bucket and prefix.
* Base filename.
* Join key.
* Selected output fields.
* Delivery mode.

The configured join key is always included in the output so that you can join Kernel results back to your source data.

### Output data

Each export contains:

* One row for every account imported through this S3 connection.
* The configured source join key.
* The selected supported public account API fields.
* Selected cleaning fields and the current `cleaning_action`, when configured.

All supported public account API fields are selected by default. The join key appears first, followed by fields in the saved configuration order. Null values are written as empty cells.

Cleaning actions are informational data. Exporting them does not mutate your systems. Accepted or rejected operational review status is not included in the file exchange.

### Output delivery modes

**Overwrite** replaces one stable object on every successful export:

```
s3://<OUTPUT_BUCKET>/<OUTPUT_PREFIX>/<BASE_FILENAME>.csv
```

For example:

```
s3://acme-data-exchange/kernel/output/accounts.csv
```

**Timestamped** creates one new object on every successful export:

```
s3://<OUTPUT_BUCKET>/<OUTPUT_PREFIX>/<BASE_FILENAME>_<YYYYMMDDTHHmmssSSSZ>.csv
```

For example:

```
s3://acme-data-exchange/kernel/output/accounts_20260812T145530123Z.csv
```

The timestamp is UTC and includes milliseconds. Each export writes exactly one complete CSV object. An export is successful only after CSV generation and `PutObject` both complete.

## Connection verification

Kernel verifies input and output independently.

* **Input verification** assumes the input role and performs `GetObject` against the exact configured input key.
* **Output verification** assumes the output role and performs `PutObject` beneath the configured output prefix.

Output verification supports an intentionally write-only role and does not require list, read, or delete permissions.

The connection displays one of four states:

| State            | Meaning                                          |
| ---------------- | ------------------------------------------------ |
| **Disconnected** | Neither input nor output is verified and usable. |
| **Input only**   | Input is verified and usable; output is not.     |
| **Output only**  | Output is verified and usable; input is not.     |
| **Live**         | Both input and output are verified and usable.   |

Changing a role ARN, bucket, region, input key, output prefix, or KMS configuration requires the affected capability to be verified again.

## Operating cycle

1. Produce the new account dataset.
2. Write it to the exact configured input object key.
3. Confirm that the upload has completed.
4. In Kernel, click **Pull file now**.
5. Review the object key, status, and row counts.
6. Complete the required processing and review in Kernel.
7. Click **Export to S3**.
8. Review the output object key, status, row count, selected field count, and delivery mode.
9. Ingest the complete output file using your source account ID.

## File exchange boundaries

The S3 file exchange uses manual, complete-file operations. It does not use:

* Scheduled pulls or automatic polling.
* Automatic exports.
* Multiple input files or newest-partition discovery.
* Diffs, incremental files, manifests, or completion markers.
* Deletion or deactivation inferred from a missing row.
* Kernel-hosted exchange buckets.
* Accept or reject actions through S3.

Use the [Kernel API](/developer/api-getting-started.md) for event-driven integrations, record-level writes, or near-real-time retrieval.

## Troubleshooting

### AssumeRole fails

Check the trusted Kernel role ARN, External ID, `sts:AssumeRole`, `sts:TagSession`, permission boundary, and organization service control policies.

### Input access is denied

Check `s3:GetObject` on the exact object ARN, `s3:ListBucket` on the configured prefix, bucket policy denies, and `kms:Decrypt` when SSE-KMS is used.

### The object cannot be found

Check the bucket, region, exact key, filename case, and prefix. S3 object keys are case-sensitive.

### The CSV is rejected

Check UTF-8 encoding, the header row, delimiter, quote escaping, mapped columns, and source account IDs. Confirm that the upload completed before starting the pull.

### Output access is denied

Check `s3:PutObject` on the configured prefix, bucket policy denies, the selected output role, and `kms:GenerateDataKey` when SSE-KMS is used.

## Customer handoff checklist

Provide the following information to your Kernel contact.

### Input

* Environment: production or sandbox
* Input IAM role ARN
* Input bucket
* Input region
* Input prefix
* Exact input object key
* Customer-managed KMS key ARN, if applicable
* Source account ID header
* Confirmation that a representative sample is available at the exact key
* Field mapping owner
* Notes about date formats or custom fields

### Output

* Whether the input role is also used for output
* Output IAM role ARN, if separate
* Output bucket
* Output region
* Output prefix
* Base filename
* Delivery mode: Overwrite or Timestamped
* Customer-managed KMS key ARN, if applicable
* Output join key
* Required output fields
* Downstream ingestion owner
