Comprehensive machine-readable API documentation covering all REST endpoints exposed by the php-tenant package: - Workspace API (CRUD, switching, session and API key auth) - Entitlement Provisioning API (Blesta: create, suspend, unsuspend, cancel, renew) - Cross-App Entitlement API (check, usage recording, summary) - Entitlement Webhooks API (CRUD, test, secret rotation, circuit breaker, deliveries) Includes full request/response schemas, authentication details, error responses, and pagination structures. Fixes #33 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1830 lines
52 KiB
YAML
1830 lines
52 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: php-tenant API
|
|
description: |
|
|
REST API for the Core PHP Tenant module. Provides workspace management,
|
|
entitlement provisioning, cross-app entitlement checks, and webhook management.
|
|
|
|
## Authentication
|
|
|
|
Endpoints use one of two authentication methods:
|
|
|
|
- **Session auth** (`auth` middleware) — cookie-based session authentication
|
|
for browser clients.
|
|
- **API key auth** (`api.auth` middleware) — pass an API key via
|
|
`Authorization: Bearer hk_xxx` header. Used for server-to-server
|
|
communication and external integrations.
|
|
|
|
Provisioning endpoints (Blesta) require API key auth with
|
|
`entitlements.write` scope.
|
|
|
|
## Rate Limits
|
|
|
|
Provisioning endpoints are rate-limited to 60 requests per minute per API key.
|
|
version: 1.0.0
|
|
contact:
|
|
name: Core Team
|
|
license:
|
|
name: Proprietary
|
|
|
|
servers:
|
|
- url: /api
|
|
description: API base path (session-authenticated workspace routes)
|
|
- url: /api/v1
|
|
description: API v1 base path (cross-app entitlement routes)
|
|
- url: /api/provisioning
|
|
description: Provisioning base path (Blesta entitlement routes)
|
|
|
|
tags:
|
|
- name: Workspaces
|
|
description: Workspace CRUD and switching (session auth)
|
|
- name: Workspaces (API Key)
|
|
description: Read-only workspace access via API key
|
|
- name: Entitlement Provisioning
|
|
description: >-
|
|
Blesta provisioning API for creating, suspending, cancelling, and
|
|
renewing entitlements. Requires API key with entitlements.write scope.
|
|
- name: Cross-App Entitlements
|
|
description: >-
|
|
Cross-application entitlement checks and usage recording.
|
|
Used by external services (e.g. BioHost) to verify feature access.
|
|
- name: Entitlement Webhooks
|
|
description: >-
|
|
Webhook management for entitlement events. Supports CRUD, testing,
|
|
secret rotation, circuit-breaker reset, and delivery history.
|
|
|
|
paths:
|
|
# ==========================================================================
|
|
# Workspaces API (Session Auth)
|
|
# ==========================================================================
|
|
|
|
/workspaces:
|
|
get:
|
|
operationId: listWorkspaces
|
|
summary: List workspaces
|
|
description: List all workspaces the authenticated user has access to.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
description: Filter by workspace type.
|
|
schema:
|
|
type: string
|
|
enum: [personal, team, agency, custom]
|
|
- name: is_active
|
|
in: query
|
|
description: Filter by active status.
|
|
schema:
|
|
type: boolean
|
|
- name: search
|
|
in: query
|
|
description: Search workspaces by name.
|
|
schema:
|
|
type: string
|
|
- name: per_page
|
|
in: query
|
|
description: Results per page (max 100).
|
|
schema:
|
|
type: integer
|
|
default: 25
|
|
maximum: 100
|
|
responses:
|
|
'200':
|
|
description: Paginated list of workspaces.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedWorkspaces'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
|
|
post:
|
|
operationId: createWorkspace
|
|
summary: Create a workspace
|
|
description: Create a new workspace. The authenticated user becomes the owner.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateWorkspaceRequest'
|
|
responses:
|
|
'200':
|
|
description: Workspace created.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
/workspaces/current:
|
|
get:
|
|
operationId: getCurrentWorkspace
|
|
summary: Get current workspace
|
|
description: Get the user's currently active (default) workspace.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
responses:
|
|
'200':
|
|
description: Current workspace.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
description: No workspace found.
|
|
|
|
/workspaces/{workspace}:
|
|
get:
|
|
operationId: getWorkspace
|
|
summary: Get a workspace
|
|
description: Get a single workspace by ID. User must have access.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
responses:
|
|
'200':
|
|
description: Workspace details.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
put:
|
|
operationId: updateWorkspace
|
|
summary: Update a workspace
|
|
description: Update workspace details. Requires owner or admin role.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateWorkspaceRequest'
|
|
responses:
|
|
'200':
|
|
description: Workspace updated.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
delete:
|
|
operationId: deleteWorkspace
|
|
summary: Delete a workspace
|
|
description: >-
|
|
Delete a workspace. Only the owner can delete. Cannot delete the
|
|
user's only workspace.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
responses:
|
|
'204':
|
|
description: Workspace deleted.
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'422':
|
|
description: Cannot delete the user's only workspace.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: cannot_delete
|
|
message:
|
|
type: string
|
|
example: You cannot delete your only workspace.
|
|
|
|
/workspaces/{workspace}/switch:
|
|
post:
|
|
operationId: switchWorkspace
|
|
summary: Switch to a workspace
|
|
description: Set a workspace as the user's default (active) workspace.
|
|
tags: [Workspaces]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
responses:
|
|
'200':
|
|
description: Switched to workspace.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
# ==========================================================================
|
|
# Workspaces API (API Key Auth — read-only)
|
|
# ==========================================================================
|
|
|
|
/workspaces#apikey:
|
|
get:
|
|
operationId: listWorkspacesApiKey
|
|
summary: List workspaces (API key)
|
|
description: List workspaces accessible to the API key holder.
|
|
tags: [Workspaces (API Key)]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [personal, team, agency, custom]
|
|
- name: is_active
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
- name: search
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: per_page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 25
|
|
maximum: 100
|
|
responses:
|
|
'200':
|
|
description: Paginated list of workspaces.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedWorkspaces'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
|
|
/workspaces/current#apikey:
|
|
get:
|
|
operationId: getCurrentWorkspaceApiKey
|
|
summary: Get current workspace (API key)
|
|
description: Get the current workspace for the API key holder.
|
|
tags: [Workspaces (API Key)]
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: Current workspace.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
|
|
/workspaces/{workspace}#apikey:
|
|
get:
|
|
operationId: getWorkspaceApiKey
|
|
summary: Get a workspace (API key)
|
|
description: Get a single workspace by ID via API key.
|
|
tags: [Workspaces (API Key)]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
responses:
|
|
'200':
|
|
description: Workspace details.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
# ==========================================================================
|
|
# Entitlement Provisioning API (Blesta)
|
|
# ==========================================================================
|
|
|
|
/entitlements:
|
|
post:
|
|
operationId: createEntitlement
|
|
summary: Create an entitlement
|
|
description: >-
|
|
Provision a new entitlement for a workspace. Finds or creates the user
|
|
by email, creates a workspace if needed, and provisions the package.
|
|
New users receive an email verification notification.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateEntitlementRequest'
|
|
responses:
|
|
'201':
|
|
description: Entitlement created.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateEntitlementResponse'
|
|
'404':
|
|
description: Package not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
/entitlements/{id}:
|
|
get:
|
|
operationId: getEntitlement
|
|
summary: Get entitlement details
|
|
description: Retrieve full details for an entitlement by ID.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitlementId'
|
|
responses:
|
|
'200':
|
|
description: Entitlement details.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementDetailResponse'
|
|
'404':
|
|
description: Entitlement not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/entitlements/{id}/suspend:
|
|
post:
|
|
operationId: suspendEntitlement
|
|
summary: Suspend an entitlement
|
|
description: Suspend an active entitlement. Optionally provide a reason.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitlementId'
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
reason:
|
|
type: string
|
|
description: Reason for suspension.
|
|
example: Non-payment
|
|
responses:
|
|
'200':
|
|
description: Entitlement suspended.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementActionResponse'
|
|
'404':
|
|
description: Entitlement not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/entitlements/{id}/unsuspend:
|
|
post:
|
|
operationId: unsuspendEntitlement
|
|
summary: Unsuspend an entitlement
|
|
description: Reactivate a suspended entitlement.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitlementId'
|
|
responses:
|
|
'200':
|
|
description: Entitlement reactivated.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementActionResponse'
|
|
'404':
|
|
description: Entitlement not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/entitlements/{id}/cancel:
|
|
post:
|
|
operationId: cancelEntitlement
|
|
summary: Cancel an entitlement
|
|
description: Cancel an entitlement. Optionally provide a reason.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitlementId'
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
reason:
|
|
type: string
|
|
description: Reason for cancellation.
|
|
example: Customer request
|
|
responses:
|
|
'200':
|
|
description: Entitlement cancelled.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementActionResponse'
|
|
'404':
|
|
description: Entitlement not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/entitlements/{id}/renew:
|
|
post:
|
|
operationId: renewEntitlement
|
|
summary: Renew an entitlement
|
|
description: >-
|
|
Renew an entitlement by extending the expiry date and/or updating the
|
|
billing cycle anchor. Cycle-bound boosts from the previous cycle are
|
|
expired.
|
|
tags: [Entitlement Provisioning]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitlementId'
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RenewEntitlementRequest'
|
|
responses:
|
|
'200':
|
|
description: Entitlement renewed.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RenewEntitlementResponse'
|
|
'404':
|
|
description: Entitlement not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
# ==========================================================================
|
|
# Cross-App Entitlement API
|
|
# ==========================================================================
|
|
|
|
/entitlements/check:
|
|
get:
|
|
operationId: checkEntitlement
|
|
summary: Check feature access
|
|
description: >-
|
|
Check whether a user/workspace is entitled to use a specific feature.
|
|
Used by external applications (e.g. BioHost) to verify access before
|
|
performing an action.
|
|
tags: [Cross-App Entitlements]
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: email
|
|
in: query
|
|
required: true
|
|
description: User email to look up the workspace.
|
|
schema:
|
|
type: string
|
|
format: email
|
|
- name: feature
|
|
in: query
|
|
required: true
|
|
description: Feature code to check (e.g. `social.accounts`).
|
|
schema:
|
|
type: string
|
|
- name: quantity
|
|
in: query
|
|
description: Quantity to check against the limit (default 1).
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
responses:
|
|
'200':
|
|
description: Entitlement check result.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementCheckResponse'
|
|
'404':
|
|
description: User or workspace not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
allowed:
|
|
type: boolean
|
|
example: false
|
|
reason:
|
|
type: string
|
|
example: User not found
|
|
feature_code:
|
|
type: string
|
|
example: social.accounts
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
/entitlements/usage:
|
|
post:
|
|
operationId: recordUsage
|
|
summary: Record feature usage
|
|
description: >-
|
|
Record usage for a feature after an action is performed. Used by
|
|
external applications to track consumption against entitlement limits.
|
|
tags: [Cross-App Entitlements]
|
|
security:
|
|
- apiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RecordUsageRequest'
|
|
responses:
|
|
'201':
|
|
description: Usage recorded.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RecordUsageResponse'
|
|
'404':
|
|
description: User or workspace not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
/entitlements/summary:
|
|
get:
|
|
operationId: myEntitlementSummary
|
|
summary: Get my entitlement summary
|
|
description: >-
|
|
Get the usage summary for the authenticated user's default workspace.
|
|
Returns active packages, feature usage by category, and active boosts.
|
|
tags: [Cross-App Entitlements]
|
|
security:
|
|
- sessionAuth: []
|
|
responses:
|
|
'200':
|
|
description: Entitlement summary.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementSummaryResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
description: No workspace found for user.
|
|
|
|
/entitlements/summary/{workspace}:
|
|
get:
|
|
operationId: workspaceEntitlementSummary
|
|
summary: Get workspace entitlement summary
|
|
description: >-
|
|
Get the usage summary for a specific workspace. Returns active
|
|
packages, feature usage grouped by category, and active boosts.
|
|
tags: [Cross-App Entitlements]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- name: workspace
|
|
in: path
|
|
required: true
|
|
description: Workspace ID.
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Entitlement summary.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntitlementSummaryResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
# ==========================================================================
|
|
# Entitlement Webhooks API
|
|
# ==========================================================================
|
|
|
|
/entitlement-webhooks:
|
|
get:
|
|
operationId: listWebhooks
|
|
summary: List webhooks
|
|
description: >-
|
|
List all entitlement webhooks for the current workspace. Supports
|
|
pagination.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- name: workspace_id
|
|
in: query
|
|
description: >-
|
|
Explicit workspace ID. Falls back to the user's default workspace
|
|
if omitted.
|
|
schema:
|
|
type: integer
|
|
- name: per_page
|
|
in: query
|
|
description: Results per page.
|
|
schema:
|
|
type: integer
|
|
default: 25
|
|
responses:
|
|
'200':
|
|
description: Paginated list of webhooks.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedWebhooks'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
|
|
post:
|
|
operationId: createWebhook
|
|
summary: Create a webhook
|
|
description: >-
|
|
Register a new entitlement webhook. The webhook URL is validated
|
|
against SSRF attacks. Returns the webhook secret on creation (the
|
|
only time it is exposed).
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateWebhookRequest'
|
|
responses:
|
|
'201':
|
|
description: Webhook created.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Webhook created successfully
|
|
webhook:
|
|
$ref: '#/components/schemas/Webhook'
|
|
secret:
|
|
type: string
|
|
description: >-
|
|
The webhook signing secret. Only returned on creation.
|
|
example: whsec_a1b2c3d4e5f6...
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'422':
|
|
description: Validation error or invalid webhook URL.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/ValidationErrorBody'
|
|
- type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
error:
|
|
type: string
|
|
example: invalid_webhook_url
|
|
|
|
/entitlement-webhooks/events:
|
|
get:
|
|
operationId: listWebhookEvents
|
|
summary: List available event types
|
|
description: Get the list of event types that webhooks can subscribe to.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
responses:
|
|
'200':
|
|
description: Available event types.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
events:
|
|
type: object
|
|
description: >-
|
|
Map of event codes to human-readable descriptions.
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
limit_warning: Limit warning threshold reached
|
|
limit_reached: Feature limit reached
|
|
package_changed: Package added or changed
|
|
boost_activated: Boost activated
|
|
boost_expired: Boost expired
|
|
|
|
/entitlement-webhooks/{webhook}:
|
|
get:
|
|
operationId: getWebhook
|
|
summary: Get a webhook
|
|
description: >-
|
|
Get webhook details including delivery count and the 10 most recent
|
|
deliveries.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
responses:
|
|
'200':
|
|
description: Webhook details with recent deliveries.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
webhook:
|
|
$ref: '#/components/schemas/Webhook'
|
|
available_events:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
put:
|
|
operationId: updateWebhook
|
|
summary: Update a webhook
|
|
description: Update webhook settings. All fields are optional.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateWebhookRequest'
|
|
responses:
|
|
'200':
|
|
description: Webhook updated.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Webhook updated successfully
|
|
webhook:
|
|
$ref: '#/components/schemas/Webhook'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'422':
|
|
description: Validation error or invalid webhook URL.
|
|
|
|
delete:
|
|
operationId: deleteWebhook
|
|
summary: Delete a webhook
|
|
description: Permanently delete a webhook and its delivery history.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
responses:
|
|
'200':
|
|
description: Webhook deleted.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Webhook deleted successfully
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
|
|
/entitlement-webhooks/{webhook}/test:
|
|
post:
|
|
operationId: testWebhook
|
|
summary: Send a test webhook
|
|
description: >-
|
|
Send a test event to the webhook URL. The URL is re-validated against
|
|
SSRF before the request is made.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
responses:
|
|
'200':
|
|
description: Test delivery result.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Test webhook sent successfully
|
|
delivery:
|
|
$ref: '#/components/schemas/WebhookDelivery'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'422':
|
|
description: Invalid webhook URL (SSRF blocked).
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
error:
|
|
type: string
|
|
example: invalid_webhook_url
|
|
reason:
|
|
type: string
|
|
|
|
/entitlement-webhooks/{webhook}/regenerate-secret:
|
|
post:
|
|
operationId: regenerateWebhookSecret
|
|
summary: Regenerate webhook secret
|
|
description: Generate a new signing secret for the webhook.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
responses:
|
|
'200':
|
|
description: Secret regenerated.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Secret regenerated successfully
|
|
secret:
|
|
type: string
|
|
description: The new webhook signing secret.
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
|
|
/entitlement-webhooks/{webhook}/reset-circuit-breaker:
|
|
post:
|
|
operationId: resetCircuitBreaker
|
|
summary: Reset circuit breaker
|
|
description: >-
|
|
Re-enable a webhook that was automatically disabled after consecutive
|
|
failures (circuit breaker tripped after 5 failures).
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
responses:
|
|
'200':
|
|
description: Circuit breaker reset, webhook re-enabled.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Webhook re-enabled successfully
|
|
webhook:
|
|
$ref: '#/components/schemas/Webhook'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
|
|
/entitlement-webhooks/{webhook}/deliveries:
|
|
get:
|
|
operationId: listWebhookDeliveries
|
|
summary: List webhook deliveries
|
|
description: Get the delivery history for a webhook, newest first.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/WebhookId'
|
|
- name: per_page
|
|
in: query
|
|
description: Results per page.
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
responses:
|
|
'200':
|
|
description: Paginated delivery history.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedDeliveries'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
|
|
/entitlement-webhooks/deliveries/{delivery}/retry:
|
|
post:
|
|
operationId: retryDelivery
|
|
summary: Retry a failed delivery
|
|
description: >-
|
|
Retry a previously failed webhook delivery. Cannot retry a delivery
|
|
that already succeeded.
|
|
tags: [Entitlement Webhooks]
|
|
security:
|
|
- sessionAuth: []
|
|
parameters:
|
|
- name: delivery
|
|
in: path
|
|
required: true
|
|
description: Delivery ID.
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Retry result.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Delivery retried successfully
|
|
delivery:
|
|
$ref: '#/components/schemas/WebhookDelivery'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthenticated'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'422':
|
|
description: Cannot retry a successful delivery.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Cannot retry a successful delivery
|
|
|
|
# ==============================================================================
|
|
# Components
|
|
# ==============================================================================
|
|
|
|
components:
|
|
securitySchemes:
|
|
sessionAuth:
|
|
type: apiKey
|
|
in: cookie
|
|
name: session
|
|
description: Cookie-based session authentication.
|
|
|
|
apiKeyAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: >-
|
|
API key authentication. Pass your key as a Bearer token
|
|
(`Authorization: Bearer hk_xxx`).
|
|
|
|
parameters:
|
|
WorkspaceId:
|
|
name: workspace
|
|
in: path
|
|
required: true
|
|
description: Workspace ID.
|
|
schema:
|
|
type: integer
|
|
|
|
EntitlementId:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
description: Entitlement (workspace package) ID.
|
|
schema:
|
|
type: integer
|
|
|
|
WebhookId:
|
|
name: webhook
|
|
in: path
|
|
required: true
|
|
description: Webhook ID.
|
|
schema:
|
|
type: integer
|
|
|
|
responses:
|
|
Unauthenticated:
|
|
description: Authentication required.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: Unauthenticated
|
|
|
|
Forbidden:
|
|
description: Insufficient permissions.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: You do not have permission to perform this action.
|
|
|
|
NotFound:
|
|
description: Resource not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Not found
|
|
|
|
ValidationError:
|
|
description: Validation failed.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ValidationErrorBody'
|
|
|
|
schemas:
|
|
# ------------------------------------------------------------------
|
|
# Workspace schemas
|
|
# ------------------------------------------------------------------
|
|
|
|
WorkspaceResource:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: "Acme Corp"
|
|
slug:
|
|
type: string
|
|
example: acme-corp-a1b2c3
|
|
icon:
|
|
type: string
|
|
nullable: true
|
|
example: fa-building
|
|
color:
|
|
type: string
|
|
nullable: true
|
|
example: "#3b82f6"
|
|
description:
|
|
type: string
|
|
nullable: true
|
|
example: Main workspace for Acme Corp
|
|
type:
|
|
type: string
|
|
enum: [personal, team, agency, custom]
|
|
example: custom
|
|
is_active:
|
|
type: boolean
|
|
example: true
|
|
users_count:
|
|
type: integer
|
|
example: 5
|
|
bio_pages_count:
|
|
type: integer
|
|
example: 12
|
|
|
|
CreateWorkspaceRequest:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
example: My Workspace
|
|
slug:
|
|
type: string
|
|
maxLength: 100
|
|
description: >-
|
|
URL-friendly identifier. Auto-generated from name if omitted.
|
|
example: my-workspace
|
|
icon:
|
|
type: string
|
|
maxLength: 50
|
|
nullable: true
|
|
color:
|
|
type: string
|
|
maxLength: 20
|
|
nullable: true
|
|
description:
|
|
type: string
|
|
maxLength: 500
|
|
nullable: true
|
|
type:
|
|
type: string
|
|
enum: [personal, team, agency, custom]
|
|
default: custom
|
|
|
|
UpdateWorkspaceRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
slug:
|
|
type: string
|
|
maxLength: 100
|
|
icon:
|
|
type: string
|
|
maxLength: 50
|
|
nullable: true
|
|
color:
|
|
type: string
|
|
maxLength: 20
|
|
nullable: true
|
|
description:
|
|
type: string
|
|
maxLength: 500
|
|
nullable: true
|
|
is_active:
|
|
type: boolean
|
|
|
|
PaginatedWorkspaces:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WorkspaceResource'
|
|
links:
|
|
$ref: '#/components/schemas/PaginationLinks'
|
|
meta:
|
|
$ref: '#/components/schemas/PaginationMeta'
|
|
|
|
# ------------------------------------------------------------------
|
|
# Entitlement Provisioning schemas
|
|
# ------------------------------------------------------------------
|
|
|
|
CreateEntitlementRequest:
|
|
type: object
|
|
required: [email, name, product_code]
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
description: Client email. User is found or created by this address.
|
|
example: client@example.com
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
description: Client name. Used when creating a new user.
|
|
example: Jane Doe
|
|
product_code:
|
|
type: string
|
|
description: Package code to provision.
|
|
example: starter-plan
|
|
billing_cycle_anchor:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: Billing cycle anchor date (ISO 8601).
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: Entitlement expiry date (ISO 8601).
|
|
blesta_service_id:
|
|
type: string
|
|
nullable: true
|
|
description: External Blesta service ID for cross-referencing.
|
|
|
|
CreateEntitlementResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
entitlement_id:
|
|
type: integer
|
|
example: 42
|
|
workspace_id:
|
|
type: integer
|
|
example: 7
|
|
workspace_slug:
|
|
type: string
|
|
example: jane-doe-a1b2c3
|
|
package:
|
|
type: string
|
|
example: starter-plan
|
|
status:
|
|
type: string
|
|
enum: [active, suspended, cancelled, expired]
|
|
example: active
|
|
|
|
EntitlementDetailResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
entitlement:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 42
|
|
workspace_id:
|
|
type: integer
|
|
example: 7
|
|
workspace_slug:
|
|
type: string
|
|
example: jane-doe-a1b2c3
|
|
package_code:
|
|
type: string
|
|
example: starter-plan
|
|
package_name:
|
|
type: string
|
|
example: Starter Plan
|
|
status:
|
|
type: string
|
|
enum: [active, suspended, cancelled, expired]
|
|
example: active
|
|
starts_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
billing_cycle_anchor:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
blesta_service_id:
|
|
type: string
|
|
nullable: true
|
|
|
|
EntitlementActionResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
entitlement_id:
|
|
type: integer
|
|
example: 42
|
|
status:
|
|
type: string
|
|
enum: [active, suspended, cancelled, expired]
|
|
|
|
RenewEntitlementRequest:
|
|
type: object
|
|
properties:
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: New expiry date (ISO 8601).
|
|
billing_cycle_anchor:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: New billing cycle anchor (ISO 8601).
|
|
|
|
RenewEntitlementResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
entitlement_id:
|
|
type: integer
|
|
example: 42
|
|
status:
|
|
type: string
|
|
enum: [active, suspended, cancelled, expired]
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
|
|
# ------------------------------------------------------------------
|
|
# Cross-App Entitlement schemas
|
|
# ------------------------------------------------------------------
|
|
|
|
EntitlementCheckResponse:
|
|
type: object
|
|
properties:
|
|
allowed:
|
|
type: boolean
|
|
description: Whether the requested action is permitted.
|
|
example: true
|
|
limit:
|
|
type: integer
|
|
nullable: true
|
|
description: Total limit for the feature (null if unlimited).
|
|
example: 10
|
|
used:
|
|
type: integer
|
|
description: Current usage count.
|
|
example: 3
|
|
remaining:
|
|
type: integer
|
|
nullable: true
|
|
description: Remaining quota (null if unlimited).
|
|
example: 7
|
|
unlimited:
|
|
type: boolean
|
|
description: Whether the feature has no limit.
|
|
example: false
|
|
usage_percentage:
|
|
type: number
|
|
format: float
|
|
description: Usage as a percentage of the limit (0-100).
|
|
example: 30.0
|
|
feature_code:
|
|
type: string
|
|
example: social.accounts
|
|
workspace_id:
|
|
type: integer
|
|
example: 7
|
|
|
|
RecordUsageRequest:
|
|
type: object
|
|
required: [email, feature]
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
description: User email to look up the workspace.
|
|
example: client@example.com
|
|
feature:
|
|
type: string
|
|
description: Feature code to record usage for.
|
|
example: social.posts.scheduled
|
|
quantity:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
description: Number of units consumed.
|
|
metadata:
|
|
type: object
|
|
nullable: true
|
|
description: Arbitrary metadata to attach to the usage record.
|
|
additionalProperties: true
|
|
example:
|
|
post_id: "abc123"
|
|
platform: twitter
|
|
|
|
RecordUsageResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
usage_record_id:
|
|
type: integer
|
|
example: 891
|
|
feature_code:
|
|
type: string
|
|
example: social.posts.scheduled
|
|
quantity:
|
|
type: integer
|
|
example: 1
|
|
|
|
EntitlementSummaryResponse:
|
|
type: object
|
|
properties:
|
|
workspace_id:
|
|
type: integer
|
|
example: 7
|
|
packages:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
example: starter-plan
|
|
name:
|
|
type: string
|
|
example: Starter Plan
|
|
status:
|
|
type: string
|
|
enum: [active, suspended, cancelled, expired]
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
features:
|
|
type: object
|
|
description: >-
|
|
Feature usage grouped by category. Each category key maps to an
|
|
array of feature objects.
|
|
additionalProperties:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
example: social.accounts
|
|
name:
|
|
type: string
|
|
example: Social Accounts
|
|
limit:
|
|
type: integer
|
|
nullable: true
|
|
used:
|
|
type: integer
|
|
remaining:
|
|
type: integer
|
|
nullable: true
|
|
unlimited:
|
|
type: boolean
|
|
percentage:
|
|
type: number
|
|
format: float
|
|
example:
|
|
social:
|
|
- code: social.accounts
|
|
name: Social Accounts
|
|
limit: 10
|
|
used: 3
|
|
remaining: 7
|
|
unlimited: false
|
|
percentage: 30.0
|
|
boosts:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
feature:
|
|
type: string
|
|
example: social.accounts
|
|
value:
|
|
type: integer
|
|
example: 5
|
|
type:
|
|
type: string
|
|
example: add
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
|
|
# ------------------------------------------------------------------
|
|
# Webhook schemas
|
|
# ------------------------------------------------------------------
|
|
|
|
Webhook:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
uuid:
|
|
type: string
|
|
format: uuid
|
|
workspace_id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
example: My Webhook
|
|
url:
|
|
type: string
|
|
format: uri
|
|
example: https://example.com/webhooks/entitlements
|
|
events:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- limit_warning
|
|
- limit_reached
|
|
- package_changed
|
|
- boost_activated
|
|
- boost_expired
|
|
is_active:
|
|
type: boolean
|
|
example: true
|
|
max_attempts:
|
|
type: integer
|
|
example: 3
|
|
last_delivery_status:
|
|
type: string
|
|
enum: [pending, success, failed]
|
|
nullable: true
|
|
last_triggered_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
failure_count:
|
|
type: integer
|
|
example: 0
|
|
metadata:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
deliveries_count:
|
|
type: integer
|
|
description: Total number of deliveries (when loaded).
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
CreateWebhookRequest:
|
|
type: object
|
|
required: [name, url, events]
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
example: Production Webhook
|
|
url:
|
|
type: string
|
|
format: uri
|
|
maxLength: 2048
|
|
description: >-
|
|
HTTPS endpoint URL. Validated against SSRF (internal network
|
|
addresses are rejected).
|
|
example: https://example.com/webhooks/entitlements
|
|
events:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
type: string
|
|
enum:
|
|
- limit_warning
|
|
- limit_reached
|
|
- package_changed
|
|
- boost_activated
|
|
- boost_expired
|
|
example: [limit_warning, limit_reached]
|
|
secret:
|
|
type: string
|
|
minLength: 32
|
|
nullable: true
|
|
description: >-
|
|
Custom signing secret. If omitted, one is auto-generated.
|
|
metadata:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
|
|
UpdateWebhookRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
url:
|
|
type: string
|
|
format: uri
|
|
maxLength: 2048
|
|
events:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
type: string
|
|
enum:
|
|
- limit_warning
|
|
- limit_reached
|
|
- package_changed
|
|
- boost_activated
|
|
- boost_expired
|
|
is_active:
|
|
type: boolean
|
|
max_attempts:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 10
|
|
metadata:
|
|
type: object
|
|
nullable: true
|
|
additionalProperties: true
|
|
|
|
WebhookDelivery:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
uuid:
|
|
type: string
|
|
format: uuid
|
|
webhook_id:
|
|
type: integer
|
|
event:
|
|
type: string
|
|
example: limit_warning
|
|
attempts:
|
|
type: integer
|
|
example: 1
|
|
status:
|
|
type: string
|
|
enum: [pending, success, failed]
|
|
http_status:
|
|
type: integer
|
|
nullable: true
|
|
example: 200
|
|
resend_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
resent_manually:
|
|
type: boolean
|
|
example: false
|
|
payload:
|
|
type: object
|
|
description: The JSON payload that was sent.
|
|
response:
|
|
type: object
|
|
nullable: true
|
|
description: The response body received from the endpoint.
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
PaginatedWebhooks:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Webhook'
|
|
links:
|
|
$ref: '#/components/schemas/PaginationLinks'
|
|
meta:
|
|
$ref: '#/components/schemas/PaginationMeta'
|
|
|
|
PaginatedDeliveries:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WebhookDelivery'
|
|
links:
|
|
$ref: '#/components/schemas/PaginationLinks'
|
|
meta:
|
|
$ref: '#/components/schemas/PaginationMeta'
|
|
|
|
# ------------------------------------------------------------------
|
|
# Shared schemas
|
|
# ------------------------------------------------------------------
|
|
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: false
|
|
error:
|
|
type: string
|
|
example: Resource not found
|
|
|
|
ValidationErrorBody:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: The given data was invalid.
|
|
errors:
|
|
type: object
|
|
description: >-
|
|
Field-level validation errors. Keys are field names, values are
|
|
arrays of error messages.
|
|
additionalProperties:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example:
|
|
email:
|
|
- The email field is required.
|
|
name:
|
|
- The name field is required.
|
|
|
|
PaginationLinks:
|
|
type: object
|
|
properties:
|
|
first:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
last:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
prev:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
next:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
|
|
PaginationMeta:
|
|
type: object
|
|
properties:
|
|
current_page:
|
|
type: integer
|
|
from:
|
|
type: integer
|
|
nullable: true
|
|
last_page:
|
|
type: integer
|
|
per_page:
|
|
type: integer
|
|
to:
|
|
type: integer
|
|
nullable: true
|
|
total:
|
|
type: integer
|