Outcome
Register pending metadata for an asset before uploading its bytes.
Before you start
- Verify whoami and the pinned credential context, then inspect the exact discovered action before preparing input.
- Discover a granted Brand workspace. Pass its resourceType/workspace identifier separately from input; a copied fixture identifier grants no access.
- The declared permission is brand:write. The active credential, application scope, resource binding and runtime authority must all authorize the request.
- Review the exact mutation and recovery, including destructive scope, and execute only after the intended effect is authorized.
Discover the target
topolo whoami --json
topolo actions get app_topolo_brand.brand_assets.register --detail --json
topolo resources topolo-brand --json
topolo workspaces list topolo-brand --json
Request
POST /api/brand-assets
Resource context is the selected Brand workspace. CLI/SDK action input includes path identifiers; direct HTTP JSON bodies exclude path parameters. Read the reviewed plan for the exact request.
Input fields
| Field | Required | Meaning |
|---|---|---|
brandKitId | Yes | Brand kit identifier in the verified Brand workspace. Read brand_kits.list before selecting it. |
kind | Yes | Asset category: logo, font, image, icon, motion, audio or template. |
name | Yes | Human-readable kit or asset name. Kit metadata changes do not modify an immutable published snapshot. |
mimeType | Yes | MIME type registered for the asset. Uploaded contentType must match it. |
license | Conditional/optional | Optional non-empty asset licensing information. |
altText | Conditional/optional | Optional non-empty accessible description of the asset. |
Exact published input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"brandKitId": {
"type": "string",
"minLength": 1,
"description": "Brand kit identifier in the verified Brand workspace. Read brand_kits.list before selecting it."
},
"kind": {
"type": "string",
"enum": [
"logo",
"font",
"image",
"icon",
"motion",
"audio",
"template"
],
"description": "Asset category: logo, font, image, icon, motion, audio or template."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable kit or asset name. Kit metadata changes do not modify an immutable published snapshot."
},
"mimeType": {
"type": "string",
"minLength": 1,
"description": "MIME type registered for the asset. Uploaded contentType must match it."
},
"license": {
"type": "string",
"minLength": 1,
"description": "Optional non-empty asset licensing information."
},
"altText": {
"type": "string",
"minLength": 1,
"description": "Optional non-empty accessible description of the asset."
}
},
"required": [
"brandKitId",
"kind",
"name",
"mimeType"
],
"additionalProperties": false
}
Effects
Creates a pending asset record and an audit under an active kit; no content bytes are uploaded.
Interpret the response
asset contains its exact identifier, registered MIME type and status:pending. Use a supported kind. License and altText are optional non-empty metadata; registration is not a completed upload.
Response identifier contract:
{
"kind": "brand_asset",
"identifierSource": "response",
"idPath": "$.asset.id"
}
Worked examples
These complete synthetic responses were captured from the local worker over canonical SQL migrations. Auth and R2 dependencies are simulated; notification delivery is not exercised. Set BRAND_WORKSPACE_ID from granted workspace discovery. Save reviewed input as payload.json, validate and inspect the unchanged plan. The final mutation command and MCP confirm flag assume the intended effect has already been authorized.
Minimal example
Input · payload.json:
{
"brandKitId": "brand_c794be50-0306-4933-8de8-5609340bed9e",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"license": "Fixture-only artwork",
"altText": "Fixture identity"
}
CLI:
topolo actions validate app_topolo_brand.brand_assets.register --data @payload.json --json
topolo actions plan app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --confirm --json
MCP tool and arguments:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_brand.brand_assets.register",
"input": {
"brandKitId": "brand_c794be50-0306-4933-8de8-5609340bed9e",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"license": "Fixture-only artwork",
"altText": "Fixture identity"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by resource discovery>",
"confirm": true
}
}
Captured local response · HTTP 201:
{
"asset": {
"id": "brand_asset_dd192c95-76da-4c2e-a61c-8b164686806b",
"brandKitId": "brand_c794be50-0306-4933-8de8-5609340bed9e",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"storageKey": "org_documentation_fixture/brand_c794be50-0306-4933-8de8-5609340bed9e/brand_asset_dd192c95-76da-4c2e-a61c-8b164686806b",
"license": "Fixture-only artwork",
"altText": "Fixture identity",
"status": "pending",
"createdAt": "2026-10-03T11:23:59.064Z",
"updatedAt": "2026-10-03T11:23:59.064Z"
}
}
asset contains its exact identifier, registered MIME type and status:pending. Use a supported kind. License and altText are optional non-empty metadata; registration is not a completed upload.
Workflow example
Input · payload.json:
{
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"license": "Fixture-only artwork",
"altText": "Fixture identity"
}
CLI:
topolo actions validate app_topolo_brand.brand_assets.register --data @payload.json --json
topolo actions plan app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --confirm --json
MCP tool and arguments:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_brand.brand_assets.register",
"input": {
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"license": "Fixture-only artwork",
"altText": "Fixture identity"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by resource discovery>",
"confirm": true
}
}
Captured local response · HTTP 201:
{
"asset": {
"id": "brand_asset_87bffee4-7249-419b-b4c1-8edeeb732d55",
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture logo",
"mimeType": "image/svg+xml",
"storageKey": "org_documentation_fixture/brand_55886012-13a4-4e95-ad31-3fe2b52cdf20/brand_asset_87bffee4-7249-419b-b4c1-8edeeb732d55",
"license": "Fixture-only artwork",
"altText": "Fixture identity",
"status": "pending",
"createdAt": "2026-10-03T11:23:59.106Z",
"updatedAt": "2026-10-03T11:23:59.106Z"
}
}
asset contains its exact identifier, registered MIME type and status:pending. Use a supported kind. License and altText are optional non-empty metadata; registration is not a completed upload.
workflow email logo example
Input · payload.json:
{
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture email logo",
"mimeType": "image/png",
"altText": "Fixture email identity"
}
CLI:
topolo actions validate app_topolo_brand.brand_assets.register --data @payload.json --json
topolo actions plan app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_brand.brand_assets.register --resource-type workspace --resource-id "$BRAND_WORKSPACE_ID" --data @payload.json --confirm --json
MCP tool and arguments:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_brand.brand_assets.register",
"input": {
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture email logo",
"mimeType": "image/png",
"altText": "Fixture email identity"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by resource discovery>",
"confirm": true
}
}
Captured local response · HTTP 201:
{
"asset": {
"id": "brand_asset_dce3c24f-65dd-4579-913f-9ffbf74619c9",
"brandKitId": "brand_55886012-13a4-4e95-ad31-3fe2b52cdf20",
"kind": "logo",
"name": "Fixture email logo",
"mimeType": "image/png",
"storageKey": "org_documentation_fixture/brand_55886012-13a4-4e95-ad31-3fe2b52cdf20/brand_asset_dce3c24f-65dd-4579-913f-9ffbf74619c9",
"license": null,
"altText": "Fixture email identity",
"status": "pending",
"createdAt": "2026-10-03T11:23:59.114Z",
"updatedAt": "2026-10-03T11:23:59.114Z"
}
}
asset contains its exact identifier, registered MIME type and status:pending. Use a supported kind. License and altText are optional non-empty metadata; registration is not a completed upload.
Verify the result
List assets and confirm the identifier and metadata, then upload content using the matching MIME type.
Errors and recovery
-
auth_error(HTTP 401): CLI/SDK authentication classification when Auth returns a non-code message: restore the authorized credential, then verify whoami and context. Preserve the exact service message. -
permission_denied(HTTP 403): Use the exact permission and granted resource required by the reviewed action; organization membership alone is insufficient. -
workspace_required(HTTP 400): Discover and select a granted Brand workspace before preparing the request. -
brand_storage_unavailable(HTTP 503): The Brand storage bindings are unavailable. Preserve the request identifier and report the service fault; do not retry an unverified mutation.
Recovery boundary
This action set has no individual asset deletion endpoint. Do not register disposable live assets without an authorized cleanup strategy. Kit/workspace erasure is separate and much broader.
Related actions
app_topolo_brand.brand_assets.upload: Upload or replace bytes for a registered Brand asset.
Evidence
Four real local SQLite stores use all canonical migrations; Auth identity/grants and archival plus R2 object storage are explicitly simulated. Notifications are disabled in fixtures. No notification delivery, live mutation, gateway credential parity or deployed environment proof is claimed. Fixture identifiers and timestamps are synthetic and must be replaced by exact authorized resource discovery.