---
updatedAt: 2026-09-14T14:06:11.000Z
agentTools:
  projectIndex: https://developers.agendapro.com/llms.txt
---

# Activate Product

This endpoint sets a product to active. It takes no request body, and is idempotent.

### Errors Dictionary

| **Status** | **Error** | **Detail** | **Description** |
| --- | --- | --- | --- |
| 401 | unauthorized | invalid_api_key | Missing or invalid Bearer token. |
| 401 | unauthorized | api_config_inactive | API access is inactive for this company. |
| 403 | forbidden | scope_denied | API key lacks `products:write` scope. |
| 404 | not_found | product | Product not found, or it belongs to another company. |
| 429 | rate_limited | burst_limit_exceeded | Per-minute request limit exceeded. |
| 429 | rate_limited | daily_quota_exceeded | Daily request quota exceeded. |
| 502 | upstream_unavailable |  | The upstream service is unavailable. |


# OpenAPI definition

````json
{
  "openapi": "3.0.3",
  "info": {
    "title": "Connect v3",
    "version": "3.0.0",
    "description": "Public API gateway for AgendaPro.\nAuthenticates external developers, enforces rate limits and scopes, and proxies requests to internal services.\n\n## Authentication\n\nAll requests require a Bearer API key in the `Authorization` header:\n\n```\nAuthorization: Bearer <your-api-key>\n```\n\nAPI keys are scoped to a single company. The `company_id` is derived automatically\nfrom the API key — you never pass it as a parameter.\n\n## Scopes\n\nAPI keys may be restricted to specific scopes. Scopes follow the pattern `{resource}:{action}`:\n\n| Scope | Description |\n| --- | --- |\n| `bookings:read` | List and show bookings |\n| `bookings:write` | Create, update, and cancel bookings |\n| `clients:read` | List and show clients |\n| `clients:write` | Create and update clients |\n| `locations:read` | List and show locations |\n| `services:read` | List and show services |\n| `categories:read` | List service categories |\n| `providers:read` | List and show providers |\n| `custom_attributes:read` | List custom attribute templates |\n| `sales:read` | List and show sales |\n| `carts:read` | Show carts |\n| `carts:write` | Create and update carts; create payment requests on a cart |\n| `payment_requests:write` | Cancel payment requests |\n| `leads:read` | List and show Cortex leads and their conversations |\n| `segments:read` | List and show Cortex CRM segments and their members |\n| `conversations:read` | List the messages and the agent tool calls of a Cortex conversation |\n| `reminder_messages:read` | List the reminder messages sent by Cortex |\n| `provider_breaks:read` | List and show provider breaks; show provider break series |\n| `provider_breaks:write` | Create, update and delete provider breaks; create and delete provider break series |\n\nAn API key with empty scopes has full access (all scopes granted).\n\n## Rate Limiting\n\nTwo rate limits apply per company:\n\n- **Burst limit**: Maximum requests per minute.\n- **Daily quota**: Maximum requests per day.\n\nRate limit status is returned in response headers:\n\n| Header | Description |\n| --- | --- |\n| `X-RateLimit-Limit` | Daily quota limit |\n| `X-RateLimit-Remaining` | Daily requests remaining |\n| `X-RateLimit-Reset` | Unix timestamp when daily quota resets |\n| `X-RateLimit-Burst-Limit` | Burst (per-minute) limit |\n| `X-RateLimit-Burst-Remaining` | Burst requests remaining |\n| `X-RateLimit-Burst-Reset` | Unix timestamp when burst window resets |\n\nWhen either limit is exceeded, the API returns `429 Too Many Requests` with a `Retry-After` header.\n\n## Pagination\n\nList endpoints return paginated responses wrapped in a `data` array with a `pagination` metadata object:\n\n```json\n{\n  \"data\": [...],\n  \"pagination\": {\n    \"current_page\": 1,\n    \"per_page\": 30,\n    \"next_page\": null,\n    \"prev_page\": null,\n    \"total_records\": 95,\n    \"total_pages\": 4\n  }\n}\n```\n\nLeads, segments and reminder messages (served by Cortex, AgendaPro's conversational agent) are\npaginated by cursor instead. Pass `limit` and, for the next page, the `next_cursor` you received\nas `cursor`; `next_cursor` is `null` on the last page:\n\n```json\n{\n  \"data\": [...],\n  \"pagination\": {\n    \"next_cursor\": \"eyJpZCI6IjEyMyJ9\"\n  }\n}\n```\n\n## Dates and times\n\nBooking and provider break dates are the local time of the location, written in ISO 8601\nwith a `Z` suffix. The `Z` does **not** mean UTC: a break that starts at 13:00 in Santiago is\nsent and returned as `2026-10-23T13:00:00Z`. Send dates in the same form: an offset such as\n`-03:00` either shifts the time or is rejected, depending on the endpoint.\n\n## Webhooks\n\nThe `booking.created` and `booking.updated` webhook payloads are filtered with the same field list\nas the Booking resource, so they also carry `creative_source`.\n\n## Errors\n\nErrors produced by Connect use the `{error, detail}` format:\n\n```json\n{\n  \"error\": \"error_type\",\n  \"detail\": \"additional_context\"\n}\n```\n\nSome business errors of carts, payment requests, provider breaks and the booking history come from the service behind the endpoint with a legacy single-key code, such as `{\"error\": \"cart_expired\"}`. Each endpoint's errors dictionary says which shape each error has.\n"
  },
  "servers": [
    {
      "url": "https://connect.agendapro.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Products",
      "description": "Product catalog management (list, show, create, update, activate, deactivate)"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/v3/products/{id}/activate": {
      "patch": {
        "operationId": "activateProduct",
        "summary": "Activate Product",
        "description": "This endpoint sets a product to active. It takes no request body, and is idempotent.\n\n### Errors Dictionary\n\n| **Status** | **Error** | **Detail** | **Description** |\n| --- | --- | --- | --- |\n| 401 | unauthorized | invalid_api_key | Missing or invalid Bearer token. |\n| 401 | unauthorized | api_config_inactive | API access is inactive for this company. |\n| 403 | forbidden | scope_denied | API key lacks `products:write` scope. |\n| 404 | not_found | product | Product not found, or it belongs to another company. |\n| 429 | rate_limited | burst_limit_exceeded | Per-minute request limit exceeded. |\n| 429 | rate_limited | daily_quota_exceeded | Daily request quota exceeded. |\n| 502 | upstream_unavailable |  | The upstream service is unavailable. |\n",
        "tags": [
          "Products"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductId"
          }
        ],
        "responses": {
          "200": {
            "description": "Product activated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ProductNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key issued per company. Pass as Authorization: Bearer <key>."
      }
    },
    "parameters": {
      "ProductId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Product unique identifier.",
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      }
    },
    "schemas": {
      "ProductDimension": {
        "type": "object",
        "nullable": true,
        "description": "A product dimension (category, brand or display). Returned as `null` when the product has no real dimension assigned.\n",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique dimension ID.",
            "example": 441
          },
          "name": {
            "type": "string",
            "description": "Dimension name.",
            "example": "Salud"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Product": {
        "type": "object",
        "description": "Product resource (filtered for public API). Internal pricing and commission data (`cost`, `internal_price`, `tax`, `has_sales_taxes`, `commission_value`, `commission_option`) is never returned.\n",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique product ID.",
            "example": 3518
          },
          "name": {
            "type": "string",
            "description": "Product name.",
            "example": "Shampoo"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Product description. Empty string when not set.",
            "example": "Shampoo for dry hair"
          },
          "sku": {
            "type": "string",
            "nullable": true,
            "description": "Stock keeping unit code.",
            "example": "SH-01"
          },
          "price": {
            "type": "string",
            "description": "Sale price, serialized as a decimal string.",
            "example": "10000.0"
          },
          "active": {
            "type": "boolean",
            "description": "Whether the product is active.",
            "example": true
          },
          "category": {
            "$ref": "#/components/schemas/ProductDimension"
          },
          "brand": {
            "$ref": "#/components/schemas/ProductDimension"
          },
          "display": {
            "$ref": "#/components/schemas/ProductDimension"
          }
        },
        "required": [
          "id",
          "name",
          "price",
          "active"
        ]
      },
      "ErrorDetailResponse": {
        "type": "object",
        "description": "Standard error response.\nThe `error` field contains the error type and the `detail` field\nprovides additional context.\n",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error type identifier.",
            "example": "unauthorized"
          },
          "detail": {
            "type": "string",
            "nullable": true,
            "description": "Additional context about the error.",
            "example": "invalid_api_key"
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid Bearer API key, or inactive API configuration.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "example": "Bearer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "invalidApiKey": {
                "summary": "[Error] 401 Unauthorized - Invalid API key",
                "value": {
                  "error": "unauthorized",
                  "detail": "invalid_api_key"
                }
              },
              "apiConfigInactive": {
                "summary": "[Error] 401 Unauthorized - API access inactive",
                "value": {
                  "error": "unauthorized",
                  "detail": "api_config_inactive"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "API key lacks the required scope for this operation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "scopeDenied": {
                "summary": "[Error] 403 Forbidden - Scope denied",
                "value": {
                  "error": "forbidden",
                  "detail": "scope_denied"
                }
              }
            }
          }
        }
      },
      "ProductNotFound": {
        "description": "Product not found, or it belongs to another company.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "productNotFound": {
                "summary": "[Error] 404 Not Found - Product not found",
                "value": {
                  "error": "not_found",
                  "detail": "product"
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded. Check the `Retry-After` header.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the rate limit resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "burstLimitExceeded": {
                "summary": "[Error] 429 Too Many Requests - Burst limit",
                "value": {
                  "error": "rate_limited",
                  "detail": "burst_limit_exceeded"
                }
              },
              "dailyQuotaExceeded": {
                "summary": "[Error] 429 Too Many Requests - Daily quota",
                "value": {
                  "error": "rate_limited",
                  "detail": "daily_quota_exceeded"
                }
              }
            }
          }
        }
      },
      "UpstreamUnavailable": {
        "description": "Upstream service is unavailable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "upstreamUnavailable": {
                "summary": "[Error] 502 Bad Gateway - Upstream unavailable",
                "value": {
                  "error": "upstream_unavailable",
                  "detail": "The upstream service is unavailable"
                }
              }
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal server error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorDetailResponse"
            },
            "examples": {
              "internalError": {
                "summary": "[Error] 500 Internal Server Error - Internal error",
                "value": {
                  "error": "internal_error",
                  "detail": "unexpected"
                }
              }
            }
          }
        }
      }
    }
  }
}
````