> ## Documentation Index
> Fetch the complete documentation index at: https://docs.affixo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Register a product by your own id

> For workspaces that don't use Stripe. Registers a product under the id your own system uses, so you can give it its own commission rate or switch commissions off for it. Requires `write` scope. A workspace whose plan is restricted gets `402 plan_restricted`. Registering a product doesn't change what it earns, or what its past sales earned: it starts with the same setting as your other uncatalogued products (on when the products policy is on, off when it's off). Turn it on or off, or give it its own rate, to change that. Registering never happens automatically: a sale with an unknown `product_id` earns the campaign's default rate, or nothing if the products policy is off, until you register it. Stripe workspaces get `409 stripe_connected` because their products sync from Stripe.



## OpenAPI

````yaml /openapi.yaml post /v1/products
openapi: 3.1.0
info:
  title: Affixo API
  version: 1.0.0
  description: |
    The Affixo REST API for affiliate program management and server-to-server
    conversion tracking.

    All requests authenticate with a workspace key (`sa_live_…`) as a Bearer
    token. Scopes: `read` / `write` / `track` / `*`.
servers:
  - url: https://go.affixo.dev
    description: Production
security: []
tags:
  - name: Affiliates
    description: Manage affiliates (workspace key)
  - name: Campaigns
    description: Create and configure campaigns + commission rules (workspace key)
  - name: Links
    description: Manage referral links (workspace key)
  - name: Risk
    description: AI risk assessments for fraud triage (workspace key)
  - name: Commissions
    description: Approve, deny, and manage commissions (workspace key)
  - name: Conversions
    description: Re-attribute and manage conversions (workspace key)
  - name: Webhooks
    description: Manage webhook endpoint subscriptions (workspace key)
  - name: Reports
    description: Aggregated reporting data (workspace key)
  - name: Resources
    description: Read campaigns, commissions, conversions, payouts (workspace key)
  - name: Referrals
    description: >-
      Move a referred customer to another affiliate, and send test referrals
      (workspace key)
  - name: Tracking
    description: >-
      Server-to-server click & conversion tracking (workspace key, scope
      "track")
  - name: Products
    description: >-
      Your Stripe product catalog and which products earn commission (workspace
      key)
paths:
  /v1/products:
    post:
      tags:
        - Products
      summary: Register a product by your own id
      description: >-
        For workspaces that don't use Stripe. Registers a product under the id
        your own system uses, so you can give it its own commission rate or
        switch commissions off for it. Requires `write` scope. A workspace whose
        plan is restricted gets `402 plan_restricted`. Registering a product
        doesn't change what it earns, or what its past sales earned: it starts
        with the same setting as your other uncatalogued products (on when the
        products policy is on, off when it's off). Turn it on or off, or give it
        its own rate, to change that. Registering never happens automatically: a
        sale with an unknown `product_id` earns the campaign's default rate, or
        nothing if the products policy is off, until you register it. Stripe
        workspaces get `409 stripe_connected` because their products sync from
        Stripe.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - product_id
                - name
              properties:
                product_id:
                  type: string
                  minLength: 1
                  maxLength: 255
                  example: plan_pro
                name:
                  type: string
                  minLength: 1
                  maxLength: 255
                  example: Pro plan
      responses:
        '201':
          description: The registered product, in the same shape as the items in the list
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: product
                  data:
                    type: object
        '400':
          description: '`invalid_product_id` or `invalid_name`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: invalid_product_id
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/DashboardLocked'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '409':
          description: >-
            `stripe_connected` (this workspace syncs products from Stripe) or
            `product_exists`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: product_exists
        '500':
          description: >-
            `policy_unavailable`: the products policy couldn't be read, so
            nothing was registered. Safe to retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: policy_unavailable
      security:
        - WorkspaceKey: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        need:
          type: string
          description: Present on insufficient_scope.
        detail:
          type: string
  responses:
    Unauthorized:
      description: Missing or invalid bearer token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthorized
    DashboardLocked:
      description: >-
        Your plan's dashboard and management access is locked until you upgrade.
        Tracking keeps working.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: plan_restricted
    InsufficientScope:
      description: The key lacks the required scope
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: insufficient_scope
            need: write
  securitySchemes:
    WorkspaceKey:
      type: http
      scheme: bearer
      description: 'Workspace API key, e.g. `sa_live_…`. Scopes: read / write / track / *.'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.