ChannelsGoogle CloudPermissions

Set up Google Cloud Storage for channel deliveries

The service account and IAM role a Google Cloud Storage destination needs, why delete permission is required, and what the endpoint's Test connection actually checks.
Updated September 3, 2026

A channel's Google Cloud Storage destination delivers files into a bucket in your own Google Cloud project. It authenticates as a service account whose JSON key you upload when creating the endpoint - this guide walks through creating that account with the right (and only the right) permissions.

The role your service account needs

Grant the service account roles/storage.objectUser on the bucket - or a custom role containing exactly:

  • storage.objects.create
  • storage.objects.delete

Delete looks surprising for a destination that only ever writes, but it is load-bearing: delivering a file under a name that already exists is an overwrite, and overwriting an object in Cloud Storage requires storage.objects.delete. Channels overwrite by design - a corrected invoice or re-issued document arrives under the same filename - so a service account with only roles/storage.objectCreator works for the first delivery of each name and then fails on every repeat.

Grant the role on the bucket, not the project, so the key you hand to DocEvent can touch nothing else:

gcloud storage buckets add-iam-policy-binding gs://<bucket> \
  --member="serviceAccount:<name>@<project>.iam.gserviceaccount.com" \
  --role="roles/storage.objectUser"

Create the account and key

gcloud iam service-accounts create docevent-delivery \
  --display-name="DocEvent channel delivery"

gcloud iam service-accounts keys create docevent-delivery.json \
  --iam-account=docevent-delivery@<project>.iam.gserviceaccount.com

Then, in the DocEvent console, open Channels, add (or edit) a Google Cloud Storage destination, enter the bucket and optional folder, and upload docevent-delivery.json as the key file. The key is stored encrypted and is write-only - the console never shows it back, and editing the endpoint later keeps the stored key unless you upload a new one.

What Test connection checks

The endpoint's Test connection button verifies both permissions without creating or deleting anything in your bucket:

  1. It starts a resumable upload session under a random probe name and abandons it - proving the bucket exists, the key works, and storage.objects.create is held. An abandoned session stores nothing and Google discards it automatically.
  2. It attempts to delete that same random, nonexistent name. A not found answer proves Google evaluated storage.objects.delete and the account holds it; a permission denied answer means the delete permission is missing, and the Test fails telling you so.

So a failing Test that mentions storage.objects.delete means the account can write but could not overwrite - grant roles/storage.objectUser (or add storage.objects.delete to your custom role) and test again.

Notes

  • Files are delivered under the endpoint's folder prefix; each file becomes visible in the bucket only once it is fully written - consumers never see partial content.
  • Bucket names, folders and filenames pass through unchanged; Cloud Storage object names are limited to 1024 bytes of UTF-8.
  • If you also receive files from a bucket with the Google Cloud Storage source, that endpoint has its own, different permission needs - configure its service account separately rather than sharing one broad key.

Still stuck? Contact support.