{"openapi":"3.1.1","info":{"title":"Brandloop Public API","version":"0.1.0","description":"Generated from workspace Zod contracts. This foundation covers authenticated subject inspection, brand-intelligence source orchestration, asset uploads, and generation job stubs.","contact":{"name":"Brandloop API"},"license":{"name":"Proprietary","url":"https://brandloop.app/terms"}},"servers":[{"url":"/"}],"tags":[{"name":"Identity","description":"Bearer-authenticated caller identity and subject introspection."},{"name":"Brand intelligence","description":"Source ingestion and processing status for Brandloop brand capture."},{"name":"Assets","description":"Asset upload session creation and asset metadata retrieval."},{"name":"Generations","description":"Asynchronous generation job creation and status retrieval."}],"security":[{"bearerAuth":[]}],"components":{"schemas":{"ApiKeySubject":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"a0744d46-c25e-4d0c-8c13-9b68a9e68177"},"type":{"type":"string","enum":["api_key"]},"label":{"type":"string","example":"Production integration key"},"mode":{"type":"string","enum":["live","test"],"example":"test"},"workspaceId":{"type":["string","null"],"format":"uuid","example":"0d93ed79-e5ea-4fd6-a478-acf7ebdbad37"},"accountId":{"type":["string","null"],"format":"uuid","example":"fe0187f0-9adc-466a-83c0-4818bf2a63c7"},"scopes":{"type":"array","items":{"type":"string","minLength":1},"example":["assets:write","assets:read","generations:read"]},"createdAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"},"lastUsedAt":{"type":["string","null"],"format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["id","type","label","mode","workspaceId","accountId","scopes","createdAt","lastUsedAt"]},"ApiKeySubjectEnvelope":{"type":"object","properties":{"data":{"type":"object","properties":{"subject":{"$ref":"#/components/schemas/ApiKeySubject"},"rateLimit":{"type":"object","properties":{"limit":{"type":["integer","null"],"exclusiveMinimum":0},"remaining":{"type":["integer","null"],"minimum":0},"resetAt":{"type":["string","null"],"format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["limit","remaining","resetAt"]}},"required":["subject","rateLimit"]}},"required":["data"]},"Asset":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"workspaceId":{"type":"string","format":"uuid","example":"0d93ed79-e5ea-4fd6-a478-acf7ebdbad37"},"purpose":{"$ref":"#/components/schemas/AssetPurpose"},"status":{"$ref":"#/components/schemas/AssetStatus"},"fileName":{"type":"string","minLength":1,"example":"hero-source.png"},"contentType":{"type":"string","minLength":1,"example":"image/png"},"byteLength":{"type":"integer","minimum":0,"example":2481021},"checksumSha256":{"type":["string","null"],"pattern":"^[a-f0-9]{64}$","example":"20a8b6fe4dfaf51d7cb78f1fb2d4c85d5d8f9cad2e3a86cc7a8d9f2e1d34c7af"},"sourceUrl":{"type":["string","null"],"format":"uri","description":"Original source location when it is safe to expose. Generated assets omit this value until safety and human review are complete.","example":"https://cdn.brandloop.dev/assets/9501dc0e.png"},"downloadUrl":{"type":["string","null"],"format":"uri","description":"Short-lived Brandloop download URL. Generated assets omit this value until safety and human review are complete.","example":"https://uploads.brandloop.dev/assets/9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"metadata":{"$ref":"#/components/schemas/Metadata"},"createdAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"},"updatedAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["id","workspaceId","purpose","status","fileName","contentType","byteLength","checksumSha256","sourceUrl","downloadUrl","metadata","createdAt","updatedAt"]},"AssetEnvelope":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Asset"}},"required":["data"]},"AssetListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Asset"}}},"required":["data"]},"AssetPurpose":{"type":"string","enum":["brand_reference","generation_input","generation_output","knowledge_attachment"]},"AssetStatus":{"type":"string","enum":["upload_pending","uploaded","processing","ready","failed"]},"AssetUploadInstruction":{"type":"object","properties":{"method":{"type":"string","enum":["PUT"]},"url":{"type":"string","format":"uri","example":"https://uploads.brandloop.dev/presigned/9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"headers":{"type":"object","additionalProperties":{"type":"string"},"example":{"content-type":"image/png","x-amz-checksum-sha256":"20a8b6fe4dfaf51d7cb78f1fb2d4c85d5d8f9cad2e3a86cc7a8d9f2e1d34c7af"}},"expiresAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["method","url","headers","expiresAt"]},"BrandIntelligenceSource":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"06f37b77-5c8f-4327-9a2e-0a63c7cf64dc"},"workspaceId":{"type":"string","format":"uuid","example":"0d93ed79-e5ea-4fd6-a478-acf7ebdbad37"},"platform":{"$ref":"#/components/schemas/BrandIntelligenceSourcePlatform"},"status":{"$ref":"#/components/schemas/BrandIntelligenceSourceStatus"},"url":{"type":"string","format":"uri","example":"https://example.com"},"normalizedUrl":{"type":"string","format":"uri","example":"https://example.com/"},"snapshotId":{"type":["string","null"],"format":"uuid","example":"1a5efb9f-a497-44b5-8fa1-cc120c8f6f81"},"idempotencyKey":{"type":["string","null"],"minLength":1},"message":{"type":["string","null"],"example":"Queued for source fetch and fact extraction."},"issues":{"type":"array","items":{"type":"string"},"example":[]},"createdAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"},"updatedAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["id","workspaceId","platform","status","url","normalizedUrl","snapshotId","idempotencyKey","message","issues","createdAt","updatedAt"]},"BrandIntelligenceSourceEnvelope":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BrandIntelligenceSource"}},"required":["data"]},"BrandIntelligenceSourcePlatform":{"type":"string","enum":["website","linkedin","instagram","x_twitter","tiktok"]},"BrandIntelligenceSourceStatus":{"type":"string","enum":["queued","processing","ready","failed"]},"CompleteAssetUploadRequest":{"type":"object","properties":{"status":{"type":"string","enum":["uploaded","ready"],"description":"Defaults to uploaded. Use ready only when the caller wants the uploaded asset marked immediately reusable.","example":"uploaded"},"byteLength":{"type":"integer","minimum":0,"example":2481021},"checksumSha256":{"type":"string","pattern":"^[a-f0-9]{64}$","example":"20a8b6fe4dfaf51d7cb78f1fb2d4c85d5d8f9cad2e3a86cc7a8d9f2e1d34c7af"},"contentType":{"type":"string","minLength":1,"example":"image/png"},"metadata":{"$ref":"#/components/schemas/Metadata"}}},"CreateAssetEnvelope":{"type":"object","properties":{"data":{"type":"object","properties":{"asset":{"$ref":"#/components/schemas/Asset"},"upload":{"$ref":"#/components/schemas/AssetUploadInstruction"}},"required":["asset","upload"]}},"required":["data"]},"CreateAssetRequest":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"example":"hero-source.png"},"contentType":{"type":"string","minLength":1,"example":"image/png"},"byteLength":{"type":"integer","exclusiveMinimum":0,"example":2481021},"checksumSha256":{"type":"string","pattern":"^[a-f0-9]{64}$","example":"20a8b6fe4dfaf51d7cb78f1fb2d4c85d5d8f9cad2e3a86cc7a8d9f2e1d34c7af"},"purpose":{"$ref":"#/components/schemas/AssetPurpose"},"sourceUrl":{"type":"string","format":"uri"},"metadata":{"$ref":"#/components/schemas/Metadata"}},"required":["fileName","contentType","byteLength","purpose"]},"CreateBrandIntelligenceSourceRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri","example":"https://example.com"},"platform":{"allOf":[{"$ref":"#/components/schemas/BrandIntelligenceSourcePlatform"},{"description":"Optional platform hint when the source is a public social profile."}]}},"required":["url"]},"CreateGenerationRequest":{"type":"object","properties":{"workflowKind":{"type":"string","minLength":1,"example":"aesthetic_ad"},"templateKey":{"type":"string","minLength":1,"example":"aesthetic_ad_v1"},"generationProfile":{"allOf":[{"$ref":"#/components/schemas/GenerationProfileId"},{"description":"Brandloop-owned product profile alias. Do not send provider model identifiers."}]},"outputCount":{"type":"integer","minimum":1,"maximum":4,"example":2},"assetIds":{"type":"array","items":{"type":"string","format":"uuid","example":"9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"default":[],"example":["9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"]},"input":{"$ref":"#/components/schemas/Metadata"}},"required":["workflowKind","outputCount","input"]},"ErrorCode":{"type":"string","enum":["authentication_required","forbidden","idempotency_conflict","not_found","rate_limited","setup_required","unsupported_operation","validation_failed"]},"Generation":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8d632e14-1dd6-4a6f-ae1b-0d632f54f203"},"workspaceId":{"type":"string","format":"uuid","example":"0d93ed79-e5ea-4fd6-a478-acf7ebdbad37"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"workflowKind":{"type":"string","minLength":1,"example":"aesthetic_ad"},"generationProfile":{"$ref":"#/components/schemas/GenerationProfileId"},"templateKey":{"type":["string","null"],"minLength":1,"example":"aesthetic_ad_v1"},"input":{"$ref":"#/components/schemas/Metadata"},"outputCount":{"type":"integer","exclusiveMinimum":0,"example":2},"assetIds":{"type":"array","items":{"type":"string","format":"uuid","example":"9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"example":["9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"]},"outputAssetIds":{"type":"array","items":{"type":"string","format":"uuid","example":"1918b0dc-ec4e-4b4a-b16a-2063c46d6dad"},"description":"Safe, human-reviewed generated asset identifiers only. Unsafe, unknown, and unreviewed outputs are omitted.","example":[]},"idempotencyKey":{"type":["string","null"],"minLength":1,"example":"gen_hero_q3_launch_v1"},"message":{"type":["string","null"],"example":"Queued for Brandloop generation."},"createdAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"},"updatedAt":{"type":"string","format":"date-time","example":"2026-07-07T18:24:11.000Z"}},"required":["id","workspaceId","status","workflowKind","generationProfile","templateKey","input","outputCount","assetIds","outputAssetIds","idempotencyKey","message","createdAt","updatedAt"]},"GenerationEnvelope":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Generation"}},"required":["data"]},"GenerationProfile":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/GenerationProfileId"},"label":{"type":"string","minLength":1,"example":"Image Standard"},"mediaType":{"type":"string","enum":["image"],"description":"Compatibility field for the output media type; see capabilities.mediaType.","example":"image"},"status":{"type":"string","enum":["stable","preview","deprecated"],"description":"Profile availability label for API discovery; this is not an SLA or provider guarantee.","example":"stable"},"default":{"type":"boolean","example":true},"maxOutputCount":{"type":"integer","exclusiveMinimum":0,"description":"Compatibility field for the maximum outputCount accepted by the request contract; see capabilities.maxOutputCount.","example":4},"supportsReferenceAssets":{"type":"boolean","description":"Compatibility field. True means the request contract accepts reference asset identifiers through assetIds; see capabilities.referenceAssets.","example":true},"capabilities":{"$ref":"#/components/schemas/GenerationProfileCapabilities"},"description":{"type":"string","minLength":1,"example":"Default Brandloop image generation profile for campaign asset workflows."}},"required":["id","label","mediaType","status","default","maxOutputCount","supportsReferenceAssets","capabilities","description"]},"GenerationProfileCapabilities":{"type":"object","properties":{"mediaType":{"type":"string","enum":["image"],"description":"Output media type exposed by this public profile.","example":"image"},"maxOutputCount":{"type":"integer","exclusiveMinimum":0,"description":"Maximum outputCount accepted by the public generation request contract.","example":4},"referenceAssets":{"type":"object","properties":{"supported":{"type":"boolean","description":"Generation requests may include reference asset identifiers.","example":true},"inputField":{"type":"string","enum":["assetIds"],"description":"Request field used to pass reference asset identifiers.","example":"assetIds"},"idFormat":{"type":"string","enum":["uuid"],"description":"Identifier format accepted in the assetIds array.","example":"uuid"}},"required":["supported","inputField","idFormat"],"description":"Request-shape support for reference assets; this does not expose private provider behavior."},"workflowKinds":{"type":"array","items":{"$ref":"#/components/schemas/GenerationWorkflowKind"},"description":"Workflow kinds accepted by POST /api/v1/generations for this profile.","example":["aesthetic_ad","ceo_founder","product_visual","social_variant"]}},"required":["mediaType","maxOutputCount","referenceAssets","workflowKinds"]},"GenerationProfileId":{"type":"string","enum":["brandloop-image-standard-v1"],"description":"Brandloop-owned public generation profile alias. Brandloop may route a profile to different private providers without changing this contract.","example":"brandloop-image-standard-v1"},"GenerationProfileListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GenerationProfile"}}},"required":["data"]},"GenerationStatus":{"type":"string","enum":["queued","processing","succeeded","failed","cancelled"],"description":"Public lifecycle state. Provider-completed output remains processing while safety or human review is pending, and fails closed when output safety is flagged, blocked, or unknown. Succeeded means at least one safe reviewed output is available."},"GenerationWorkflowKind":{"type":"string","enum":["aesthetic_ad","ceo_founder","product_visual","social_variant"],"description":"Public workflow kind currently accepted by the generation create endpoint.","example":"aesthetic_ad"},"IdempotencyKeyHeader":{"type":"string","minLength":1,"example":"brandloop:source:https-example-com:0d93ed79"},"Metadata":{"type":"object","additionalProperties":{},"description":"Opaque Brandloop metadata."},"Problem":{"type":"object","properties":{"type":{"type":"string","example":"https://brandloop.app/errors/validation_failed"},"title":{"type":"string","example":"The request body did not satisfy the contract."},"status":{"type":"integer","minimum":400,"maximum":599,"example":422},"detail":{"type":"string","example":"checksumSha256 must be a 64-character lowercase hex digest."},"instance":{"type":"string","example":"/api/v1/assets"},"code":{"$ref":"#/components/schemas/ErrorCode"},"requestId":{"type":"string","minLength":1,"example":"req_01JZYB7J4HVAXQ3M2C4Q9V37ZT"},"errors":{"$ref":"#/components/schemas/Metadata"}},"required":["type","title","status","code"],"description":"RFC 9457 problem document. Served with the application/problem+json media type."}},"parameters":{"IdempotencyKeyHeader":{"schema":{"$ref":"#/components/schemas/IdempotencyKeyHeader"},"required":true,"name":"Idempotency-Key","in":"header","description":"Required for every public API mutation. Brandloop uses this header, plus the request fingerprint, to replay identical retries and reject conflicting reuse. The request body does not define an idempotencyKey field."}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Use a Brandloop API key as a bearer token in the Authorization header. The key's scopes are documented in the public developer guide."}}},"paths":{"/api/v1/me":{"get":{"operationId":"getCurrentApiKeySubject","tags":["Identity"],"summary":"Inspect the authenticated API key subject.","description":"Returns the API key subject, account/workspace bindings, and current rate-limit snapshot for the bearer credential used on the request. Requires a valid API key; no resource scope is required.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Resolved API key subject.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeySubjectEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/brand-intelligence/sources":{"post":{"operationId":"createBrandIntelligenceSource","tags":["Brand intelligence"],"summary":"Queue a new brand intelligence source.","description":"Captures a public website or social profile reference and returns the first tracked source record. Send idempotency through the required Idempotency-Key header; body idempotencyKey values are not part of this public contract. Required API-key scope: `brand_sources:write`.","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKeyHeader"}],"requestBody":{"required":true,"description":"The public source to ingest into the Brandloop brand-intelligence pipeline.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBrandIntelligenceSourceRequest"}}}},"responses":{"202":{"description":"The source was accepted for asynchronous processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandIntelligenceSourceEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key conflicts with an existing source request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"422":{"description":"The source payload is valid JSON but violates the contract, or the required Idempotency-Key header is missing.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"brand_sources:write"}},"/api/v1/brand-intelligence/sources/{sourceId}":{"get":{"operationId":"getBrandIntelligenceSource","tags":["Brand intelligence"],"summary":"Fetch brand intelligence source status.","description":"Returns the latest persisted processing state for a previously created source. Required API-key scope: `brand_sources:read`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","example":"06f37b77-5c8f-4327-9a2e-0a63c7cf64dc"},"required":true,"name":"sourceId","in":"path","description":"Brand intelligence source identifier."}],"responses":{"200":{"description":"Current source status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandIntelligenceSourceEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The source identifier does not exist for the caller.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"brand_sources:read"}},"/api/v1/assets":{"get":{"operationId":"listAssets","tags":["Assets"],"summary":"List assets.","description":"Returns the caller's Brandloop asset records for the API key account and workspace. List responses omit short-lived download URLs; fetch an individual asset when a signed download URL is needed. Required API-key scope: `assets:read`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"example":50},"required":false,"name":"limit","in":"query","description":"Maximum number of assets to return. Defaults to 50."}],"responses":{"200":{"description":"Asset records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetListEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"assets:read"},"post":{"operationId":"createAssetUpload","tags":["Assets"],"summary":"Create an asset upload session.","description":"Creates an asset record and returns the upload instruction the caller should use to stream file bytes into Brandloop storage. Send idempotency through the required Idempotency-Key header; asset records do not currently echo that key as resource metadata. Required API-key scope: `assets:write`.","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKeyHeader"}],"requestBody":{"required":true,"description":"Asset metadata needed to mint an upload session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAssetRequest"}}}},"responses":{"201":{"description":"Asset record and upload instruction created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAssetEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key conflicts with a different upload request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"422":{"description":"The upload metadata is structurally valid JSON but invalid for Brandloop, or the required Idempotency-Key header is missing.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"assets:write"}},"/api/v1/assets/{assetId}":{"get":{"operationId":"getAsset","tags":["Assets"],"summary":"Fetch asset metadata.","description":"Returns the canonical Brandloop asset record, including any current download URL. Required API-key scope: `assets:read`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"required":true,"name":"assetId","in":"path","description":"Brandloop asset identifier."}],"responses":{"200":{"description":"Asset metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The asset identifier does not exist for the caller.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"assets:read"}},"/api/v1/assets/{assetId}/complete":{"post":{"operationId":"completeAssetUpload","tags":["Assets"],"summary":"Complete an asset upload.","description":"Verifies the uploaded object in Brandloop storage and advances the asset from upload_pending to uploaded or ready. Send idempotency through the required Idempotency-Key header. Required API-key scope: `assets:write`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9501dc0e-b4d4-43ef-b687-b8bcc7d7ce10"},"required":true,"name":"assetId","in":"path","description":"Brandloop asset identifier."},{"$ref":"#/components/parameters/IdempotencyKeyHeader"}],"requestBody":{"required":false,"description":"Optional upload verification metadata supplied by the caller after file bytes are transferred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteAssetUploadRequest"}}}},"responses":{"200":{"description":"Completed asset metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The asset identifier does not exist for the caller.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"409":{"description":"The Idempotency-Key conflicts with a different upload-completion request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"422":{"description":"The upload-completion metadata is invalid or the object cannot be verified in storage.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"assets:write"}},"/api/v1/generation-profiles":{"get":{"operationId":"listGenerationProfiles","tags":["Generations"],"summary":"List available generation profiles.","description":"Returns Brandloop-owned generation profile aliases that callers may use when creating generation jobs. Profiles describe product-level behavior, not private provider model identifiers. Required API-key scope: `generations:read`.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Available Brandloop generation profiles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationProfileListEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"generations:read"}},"/api/v1/generations":{"post":{"operationId":"createGeneration","tags":["Generations"],"summary":"Queue a generation job.","description":"Creates a Brandloop generation record for asynchronous processing against the selected workflow. Send idempotency through the required Idempotency-Key header; body idempotencyKey values are not part of this public contract. Required API-key scope: `generations:write`.","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKeyHeader"}],"requestBody":{"required":true,"description":"Structured generation request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenerationRequest"}}}},"responses":{"202":{"description":"Generation accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"The Idempotency-Key conflicts with a different generation request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"422":{"description":"The generation payload is valid JSON but violates the public generation contract, or the required Idempotency-Key header is missing.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"generations:write"}},"/api/v1/generations/{generationId}":{"get":{"operationId":"getGeneration","tags":["Generations"],"summary":"Fetch generation status.","description":"Returns the persisted state for a generation request, including any linked output assets. Required API-key scope: `generations:read`.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8d632e14-1dd6-4a6f-ae1b-0d632f54f203"},"required":true,"name":"generationId","in":"path","description":"Generation request identifier."}],"responses":{"200":{"description":"Generation status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationEnvelope"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"401":{"description":"The bearer token is missing, invalid, or expired.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The bearer token does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The generation identifier does not exist for the caller.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60}}},"429":{"description":"The caller exceeded its request budget.","headers":{"RateLimit-Limit":{"description":"Request budget for the current fixed window.","schema":{"type":"integer"},"example":120},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"},"example":120},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer"},"example":60},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"},"example":12}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"x-brandloop-required-scope":"generations:read"}}},"webhooks":{}}