Assets
A resource is an uploaded binary asset (today, an image) scoped to a single provider. Resources are the storage primitive behind things like branding logos and other provider-owned imagery. They decouple the stored file from the metadata that references it.
Where resources live
Each resource belongs to exactly one provider. The provider is the authorization anchor: anyone with update on the
provider can upload, list, replace, patch, or delete its resources; anyone with read on the provider can stream a
Resource's bytes.
Fields
| Field | Description | Example |
|---|---|---|
id | Unique ID assigned at upload time | 5d2a91f4-8b6c-4e3a-9f12-7c8d4e5b6a01 |
providerId | Parent provider — set on upload, immutable | 8b14d4f9-3a52-4b91-8e7c-d3e44b5c1f2a |
name | Optional display name (up to 255 chars) | acme-logo-light |
contentType | MIME type of the uploaded bytes | image/jpeg |
size | Size of the uploaded bytes, in bytes | 48213 |
ownerIdentityId | Identity that owns the resource | c0ffee00-1111-2222-3333-444455556666 |
createdBy, createdAt, updatedAt, deletedAt, deletedBy | Standard lifecycle fields |
The actual file bytes are held in internal object storage under a provider-scoped key. Clients never handle the storage key directly. They read bytes through the Customer Connect API.
Accepted content types
Only image content types are accepted at upload time:
image/pngimage/gifimage/jpegimage/webpimage/svg+xml
Any other Content-Type is rejected with 415 Unsupported Media Type.
Size limits
Uploads are capped at 8 MB per file.
Two ways to read a resource
1. Metadata
GET /providers/{providerId}/resources/{id} returns the resource's metadata.
2. Extension-based streaming
GET /providers/{providerId}/resources/{id}.{ext} streams the bytes through Customer Connect when the {ext} matches
the stored contentType and the request's Accept header allows that type. Supported extensions: png, gif, jpg,
jpeg, webp, svg.
- If the extension doesn't map to the stored type, the response is
404 Not Found. - If the
Acceptheader doesn't allow the stored type, the response is406 Not Acceptable.
This endpoint is authorized with read (not update) on the provider, so it's safe to expose to image consumers that
only need view access.
Upload
Uploads use multipart/form-data with two parts:
file: The binary content (required).name: A display name (optional).
The providerId comes from the URL path.
Replace vs. patch
PUT /providers/{providerId}/resources/{id}replaces the file and name. It re-uploads the bytes to the same storage key; the resource'sidandproviderIdare stable across replacements.PATCH /providers/{providerId}/resources/{id}updates metadata only (currently justname). Send{"name": null}to clear it.
Delete
DELETE /providers/{providerId}/resources/{id} soft-deletes the metadata row and hard-deletes the stored object. The
row remains in the database (with deletedAt set) for audit purposes, but the bytes are gone.
Authorization summary
| Operation | Auth on provider |
|---|---|
| List, get metadata, upload, replace, patch, delete | update |
Stream bytes via /{id}.{ext} | read |
Resources are not independently permissioned. All decisions route through the parent provider.