Set up Google Cloud Storage for channel deliveries
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.createstorage.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:
- It starts a resumable upload session under a random probe name and
abandons it - proving the bucket exists, the key works, and
storage.objects.createis held. An abandoned session stores nothing and Google discards it automatically. - It attempts to delete that same random, nonexistent name. A not found
answer proves Google evaluated
storage.objects.deleteand 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.