thirds.ai Brand Kits API

The Brand Kits API from thirds.ai — 4 operation(s) for brand kits.

Operations 8

POST /v1/brand-kits Create a brand kit #
GET /v1/brand-kits List brand kits #
GET /v1/brand-kits/{brand_kit_id} Get a brand kit #
PATCH /v1/brand-kits/{brand_kit_id} Update a brand kit #
DELETE /v1/brand-kits/{brand_kit_id} Archive a brand kit #
POST /v1/brand-kits/{brand_kit_id}/assets Add a brand asset #
GET /v1/brand-kits/{brand_kit_id}/assets/{asset_id} Read a brand asset #
PUT /v1/brand-kits/{brand_kit_id}/assets/{asset_id} Replace a brand asset #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/thirds-ai:thirds-ai-brand-kits-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

thirds-ai-brand-kits-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: thirds.ai Brand Kits API
  version: 1.0.0
  description: Turn one design into content at scale. Create branded images and PDFs for your campaigns and clients. Automate each new version through our API or your AI tools. Render saved templates with new data, or send HTML directly. Every error uses one envelope, every response carries an x-request-id header, and every JSON request body rejects fields it does not expect.
servers:
- url: https://thirds.ai
tags:
- name: Brand Kits
paths:
  /v1/brand-kits:
    post:
      summary: Create a brand kit
      description: 'Create one mutable account-owned brand kit. Logos and fonts are uploaded through the kit''s asset route after creation. The account plan sets how many kits the account can keep: 1 on Free, a pack-only account, and Starter, 5 on Growth, and 20 on Scale. Every kit of the account counts, archived kits too. A kit over that limit answers 409 brand_kit_limit with error.plan_limit. An account above its limit after a downgrade keeps every kit and can still change and archive them.'
      operationId: createBrandKit
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BrandKitWrite'
      responses:
        '201':
          description: The brand kit was created.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandKitDetail'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '409':
          $ref: '#/components/responses/Error'
        '413':
          $ref: '#/components/responses/Error'
        '415':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
    get:
      summary: List brand kits
      description: List the account's active and archived brand kits newest first. Asset metadata is omitted from the page; read one kit for its current assets.
      operationId: listBrandKits
      security:
      - bearerAuth: []
      parameters:
      - name: status
        in: query
        schema:
          type: string
          enum:
          - active
          - archived
          - all
          default: all
      - name: limit
        in: query
        schema:
          type: integer
          default: 20
      - name: cursor
        in: query
        schema:
          type: string
          maxLength: 128
      responses:
        '200':
          description: One page of brand-kit summaries.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandKitPage'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
  /v1/brand-kits/{brand_kit_id}:
    parameters:
    - name: brand_kit_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/BrandKitId'
    get:
      summary: Get a brand kit
      description: Return one owned kit and its current logo and font metadata. Replaced assets remain private durable content but are omitted.
      operationId: getBrandKit
      security:
      - bearerAuth: []
      responses:
        '200':
          description: The brand kit and its current assets.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandKitDetail'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
    patch:
      summary: Update a brand kit
      description: Replace any supplied mutable brand values. Omitted fields stay unchanged; a null tone_guidance clears it. Archived kits cannot change.
      operationId: updateBrandKit
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BrandKitPatch'
      responses:
        '200':
          description: The updated kit and its current assets.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandKitDetail'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '413':
          $ref: '#/components/responses/Error'
        '415':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
    delete:
      summary: Archive a brand kit
      description: Archive one owned kit. The operation is idempotent. The kit and every current or replaced asset stay durable for already captured references.
      operationId: archiveBrandKit
      security:
      - bearerAuth: []
      responses:
        '204':
          description: The brand kit is archived.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
  /v1/brand-kits/{brand_kit_id}/assets:
    parameters:
    - name: brand_kit_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/BrandKitId'
    post:
      summary: Add a brand asset
      description: Add one logo or WOFF2 font to an active owned kit. The declared Content-Type and the complete bytes must agree. No customer bytes or storage reference appears in the response.
      operationId: createBrandAsset
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          image/png:
            schema:
              type: string
              format: binary
          image/jpeg:
            schema:
              type: string
              format: binary
          image/webp:
            schema:
              type: string
              format: binary
          font/woff2:
            schema:
              type: string
              format: binary
      responses:
        '201':
          description: The immutable asset was accepted and selected by the kit.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandAsset'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '413':
          $ref: '#/components/responses/Error'
        '415':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '429':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
  /v1/brand-kits/{brand_kit_id}/assets/{asset_id}:
    parameters:
    - name: brand_kit_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/BrandKitId'
    - name: asset_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/BrandAssetId'
    get:
      summary: Read a brand asset
      description: Read the validated logo or font bytes from an owned kit. Captured assets remain readable after replacement or archive. Responses are private and must not be cached.
      operationId: readBrandAsset
      security:
      - bearerAuth: []
      responses:
        '200':
          description: The validated image or WOFF2 font bytes.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            image/png:
              schema:
                type: string
                format: binary
            image/jpeg:
              schema:
                type: string
                format: binary
            image/webp:
              schema:
                type: string
                format: binary
            font/woff2:
              schema:
                type: string
                format: binary
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
    put:
      summary: Replace a brand asset
      description: Create a new immutable asset of the same kind and make it current. The old asset and bytes stay unchanged for any template or queued operation that already captured its ID.
      operationId: replaceBrandAsset
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          image/png:
            schema:
              type: string
              format: binary
          image/jpeg:
            schema:
              type: string
              format: binary
          image/webp:
            schema:
              type: string
              format: binary
          font/woff2:
            schema:
              type: string
              format: binary
      responses:
        '201':
          description: The new immutable current asset.
          headers:
            x-request-id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrandAsset'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          $ref: '#/components/responses/Error'
        '413':
          $ref: '#/components/responses/Error'
        '415':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '429':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '431':
          $ref: '#/components/responses/RequestHeadersTooLarge'
      tags:
      - Brand Kits
components:
  responses:
    MethodNotAllowed:
      description: The method is not allowed on this route.
      headers:
        x-request-id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    AccountSuspended:
      description: The authenticated account is suspended. The code is account_suspended.
      headers:
        x-request-id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    RequestHeadersTooLarge:
      description: The request has more than 64 headers or more than 32 KiB of header names and values.
      headers:
        x-request-id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Error:
      description: The one error envelope every backend response uses.
      headers:
        x-request-id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  schemas:
    BrandKitSummary:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/BrandKitId'
        name:
          type: string
          minLength: 1
          maxLength: 100
        colours:
          type: array
          maxItems: 16
          uniqueItems: true
          items:
            type: string
            pattern: ^#[0-9a-f]{6}$
        tone_guidance:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 500
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        archived_at:
          type:
          - string
          - 'null'
          format: date-time
        assets:
          type: array
          maxItems: 16
          items:
            $ref: '#/components/schemas/BrandAsset'
      required:
      - id
      - name
      - colours
      - tone_guidance
      - created_at
      - updated_at
      - archived_at
      - assets
      additionalProperties: false
    BrandKitPatch:
      type: object
      properties:
        archived_at:
          type: 'null'
          description: Restore the item. Omit this field to keep its archive state.
        name:
          type: string
          minLength: 1
          maxLength: 100
        colours:
          type: array
          maxItems: 16
          uniqueItems: true
          items:
            type: string
            pattern: ^#[0-9A-Fa-f]{6}$
        tone_guidance:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 500
      minProperties: 1
      additionalProperties: false
    ErrorEnvelope:
      type: object
      description: The one error shape every backend response uses.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
              - account_suspended
              - account_concurrency_limited
              - abuse_limited
              - ai_failure_limit_reached
              - ai_needs_paid_credits
              - already_subscribed
              - auth_unavailable
              - batch_row_limit
              - billing_unavailable
              - brand_asset_account_limit_reached
              - brand_asset_invalid
              - brand_asset_kind_invalid
              - brand_asset_kind_mismatch
              - brand_asset_limit_reached
              - brand_asset_too_large
              - brand_asset_type_unsupported
              - brand_data_conflict
              - brand_font_glyphs_exceeded
              - brand_font_tables_invalid
              - brand_image_animated
              - brand_image_dimensions_invalid
              - brand_image_pixels_exceeded
              - brand_kit_colours_invalid
              - brand_kit_conflict
              - brand_kit_limit
              - brand_kit_name_invalid
              - brand_kit_not_found
              - brand_kit_patch_empty
              - brand_kit_tone_invalid
              - brand_kit_unavailable
              - captcha_rejected
              - checkout_superseded
              - cross_origin_rejected
              - csrf_rejected
              - download_expired
              - email_already_set
              - gallery_template_not_found
              - generated_template_invalid
              - idempotency_conflict
              - image_asset_header_unsupported
              - image_asset_invalid
              - image_asset_limit
              - image_asset_not_found
              - image_asset_reference_invalid
              - image_asset_too_large
              - image_asset_type_unsupported
              - image_asset_unavailable
              - image_url_invalid
              - image_url_unavailable
              - insufficient_credits
              - internal_error
              - invalid_cursor
              - invalid_email
              - invalid_event
              - invalid_link
              - invalid_profile
              - invalid_request
              - invalid_upload
              - job_not_finished
              - key_concurrency_limited
              - key_limit_reached
              - method_not_allowed
              - no_billing_customer
              - not_found
              - operation_conflict
              - operation_limit_exceeded
              - operation_pending
              - overage_limit_reached
              - overage_unavailable
              - overloaded
              - playground_busy
              - playground_request_invalid
              - playground_selection_invalid
              - playground_session_limited
              - playground_unavailable
              - policy_version_stale
              - provider_unavailable
              - rate_limited
              - render_probe_busy
              - render_probe_failed
              - render_probe_not_configured
              - render_probe_required
              - render_probe_timeout
              - request_headers_too_large
              - request_too_large
              - resize_timeout
              - signed_out
              - spend_cap_reached
              - template_build_not_found
              - template_data_collection_limit
              - template_data_depth_limit
              - template_data_invalid
              - template_data_limit
              - template_depth_limit
              - template_draft_not_found
              - template_evaluation_error
              - template_invalid_filter_input
              - template_missing_data
              - template_output_limit
              - template_not_found
              - template_schema_complexity
              - template_schema_draft_unsupported
              - template_schema_invalid
              - template_schema_too_large
              - template_size_canvas_mismatch
              - template_size_data_overrides_too_large
              - template_size_duplicate_id
              - template_size_invalid_dimensions
              - template_size_invalid_id
              - template_size_invalid_name
              - template_sizes_too_large
              - template_sizes_too_many
              - template_source_limit
              - template_syntax_error
              - template_timeout
              - template_version_changed
              - template_work_limit
              - testimonial_busy
              - testimonial_invalid
              - testimonial_rate_limited
              - testimonial_unavailable
              - unauthorized
              - unsupported_media_type
              - webhook_limit_reached
              description: A fixed, machine-readable error code.
            message:
              type: string
              description: A fixed, human-readable message.
            request_id:
              type: string
              format: uuid
              description: The identifier this answer also carries in its x-request-id header.
            details:
              type: array
              description: Present on a validation failure. Schema failures return at most 16 entries with bounded data paths and fixed reasons. Values from the request are never repeated.
              items:
                $ref: '#/components/schemas/FieldDetail'
            retry:
              $ref: '#/components/schemas/RetryInfo'
            plan_limit:
              $ref: '#/components/schemas/PlanLimitInfo'
          required:
          - code
          - message
          - request_id
          additionalProperties: false
      required:
      - error
      additionalProperties: false
    BrandAsset:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/BrandAssetId'
        kind:
          type: string
          enum:
          - logo
          - font
        media_type:
          type: string
          enum:
          - image/png
          - image/jpeg
          - image/webp
          - font/woff2
        byte_size:
          type: integer
          minimum: 1
          maximum: 10485760
        created_at:
          type: string
          format: date-time
      required:
      - id
      - kind
      - media_type
      - byte_size
      - created_at
      additionalProperties: false
    BrandKitWrite:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        colours:
          type: array
          maxItems: 16
          uniqueItems: true
          items:
            type: string
            pattern: ^#[0-9A-Fa-f]{6}$
          default: []
        tone_guidance:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 500
      required:
      - name
      additionalProperties: false
    RetryInfo:
      type: object
      description: How long the caller must wait before it retries.
      properties:
        retry_after_seconds:
          type: integer
          minimum: 1
          maximum: 60
      required:
      - retry_after_seconds
      additionalProperties: false
    BrandKitPage:
      type: object
      properties:
        items:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/BrandKitSummary'
        next_cursor:
          type:
          - string
          - 'null'
          maxLength: 128
      required:
      - items
      - next_cursor
      additionalProperties: false
    ArchivePeriod:
      type: object
      properties:
        archived_at:
          type: string
          format: date-time
        restored_at:
          type:
          - string
          - 'null'
          format: date-time
      required:
      - archived_at
      - restored_at
      additionalProperties: false
    BrandAssetId:
      type: string
      pattern: ^asset_[0-9a-f]{32}$
    BrandKitDetail:
      type: object
      properties:
        archive_history:
          type: array
          items:
            $ref: '#/components/schemas/ArchivePeriod'
        id:
          $ref: '#/components/schemas/BrandKitId'
        name:
          type: string
          minLength: 1
          maxLength: 100
        colours:
          type: array
          maxItems: 16
          uniqueItems: true
          items:
            type: string
            pattern: ^#[0-9a-f]{6}$
        tone_guidance:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 500
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        archived_at:
          type:
          - string
          - 'null'
          format: date-time
        assets:
          type: array
          maxItems: 16
          items:
            $ref: '#/components/schemas/BrandAsset'
      required:
      - archive_history
      - id
      - name
      - colours
      - tone_guidance
      - created_at
      - updated_at
      - archived_at
      - assets
      additionalProperties: false
    FieldDetail:
      type: object
      description: One request field that failed, its fixed safe reason, and an optional bounded source location. Details never carry template source, customer values, rendered output, or raw evaluator prose.
      properties:
        field:
          type: string
          maxLength: 260
          description: The path to the field, such as "pdf.scale". Schema errors use data followed by a JSON Pointer, such as data/items/0/count. The pointer is cut at 256 UTF-8 bytes. Empty for a problem with the whole document.
        reason:
          type: string
          enum:
          - malformed JSON
          - missing field
          - unknown field
          - wrong type
          - invalid value
          - A required value is missing.
          - Use the expected value type.
          - Declare this variable before using it.
          - Choose an allowed value.
          - Use the required format.
          - Add a value.
          - Use a shorter value.
          - Use a number within the allowed range.
          - Check this value against its data rule.
          description: A fixed, safe reason. It never repeats the value the caller sent.
        line:
          type: integer
          minimum: 1
          maximum: 1000000
          description: The one-based template source line when the evaluator provides one within the published bound.
        column:
          type: integer
          minimum: 1
          maximum: 1000000
          description: The one-based template source column when the evaluator provides one within the published bound.
      required:
      - field
      - reason
      additionalProperties: false
    BrandKitId:
      type: string
      pattern: ^kit_[0-9a-f]{32}$
    PlanLimitInfo:
      type: object
      description: 'Present when the account''s plan causes the refusal: brand_kit_limit and batch_row_limit. It names the limit and the plan that sets it, so a caller can act without a second request. The message text never names the number.'
      properties:
        plan:
          type: string
          enum:
          - scale
          - growth
          - starter
          - pack
          - free
          description: The account's plan at the time of the refusal.
        limit:
          type: integer
          minimum: 1
          description: 'What that plan allows: brand kits for brand_kit_limit, rows in one run for batch_row_limit.'
      required:
      - plan
      - limit
      additionalProperties: false
  headers:
    XRequestId:
      description: The UUID that identifies this request and matches error.request_id on an error response.
      required: true
      schema:
        type: string
        format: uuid
  securitySchemes:
    sessionCookie:
      type: apiKey
      in: cookie
      name: __Host-thirds_session
      description: A browser session. Browser writes also require the matching x-csrf-token header from GET /v1/me.
    bearerAuth:
      type: http
      scheme: bearer
      description: 'An API key''s secret, sent as "Authorization: Bearer thirds_sk_v1_...".'
x-unmatched-v1-responses:
  description: A request below /v1 that matches no operation receives the shared safe envelope. OpenAPI has no standard path item for an unmatched route, so this extension records the fallback contract without claiming that a catch-all operation exists.
  '404':
    $ref: '#/components/responses/NotFound'
  '431':
    $ref: '#/components/responses/RequestHeadersTooLarge'