openapi: 3.2.0 info: title: Compabase Watchlist API version: 1.0.0 description: '### Introduction Versioned JSON API for Polish company data: KRS search and full profiles, CEIDG (sole proprietors) by NIP, financial statements and document inventory, peer statistics, company connections, news/UGC, Warsaw Stock Exchange (GPW) listings, and watchlist management.' servers: - url: https://compabase.com/api/v1 description: Full URL tags: - name: Watchlist paths: /watchlist: get: tags: - Watchlist summary: List watchlist description: 'Lists companies on the watchlist of the **user account linked to the API key**. Requires `user_id` on the key.' security: - ApiKeyAuth: [] - BearerAuth: [] parameters: - name: limit in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 20 - name: offset in: query required: false schema: type: integer minimum: 0 default: 0 responses: '200': description: Watchlist page. content: application/json: schema: type: object example: data: [] pagination: total: 0 hasMore: false '401': $ref: '#/components/responses/Unauthorized' '403': description: API key is not linked to a user account. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '429': $ref: '#/components/responses/TooManyRequests' operationId: getWatchlist x-operation-id-source: derived /watchlist/krs/{krs}: post: tags: - Watchlist summary: Add company to watchlist description: 'Adds a company to the **watchlist of the user account linked to the API key**. The company is identified by **KRS** (Polish court registry number). Digits only; leading zeros are optional (normalized to 10 digits server-side). If the company is already on the watchlist, the response returns `already_following: true` and does not create a duplicate entry. Requires an API key associated with a Compabase portal user account (`user_id` on the key).' security: - ApiKeyAuth: [] - BearerAuth: [] parameters: - name: krs in: path required: true schema: type: string description: KRS input is normalized by stripping non-digits and left-padding to 10 digits. After normalization, KRS must contain exactly 10 digits; otherwise request fails with `400 INVALID_KRS`. example: 0000028860 responses: '200': description: Company added to watchlist (or already followed). content: application/json: schema: $ref: '#/components/schemas/WatchlistAddResponse' examples: added: summary: Newly added value: krs: 0000028860 entity_id: ad2ae683-ccbd-49c6-a85c-648024435cb5 already_following: false created_at: '2026-05-20T14:30:00Z' alreadyFollowing: summary: Already on watchlist value: krs: 0000028860 entity_id: ad2ae683-ccbd-49c6-a85c-648024435cb5 already_following: true created_at: '2026-05-15T09:00:00Z' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': description: API key is not linked to a user account. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: code: INVALID_API_KEY message: This API key is not linked to a user account. '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' operationId: postWatchlistKrsByKrs x-operation-id-source: derived delete: tags: - Watchlist summary: Remove company from watchlist description: 'Removes a KRS company from the watchlist of the user linked to the API key. Idempotent: `removed: false` when the company was not on the list.' security: - ApiKeyAuth: [] - BearerAuth: [] parameters: - name: krs in: path required: true schema: type: string example: 0000028860 responses: '200': description: Removal result. content: application/json: schema: type: object example: krs: 0000028860 entity_id: ad2ae683-ccbd-49c6-a85c-648024435cb5 removed: true '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': description: API key is not linked to a user account. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' operationId: deleteWatchlistKrsByKrs x-operation-id-source: derived components: responses: BadRequest: description: Invalid request parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: invalidKrs: summary: Invalid KRS value value: statusCode: 400 statusMessage: Invalid krs message: Invalid krs data: error: code: INVALID_KRS message: After normalization, KRS must contain exactly 10 digits. details: parameter: krs invalidCursor: summary: Invalid cursor format value: statusCode: 400 statusMessage: Invalid cursor message: Invalid cursor data: error: code: INVALID_CURSOR message: Cursor must be a valid UUID. details: parameter: cursor invalidRange: summary: Invalid numeric range value: statusCode: 400 statusMessage: Invalid range message: Invalid range data: error: code: INVALID_RANGE message: revenue_min cannot be greater than revenue_max. details: parameter: revenue_min,revenue_max NotFound: description: Resource not found. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: statusCode: 404 statusMessage: Not Found message: Not Found data: error: code: NOT_FOUND message: Company not found. Unauthorized: description: Missing, invalid, or revoked API key. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: statusCode: 401 statusMessage: Unauthorized message: Unauthorized data: message: Missing or invalid API key. TooManyRequests: description: Monthly quota exceeded for this API key. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: statusCode: 429 statusMessage: Too Many Requests message: Too Many Requests data: error: code: QUOTA_EXCEEDED message: Monthly quota exceeded for this API key. schemas: ErrorResponse: type: object required: - statusCode - statusMessage - message properties: statusCode: type: integer description: HTTP status code. statusMessage: type: string description: HTTP status text. message: type: string description: Short error summary (same as statusMessage for most errors). data: type: object description: Domain error payload set by the handler. properties: message: type: string description: Human-readable message (used by 401 responses). error: type: object description: Structured domain error (used by 400/404/429 responses). properties: code: type: string description: Machine-readable domain error code. enum: - INVALID_KRS - INVALID_NIP - INVALID_CURSOR - INVALID_RANGE - INVALID_PARAMETER - CONFLICTING_PARAMETERS - INVALID_BOOLEAN - INVALID_KEYWORDS - INVALID_API_KEY - UNAUTHORIZED - NOT_FOUND - QUOTA_EXCEEDED message: type: string details: type: object additionalProperties: true WatchlistAddResponse: type: object required: - krs - entity_id - already_following properties: krs: type: string description: Normalized 10-digit KRS. example: 0000028860 entity_id: type: string format: uuid description: Internal company identifier. already_following: type: boolean description: True if the company was already on the watchlist before this request. created_at: type: string format: date-time nullable: true description: When the watchlist entry was created. Null when already_following is true and the original timestamp is unavailable. securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-API-Key BearerAuth: type: http scheme: bearer