{ "components": { "responses": { "BadRequest": { "content": { "application/json": { "examples": { "validation_error": { "value": { "code": "invalid_argument", "details": [ { "param": "title", "reason": "missing_required_field", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Document title cannot be empty" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Invalid request parameters" }, "Conflict": { "content": { "application/json": { "examples": { "already_exists": { "value": { "code": "already_exists", "details": [ { "reason": "resource_already_exists", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Document already exists" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Resource already exists" }, "Forbidden": { "content": { "application/json": { "examples": { "insufficient_permissions": { "value": { "code": "permission_denied", "details": [ { "reason": "insufficient_permissions", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Permission denied" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Authorization failed - valid key but insufficient permissions" }, "InternalServerError": { "content": { "application/json": { "examples": { "internal_error": { "value": { "code": "internal", "details": [ { "reason": "internal_error", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "An internal error occurred" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Internal server error" }, "NotFound": { "content": { "application/json": { "examples": { "resource_not_found": { "value": { "code": "not_found", "details": [ { "reason": "resource_not_found", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Document not found" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Resource not found" }, "RateLimitExceeded": { "content": { "application/json": { "examples": { "rate_limit": { "value": { "code": "resource_exhausted", "details": [ { "reason": "rate_limit_exceeded", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Too many requests" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Too many requests", "headers": { "X-RateLimit-Limit": { "description": "Request limit per minute", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Remaining requests in current window", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp when rate limit resets", "schema": { "type": "integer" } } } }, "ServiceUnavailable": { "content": { "application/json": { "examples": { "unavailable": { "value": { "code": "unavailable", "details": [ { "reason": "service_unavailable", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "Service temporarily unavailable" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Service temporarily unavailable" }, "Unauthorized": { "content": { "application/json": { "examples": { "missing_key": { "value": { "code": "unauthenticated", "details": [ { "reason": "missing_api_key", "request_id": "req_01arwx4k8xrgqskvxq69gdn019" } ], "message": "API key is required" } } }, "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }, "description": "Authentication failed - missing or invalid API key" } }, "schemas": { "APIKeyQuota": { "additionalProperties": false, "description": "APIKeyQuota represents per-key quota status.", "properties": { "api_key_id": { "description": "The API key ID.", "example": "key_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" }, "current_usage": { "description": "Current usage for this key in the billing period.", "format": "int32", "title": "current_usage", "type": "integer" }, "is_exceeded": { "description": "Whether this key's quota is exceeded. Only true when limit is set and exceeded.", "title": "is_exceeded", "type": "boolean" }, "limit": { "description": "The configured limit for this key. Not set means no explicit key limit.", "exclusiveMinimum": 0, "format": "int32", "nullable": true, "title": "limit", "type": "integer" }, "remaining": { "description": "Remaining requests for this key. Only meaningful when limit is set.", "format": "int32", "title": "remaining", "type": "integer" } }, "title": "APIKeyQuota", "type": "object" }, "AcceptOrganizationInviteRequest": { "additionalProperties": false, "description": "AcceptOrganizationInviteRequest contains the token to accept an invitation.", "properties": { "organization_id": { "description": "Organization the invitation belongs to (for validation).\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "token": { "description": "The invitation token from the email link.", "maxLength": 128, "title": "token", "type": "string" } }, "required": [ "organization_id", "token" ], "title": "AcceptOrganizationInviteRequest", "type": "object" }, "AcceptOrganizationInviteResponse": { "additionalProperties": false, "description": "AcceptOrganizationInviteResponse contains the organization the user joined.", "properties": { "organization": { "$ref": "#/components/schemas/Organization", "description": "The organization the user is now a member of.", "title": "organization" } }, "required": [ "organization" ], "title": "AcceptOrganizationInviteResponse", "type": "object" }, "AccessLevel": { "enum": [ "private", "organization", "public" ] }, "AddOrganizationMemberRequest": { "additionalProperties": false, "description": "AddOrganizationMemberRequest identifies a user to add as a member.", "properties": { "organization_id": { "description": "Organization to add the member to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "role": { "description": "Role for the new member. Cannot be UNSPECIFIED or OWNER.", "enum": [ "admin", "member" ], "example": "member", "title": "role", "type": "string" }, "user_id": { "description": "User account ID of the member to add.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } }, "required": [ "organization_id", "user_id", "role" ], "title": "AddOrganizationMemberRequest", "type": "object" }, "AddOrganizationMemberResponse": { "additionalProperties": false, "description": "AddOrganizationMemberResponse contains the added member.", "properties": { "member": { "$ref": "#/components/schemas/OrganizationMember", "description": "The newly added organization member.", "title": "member" } }, "required": [ "member" ], "title": "AddOrganizationMemberResponse", "type": "object" }, "ApiKey": { "additionalProperties": false, "description": "ApiKey represents an authentication credential for programmatic API access.", "properties": { "created_at": { "description": "Timestamp when the key was created.", "format": "date-time", "title": "created_at", "type": "string" }, "expires_at": { "description": "Expiration timestamp. If set, the key becomes invalid after this time.", "format": "date-time", "title": "expires_at", "type": "string" }, "id": { "description": "Unique ID for the API key.\n Pattern: key_[0-9a-hjkmnp-tv-z]{26}", "example": "key_01jd4h5mck9gq6zrp8bn2t4w3x", "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "is_active": { "description": "Whether the key is currently active (not revoked and not expired).\n Computed: is_active = (revoked_at == null) \u0026\u0026 (expires_at == null || expires_at \u003e now())", "readOnly": true, "title": "is_active", "type": "boolean" }, "key_prefix": { "description": "Truncated key prefix for identification in UI (e.g., \"ffy_prod_01jd4h5...\").\n Shows the first 16 characters for better uniqueness while maintaining security.", "example": "ffy_prod_01jd4h5...", "maxLength": 20, "minLength": 16, "title": "key_prefix", "type": "string" }, "name": { "description": "Human-readable name for the key (e.g., \"Production\", \"Staging\").", "example": "Production", "maxLength": 63, "minLength": 1, "title": "name", "type": "string" }, "organization_id": { "description": "ID of the organization this key belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "revoked_at": { "description": "Timestamp when the key was revoked. Null if the key has not been revoked.", "format": "date-time", "readOnly": true, "title": "revoked_at", "type": "string" } }, "required": [ "id", "name", "organization_id", "created_at", "is_active", "key_prefix" ], "title": "ApiKey", "type": "object" }, "AttachPolicyRequest": { "additionalProperties": false, "description": "AttachPolicyRequest specifies a policy to attach to a document.", "properties": { "document_id": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "policy_id": { "description": "Policy ID to attach.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^pol_[0-9a-hjkmnp-tv-z]{26}$", "title": "policy_id", "type": "string" } }, "required": [ "policy_id" ], "title": "AttachPolicyRequest", "type": "object" }, "CreateApiKeyRequest": { "additionalProperties": false, "description": "CreateApiKeyRequest contains the data needed to create a new API key.", "properties": { "expires_at": { "description": "Expiration timestamp. If not set, the key does not expire.\n When set, must be in the future and within 1 year.\n Security note: Keys without expiration should be rotated periodically.\ntimestamp.gt_now = true\ntimestamp.within = 8760h0m0s\n", "format": "date-time", "title": "expires_at", "type": "string" }, "name": { "description": "Human-readable name for the key (e.g., \"Production\", \"Staging\").", "maxLength": 63, "minLength": 1, "title": "name", "type": "string" }, "organization_id": { "description": "Organization ID to create the key for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "required": [ "organization_id", "name" ], "title": "CreateApiKeyRequest", "type": "object" }, "CreateApiKeyResponse": { "additionalProperties": false, "description": "CreateApiKeyResponse contains the newly created API key and its secret.", "properties": { "api_key": { "$ref": "#/components/schemas/ApiKey", "description": "The created API key metadata.", "title": "api_key" }, "secret": { "description": "The API key secret. This is only returned once and cannot be retrieved later.\n Format: ffy_{env}_{base32_uuid7}{base62_random}\n - env: \"prod\" or \"test\"\n - base32_uuid7: 26 chars (TypeID base32 alphabet: 0-9a-hjkmnp-tv-z)\n - base62_random: 43 chars (0-9A-Za-z)\n Store this value securely - it will not be shown again.\n SECURITY WARNING: This field must NEVER be logged. Handlers must redact secrets from all logs.", "example": "ffy_prod_01h2xcejqtf2nbrexx3vqjhp41KJ8f3mNpQrStUvWxYz0123456789ABCDEFGHIJKLmNo", "minLength": 78, "pattern": "^ffy_(prod|test)_[A-Za-z0-9]+$", "title": "secret", "type": "string" } }, "required": [ "api_key", "secret" ], "title": "CreateApiKeyResponse", "type": "object" }, "CreateDocumentRequest": { "additionalProperties": false, "description": "CreateDocumentRequest contains the file and metadata for creating a document.", "properties": { "access_level": { "$ref": "#/components/schemas/AccessLevel", "description": "Document access level. Defaults to organization if user belongs to an org, otherwise private.", "nullable": true, "title": "access_level" }, "description": { "description": "Optional document description.", "maxLength": 2000, "nullable": true, "title": "description", "type": "string" }, "document_id": { "description": "Pre-generated document ID (set by server)", "readOnly": true, "title": "document_id", "type": "string" }, "payload": { "description": "PDF file to upload", "format": "binary", "title": "payload", "type": "string" }, "payload_key": { "description": "Storage key for uploaded file (set by server)", "readOnly": true, "title": "payload_key", "type": "string" }, "title": { "description": "Document title.", "maxLength": 255, "minLength": 1, "title": "title", "type": "string" }, "version_id": { "description": "Pre-generated version ID (set by server)", "readOnly": true, "title": "version_id", "type": "string" } }, "required": [ "payload", "title" ], "title": "CreateDocumentRequest", "type": "object" }, "CreateDocumentResponse": { "additionalProperties": false, "description": "CreateDocumentResponse contains the newly created document.", "properties": { "document": { "$ref": "#/components/schemas/Document", "description": "The created document.", "title": "document" } }, "required": [ "document" ], "title": "CreateDocumentResponse", "type": "object" }, "CreateOrganizationInviteRequest": { "additionalProperties": false, "description": "CreateOrganizationInviteRequest contains the data needed to create an invitation.", "properties": { "email": { "description": "Email address of the recipient.", "format": "email", "title": "email", "type": "string" }, "idempotency_key": { "description": "Reserved for future use. Currently, idempotency is based on email matching:\n if a PENDING invitation exists for the same email in this organization,\n that invitation is resent rather than creating a duplicate.", "maxLength": 255, "nullable": true, "title": "idempotency_key", "type": "string" }, "message": { "description": "Optional custom message from the sender (max 2000 bytes to support ~500 multibyte characters).", "maxLength": 2000, "nullable": true, "title": "message", "type": "string" }, "organization_id": { "description": "Organization to invite the user to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "required": [ "organization_id", "email" ], "title": "CreateOrganizationInviteRequest", "type": "object" }, "CreateOrganizationInviteResponse": { "additionalProperties": false, "description": "CreateOrganizationInviteResponse contains the created invitation.", "properties": { "invite": { "$ref": "#/components/schemas/OrganizationInvite", "description": "The created (or existing) invitation.", "title": "invite" } }, "required": [ "invite" ], "title": "CreateOrganizationInviteResponse", "type": "object" }, "CreateOrganizationRequest": { "additionalProperties": false, "description": "CreateOrganizationRequest contains the data needed to create a new organization.", "properties": { "name": { "description": "Human-readable organization name.", "maxLength": 255, "minLength": 1, "title": "name", "type": "string" }, "owner_user_id": { "description": "Owner user ID. If not provided, the authenticated user becomes the owner.\n Authorization: Specifying a different user requires system maintainer role.\n Required when the caller is a service account (service accounts cannot own organizations).\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "nullable": true, "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "owner_user_id", "type": "string" } }, "required": [ "name" ], "title": "CreateOrganizationRequest", "type": "object" }, "CreateOrganizationResponse": { "additionalProperties": false, "description": "CreateOrganizationResponse contains the newly created organization.", "properties": { "organization": { "$ref": "#/components/schemas/Organization", "description": "The created organization.", "title": "organization" } }, "required": [ "organization" ], "title": "CreateOrganizationResponse", "type": "object" }, "CreateVersionRequest": { "additionalProperties": false, "description": "CreateVersionRequest contains the file and metadata for creating a version.", "properties": { "description": { "description": "Description of changes in this version.", "nullable": true, "title": "description", "type": "string" }, "payload": { "description": "PDF file for new version", "format": "binary", "title": "payload", "type": "string" }, "payload_key": { "description": "Storage key for uploaded file (set by server)", "readOnly": true, "title": "payload_key", "type": "string" }, "title": { "description": "Optional version title.", "maxLength": 255, "nullable": true, "title": "title", "type": "string" }, "version_id": { "description": "Pre-generated version ID (set by server)", "readOnly": true, "title": "version_id", "type": "string" } }, "required": [ "payload" ], "title": "CreateVersionRequest", "type": "object" }, "DailyUsage": { "additionalProperties": false, "description": "DailyUsage represents usage for a single day.", "properties": { "date": { "description": "The date (YYYY-MM-DD format).", "example": "2026-01-15", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "title": "date", "type": "string" }, "request_count": { "description": "Request count for this day.", "format": "int32", "title": "request_count", "type": "integer" } }, "title": "DailyUsage", "type": "object" }, "DeleteAPIKeyQuotaRequest": { "additionalProperties": false, "description": "DeleteAPIKeyQuotaRequest removes a per-key quota.", "properties": { "api_key_id": { "description": "The API key ID (required).", "minLength": 1, "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" }, "organization_id": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "DeleteAPIKeyQuotaRequest", "type": "object" }, "DeleteAPIKeyQuotaResponse": { "additionalProperties": false, "description": "DeleteAPIKeyQuotaResponse confirms deletion. Empty response - success indicated by no error.", "title": "DeleteAPIKeyQuotaResponse", "type": "object" }, "DeleteOrganizationQuotaRequest": { "additionalProperties": false, "description": "DeleteOrganizationQuotaRequest is a request to delete quota configuration.", "properties": { "organization_id": { "description": "The organization ID (required).", "minLength": 1, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "DeleteOrganizationQuotaRequest", "type": "object" }, "DeleteOrganizationQuotaResponse": { "additionalProperties": false, "description": "DeleteOrganizationQuotaResponse confirms deletion. Empty response - success indicated by no error.", "title": "DeleteOrganizationQuotaResponse", "type": "object" }, "DetachPolicyRequest": { "additionalProperties": false, "description": "DetachPolicyRequest identifies a policy to detach from a document.", "properties": { "document_id": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "policy_id": { "description": "Policy ID to detach.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^pol_[0-9a-hjkmnp-tv-z]{26}$", "title": "policy_id", "type": "string" } }, "title": "DetachPolicyRequest", "type": "object" }, "Document": { "additionalProperties": false, "description": "Document represents a Factify document.", "properties": { "access_level": { "$ref": "#/components/schemas/AccessLevel", "description": "Document access level.", "title": "access_level" }, "created_at": { "description": "Timestamp when document was created.", "format": "date-time", "title": "created_at", "type": "string" }, "created_by": { "$ref": "#/components/schemas/Subject", "description": "Subject who created the document.", "title": "created_by" }, "current_version": { "$ref": "#/components/schemas/VersionRef", "description": "Reference to the current version, if any.", "nullable": true, "title": "current_version" }, "description": { "description": "Optional document description.", "example": "Quarterly financial report for Q4 2024", "maxLength": 2000, "nullable": true, "title": "description", "type": "string" }, "id": { "description": "Unique ID for the document.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "example": "doc_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "processing_status": { "$ref": "#/components/schemas/ProcessingStatus", "description": "Processing status.", "title": "processing_status" }, "title": { "description": "Document title.", "example": "Q4 2024 Financial Report", "maxLength": 255, "minLength": 1, "title": "title", "type": "string" }, "url": { "description": "URL for accessing the document on Factify.", "example": "https://app.factify.com/d/01h2xcejqtf2nbrexx3vqjhp41", "format": "uri", "title": "url", "type": "string" } }, "required": [ "id", "url", "title", "access_level", "processing_status", "created_at", "created_by" ], "title": "Document", "type": "object" }, "DocumentPolicy": { "additionalProperties": false, "description": "DocumentPolicy represents a policy attached to a document.", "properties": { "attached_at": { "description": "Timestamp when policy was attached.", "format": "date-time", "title": "attached_at", "type": "string" }, "document_id": { "description": "Document ID this policy is attached to.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "example": "doc_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "policy": { "$ref": "#/components/schemas/Policy", "description": "The policy details.", "title": "policy" } }, "required": [ "document_id", "attached_at", "policy" ], "title": "DocumentPolicy", "type": "object" }, "Empty": { "description": "A generic empty message that you can re-use to avoid defining duplicated\n empty messages in your APIs. A typical example is to use it as the request\n or the response type of an API method. For instance:\n\n service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }", "type": "object" }, "ErrorDetail": { "properties": { "param": { "description": "The parameter that caused the error (only set for validation errors)", "type": "string" }, "reason": { "description": "Machine-readable error reason for programmatic handling", "enum": [ "missing_required_field", "invalid_field_value", "invalid_enum_value", "invalid_cursor", "invalid_id_format", "missing_api_key", "invalid_api_key", "expired_api_key", "invalid_token", "expired_token", "authentication_required", "insufficient_permissions", "resource_not_found", "resource_already_exists", "rate_limit_exceeded", "quota_exceeded", "precondition_failed", "feature_disabled", "internal_error", "service_unavailable", "unimplemented" ], "type": "string" }, "request_id": { "description": "Request correlation ID for tracing and log lookup (e.g., \"req_01arwx4k8xrgqskvxq69gdn019\")", "type": "string" } }, "type": "object" }, "ErrorResponse": { "properties": { "code": { "description": "ConnectRPC error code. Maps to HTTP status codes:\n- invalid_argument, failed_precondition -\u003e 400\n- unauthenticated -\u003e 401\n- permission_denied -\u003e 403\n- not_found -\u003e 404\n- already_exists -\u003e 409\n- resource_exhausted -\u003e 429\n- deadline_exceeded -\u003e 408\n- canceled -\u003e 499\n- internal, unknown -\u003e 500 (unknown may appear as 400 for malformed JSON requests)\n- unimplemented -\u003e 501\n- unavailable -\u003e 503\n", "enum": [ "unknown", "invalid_argument", "unauthenticated", "permission_denied", "not_found", "already_exists", "resource_exhausted", "failed_precondition", "internal", "unavailable", "unimplemented", "canceled", "deadline_exceeded" ], "type": "string" }, "details": { "description": "Structured error details for programmatic handling", "items": { "$ref": "#/components/schemas/ErrorDetail" }, "type": "array" }, "message": { "description": "Human-readable error message", "type": "string" } }, "required": [ "code", "message" ], "type": "object" }, "GenerateEntryPageRequest": { "additionalProperties": false, "description": "GenerateEntryPageRequest identifies a document to generate an entry page for.", "properties": { "document_id": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } }, "title": "GenerateEntryPageRequest", "type": "object" }, "GenerateEntryPageResponse": { "additionalProperties": false, "description": "GenerateEntryPageResponse contains the download URL for the entry page.", "properties": { "download_url": { "description": "Temporary download URL for the entry page PDF.", "example": "https://storage.factify.com/entry-pages/abc123.pdf?token=xyz", "format": "uri", "title": "download_url", "type": "string" } }, "required": [ "download_url" ], "title": "GenerateEntryPageResponse", "type": "object" }, "GetDocumentRequest": { "additionalProperties": false, "description": "GetDocumentRequest identifies a document to retrieve.", "properties": { "document_id": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } }, "title": "GetDocumentRequest", "type": "object" }, "GetDocumentResponse": { "additionalProperties": false, "description": "GetDocumentResponse contains the requested document.", "properties": { "document": { "$ref": "#/components/schemas/Document", "description": "The requested document.", "title": "document" } }, "required": [ "document" ], "title": "GetDocumentResponse", "type": "object" }, "GetOrganizationQuotaRequest": { "additionalProperties": false, "description": "GetOrganizationQuotaRequest is a request to get quota status.", "properties": { "organization_id": { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.\n Only admins can query other organizations.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "GetOrganizationQuotaRequest", "type": "object" }, "GetOrganizationQuotaResponse": { "additionalProperties": false, "description": "GetOrganizationQuotaResponse returns the quota status.", "properties": { "quota": { "$ref": "#/components/schemas/OrganizationQuota", "description": "The organization's quota status.", "title": "quota" } }, "title": "GetOrganizationQuotaResponse", "type": "object" }, "GetOrganizationRequest": { "additionalProperties": false, "description": "GetOrganizationRequest identifies an organization to retrieve.", "properties": { "organization_id": { "description": "Organization ID.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "required": [ "organization_id" ], "title": "GetOrganizationRequest", "type": "object" }, "GetOrganizationResponse": { "additionalProperties": false, "description": "GetOrganizationResponse contains the requested organization.", "properties": { "organization": { "$ref": "#/components/schemas/Organization", "description": "The requested organization.", "title": "organization" } }, "required": [ "organization" ], "title": "GetOrganizationResponse", "type": "object" }, "GetUsageHistoryRequest": { "additionalProperties": false, "description": "GetUsageHistoryRequest is a request to get usage history.\ndate_range_valid // date.before must be after date.after\n", "properties": { "date": { "description": "Filter by date range.\n REST: ?date.after=2026-01-01T00:00:00Z\u0026date.before=2026-02-01T00:00:00Z", "format": "date-time", "nullable": true, "title": "date", "type": "string" }, "organization_id": { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "GetUsageHistoryRequest", "type": "object" }, "GetUsageHistoryResponse": { "additionalProperties": false, "description": "GetUsageHistoryResponse returns usage history.", "properties": { "daily_usage": { "description": "Daily usage records.", "items": { "$ref": "#/components/schemas/DailyUsage" }, "title": "daily_usage", "type": "array" }, "organization_id": { "description": "The organization ID.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "total_requests": { "description": "Total requests in the period.", "format": "int32", "title": "total_requests", "type": "integer" } }, "title": "GetUsageHistoryResponse", "type": "object" }, "GetVersionRequest": { "additionalProperties": false, "description": "GetVersionRequest identifies a specific version to retrieve.", "properties": { "version_id": { "description": "Version ID to retrieve.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "version_id", "type": "string" } }, "title": "GetVersionRequest", "type": "object" }, "ListAPIKeyQuotasRequest": { "additionalProperties": false, "description": "ListAPIKeyQuotasRequest lists all key-level quotas for an organization.", "properties": { "organization_id": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "ListAPIKeyQuotasRequest", "type": "object" }, "ListAPIKeyQuotasResponse": { "additionalProperties": false, "description": "ListAPIKeyQuotasResponse returns all key-level quotas.", "properties": { "quotas": { "description": "Per-key quota configurations and usage.", "items": { "$ref": "#/components/schemas/APIKeyQuota" }, "title": "quotas", "type": "array" } }, "title": "ListAPIKeyQuotasResponse", "type": "object" }, "ListApiKeysRequest": { "additionalProperties": false, "description": "ListApiKeysRequest specifies filters and pagination for listing API keys.", "properties": { "include_revoked": { "description": "Whether to include revoked keys in the response.\n Default: false (only active and expired-but-not-revoked keys are returned).\n When true, all keys including revoked ones are returned.\n Note: Expired keys are always included unless also revoked; use is_active to filter.", "title": "include_revoked", "type": "boolean" }, "organization_id": { "description": "Organization ID to list keys for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, "required": [ "organization_id" ], "title": "ListApiKeysRequest", "type": "object" }, "ListApiKeysResponse": { "additionalProperties": false, "description": "ListApiKeysResponse contains a page of API keys.", "properties": { "items": { "description": "List of API keys (secrets are never included).", "items": { "$ref": "#/components/schemas/ApiKey" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListApiKeysResponse", "type": "object" }, "ListDocumentPoliciesRequest": { "additionalProperties": false, "description": "ListDocumentPoliciesRequest specifies pagination for listing document policies.\n Follows Google AIP-158 for pagination field naming.", "properties": { "document_id": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6InBvbF8wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJuZXh0IiwiZiI6eyJkb2NfaWQiOiJkb2NfMDFoMnhjZWpxdGYybmJyZXh4M3ZxamhwNDEifX0", "title": "page_token", "type": "string" } }, "title": "ListDocumentPoliciesRequest", "type": "object" }, "ListDocumentPoliciesResponse": { "additionalProperties": false, "description": "ListDocumentPoliciesResponse contains a page of policy attachments.", "properties": { "items": { "description": "List of policy attachments.", "items": { "$ref": "#/components/schemas/DocumentPolicy" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListDocumentPoliciesResponse", "type": "object" }, "ListDocumentsRequest": { "additionalProperties": false, "description": "ListDocumentsRequest specifies filters and pagination for listing documents.\n Follows Google AIP-158 for pagination field naming.\n Uses Vanguard-compatible dot notation for nested filters: ?created.after=...\u0026created.before=...\ncreated_time_range // created.after must be before created.before\n", "properties": { "access_level": { "description": "Filter by access level(s). Returns documents matching ANY of the specified levels.\n REST: ?access_level=private or ?access_level=private\u0026access_level=organization", "items": { "$ref": "#/components/schemas/AccessLevel" }, "title": "access_level", "type": "array" }, "created": { "description": "Filter by creation time range.\n REST: ?created.after=2024-01-01T00:00:00Z\u0026created.before=2024-12-31T23:59:59Z", "format": "date-time", "nullable": true, "title": "created", "type": "string" }, "created_by_id": { "description": "Filter by creator ID(s) (user or bot). Returns documents matching ANY of the specified IDs.\n Accepts single value or comma-separated list.\n REST: ?created_by_id=user_01h2xcejqtf2nbrexx3vqjhp41 or ?created_by_id=user_xxx,bot_yyy", "nullable": true, "title": "created_by_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6ImRvY18wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJuZXh0In0", "title": "page_token", "type": "string" }, "processing_status": { "description": "Filter by processing status(es). Returns documents matching ANY of the specified statuses.\n REST: ?processing_status=ready or ?processing_status=processing\u0026processing_status=ready", "items": { "$ref": "#/components/schemas/ProcessingStatus" }, "title": "processing_status", "type": "array" } }, "title": "ListDocumentsRequest", "type": "object" }, "ListDocumentsResponse": { "additionalProperties": false, "description": "ListDocumentsResponse contains a page of documents.", "properties": { "items": { "description": "List of documents.", "items": { "$ref": "#/components/schemas/Document" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListDocumentsResponse", "type": "object" }, "ListOrganizationInvitesRequest": { "additionalProperties": false, "description": "ListOrganizationInvitesRequest specifies filters for listing invitations.\ncreated_time_range // created.after must be before created.before\nexpires_time_range // expires.after must be before expires.before\n", "properties": { "created": { "description": "Filter by creation time range.\n REST: ?created.after=2024-01-01T00:00:00Z\u0026created.before=2024-12-31T23:59:59Z", "format": "date-time", "nullable": true, "title": "created", "type": "string" }, "email": { "$ref": "#/components/schemas/StringFilter", "description": "Filter by email address.\n REST: ?email.contains=dwight or ?email.exact=dwight@dundermifflin.com", "nullable": true, "title": "email" }, "expires": { "description": "Filter by expiration time range.\n Useful for finding invitations expiring soon (expires.before) or still valid beyond a date (expires.after).\n REST: ?expires.after=2024-01-01T00:00:00Z\u0026expires.before=2024-01-31T23:59:59Z", "format": "date-time", "nullable": true, "title": "expires", "type": "string" }, "organization_id": { "description": "Organization to list invitations for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" }, "sender_id": { "description": "Filter by sender. Only returns invitations sent by this user.\n REST: ?sender_id=user_01h2xcejqtf2nbrexx3vqjhp41\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "nullable": true, "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "sender_id", "type": "string" }, "status": { "description": "Filter by invitation status.\n If empty, returns all invitations.\n REST: ?status=pending or ?status=pending\u0026status=expired", "items": { "$ref": "#/components/schemas/OrganizationInviteStatus" }, "title": "status", "type": "array" } }, "required": [ "organization_id" ], "title": "ListOrganizationInvitesRequest", "type": "object" }, "ListOrganizationInvitesResponse": { "additionalProperties": false, "description": "ListOrganizationInvitesResponse contains a page of invitations.", "properties": { "items": { "description": "List of invitations.", "items": { "$ref": "#/components/schemas/OrganizationInvite" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListOrganizationInvitesResponse", "type": "object" }, "ListOrganizationMembersRequest": { "additionalProperties": false, "description": "ListOrganizationMembersRequest specifies the organization and pagination.", "properties": { "organization_id": { "description": "Organization to list members for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, "required": [ "organization_id" ], "title": "ListOrganizationMembersRequest", "type": "object" }, "ListOrganizationMembersResponse": { "additionalProperties": false, "description": "ListOrganizationMembersResponse contains a page of organization members.", "properties": { "items": { "description": "List of organization members.", "items": { "$ref": "#/components/schemas/OrganizationMember" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListOrganizationMembersResponse", "type": "object" }, "ListOrganizationsRequest": { "additionalProperties": false, "description": "ListOrganizationsRequest specifies pagination for listing organizations.", "properties": { "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" }, "role": { "description": "Filter by the caller's role in the organization.\n If omitted or empty, returns all organizations the caller can view (no filtering).\n REST: ?role=admin or ?role=admin\u0026role=owner", "items": { "$ref": "#/components/schemas/OrganizationRole" }, "title": "role", "type": "array" } }, "title": "ListOrganizationsRequest", "type": "object" }, "ListOrganizationsResponse": { "additionalProperties": false, "description": "ListOrganizationsResponse contains a page of organizations.", "properties": { "items": { "description": "List of organizations.", "items": { "$ref": "#/components/schemas/Organization" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListOrganizationsResponse", "type": "object" }, "ListVersionsRequest": { "additionalProperties": false, "description": "ListVersionsRequest specifies filters and pagination for listing versions.\n Follows Google AIP-158 for pagination field naming.", "properties": { "document_id": { "description": "Document ID to list versions for.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "page_size": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "nullable": true, "title": "page_size", "type": "integer" }, "page_token": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6InZlcl8wMWgyYWJjZDEyMzRlZmdoNTY3OGprbW5wdCIsImQiOiJuZXh0IiwiZiI6eyJkb2NfaWQiOiJkb2NfMDFoMnhjZWpxdGYybmJyZXh4M3ZxamhwNDEifX0", "title": "page_token", "type": "string" } }, "title": "ListVersionsRequest", "type": "object" }, "ListVersionsResponse": { "additionalProperties": false, "description": "ListVersionsResponse contains a page of versions.", "properties": { "items": { "description": "List of versions.", "items": { "$ref": "#/components/schemas/Version" }, "title": "items", "type": "array" }, "pagination": { "$ref": "#/components/schemas/Pagination", "description": "Pagination metadata.", "title": "pagination" } }, "required": [ "pagination" ], "title": "ListVersionsResponse", "type": "object" }, "Organization": { "additionalProperties": false, "description": "Organization represents a Factify organization.", "properties": { "created_at": { "description": "Timestamp when the organization was created.", "format": "date-time", "title": "created_at", "type": "string" }, "id": { "description": "Unique ID for the organization.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "name": { "description": "Human-readable organization name.", "example": "Acme Corporation", "maxLength": 255, "minLength": 1, "title": "name", "type": "string" } }, "required": [ "id", "name", "created_at" ], "title": "Organization", "type": "object" }, "OrganizationInvite": { "additionalProperties": false, "description": "OrganizationInvite represents an invitation to join an organization.\naccepted_fields_consistency // accepted_at and accepted_by must both be set or both be unset\n", "properties": { "accepted_at": { "description": "When the invitation was accepted (if accepted).", "format": "date-time", "title": "accepted_at", "type": "string" }, "accepted_by": { "$ref": "#/components/schemas/User", "description": "User who accepted the invitation (if accepted).", "title": "accepted_by" }, "created_at": { "description": "When the invitation was created.", "format": "date-time", "title": "created_at", "type": "string" }, "email": { "description": "Email address of the recipient.", "example": "dwight@dundermifflin.com", "format": "email", "title": "email", "type": "string" }, "expires_at": { "description": "When the invitation expires.", "format": "date-time", "title": "expires_at", "type": "string" }, "id": { "description": "Unique identifier for the invitation.", "example": "inv_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^inv_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "message": { "description": "Custom message from sender to recipient (if provided).\n Max 2000 bytes to support ~500 multibyte characters.", "maxLength": 2000, "nullable": true, "title": "message", "type": "string" }, "organization_id": { "description": "Organization the invitation is for.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "sender": { "$ref": "#/components/schemas/User", "description": "User who sent the invitation (point-in-time snapshot at creation).", "title": "sender" }, "status": { "$ref": "#/components/schemas/OrganizationInviteStatus", "description": "Current status of the invitation.", "title": "status" } }, "required": [ "id", "organization_id", "email", "status", "sender", "created_at", "expires_at" ], "title": "OrganizationInvite", "type": "object" }, "OrganizationInviteStatus": { "enum": [ "pending", "accepted", "expired", "revoked" ] }, "OrganizationMember": { "additionalProperties": false, "description": "OrganizationMember represents a member of an organization.", "properties": { "joined_at": { "description": "When the member joined the organization.", "format": "date-time", "title": "joined_at", "type": "string" }, "role": { "$ref": "#/components/schemas/OrganizationRole", "description": "Role of the member within the organization.", "not": { "enum": [ 0 ] }, "title": "role" }, "user": { "$ref": "#/components/schemas/User", "description": "User account details for this member.", "title": "user" } }, "required": [ "user", "joined_at", "role" ], "title": "OrganizationMember", "type": "object" }, "OrganizationQuota": { "additionalProperties": false, "description": "OrganizationQuota represents the quota status for an organization.", "properties": { "current_usage": { "description": "Current usage in the billing period.", "format": "int32", "title": "current_usage", "type": "integer" }, "effective_limit": { "description": "The effective monthly limit (explicit limit if set, otherwise tier default).", "format": "int32", "title": "effective_limit", "type": "integer" }, "is_exceeded": { "description": "Whether quota is exceeded.", "title": "is_exceeded", "type": "boolean" }, "organization_id": { "description": "The organization ID.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "period_start": { "description": "Start of current billing period.", "format": "date-time", "title": "period_start", "type": "string" }, "remaining": { "description": "Remaining requests in the billing period.", "format": "int32", "title": "remaining", "type": "integer" }, "reset_at": { "description": "When the quota resets (start of next billing period).", "format": "date-time", "title": "reset_at", "type": "string" }, "tier": { "$ref": "#/components/schemas/QuotaTier", "description": "The quota tier (free or custom).", "title": "tier" }, "usage_percent": { "description": "Usage as a percentage (0-100+).", "format": "int32", "title": "usage_percent", "type": "integer" } }, "title": "OrganizationQuota", "type": "object" }, "OrganizationQuotaConfig": { "additionalProperties": false, "description": "OrganizationQuotaConfig represents the stored quota configuration (not current usage).", "properties": { "created_at": { "description": "When the configuration was created.", "format": "date-time", "title": "created_at", "type": "string" }, "effective_limit": { "description": "The effective limit (limit if set, otherwise tier default).", "format": "int32", "title": "effective_limit", "type": "integer" }, "limit": { "description": "Optional limit override. If not set, uses the configured tier default.", "exclusiveMinimum": 0, "format": "int32", "nullable": true, "title": "limit", "type": "integer" }, "organization_id": { "description": "The organization ID.", "title": "organization_id", "type": "string" }, "tier": { "$ref": "#/components/schemas/QuotaTier", "description": "The quota tier.", "title": "tier" }, "updated_at": { "description": "When the configuration was last updated.", "format": "date-time", "title": "updated_at", "type": "string" } }, "title": "OrganizationQuotaConfig", "type": "object" }, "OrganizationRole": { "enum": [ "owner", "admin", "member" ] }, "Pagination": { "additionalProperties": false, "description": "Pagination contains cursor-based pagination metadata.\n Follows Google AIP-158 for pagination field naming.", "properties": { "has_more": { "description": "Whether there are more results in the forward direction.", "title": "has_more", "type": "boolean" }, "next_page_token": { "description": "Token to retrieve the next page of results.\n Empty if there are no more results in the forward direction.", "example": "eyJpZCI6ImRvY18wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJuZXh0In0", "title": "next_page_token", "type": "string" }, "prev_page_token": { "description": "Token to retrieve the previous page of results.\n Empty if this is the first page.", "example": "eyJpZCI6ImRvY18wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJwcmV2In0", "title": "prev_page_token", "type": "string" } }, "title": "Pagination", "type": "object" }, "Policy": { "additionalProperties": false, "description": "Policy represents a governance policy.", "properties": { "created_at": { "description": "Timestamp when policy was created.", "format": "date-time", "title": "created_at", "type": "string" }, "id": { "description": "Unique ID for the policy.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "example": "pol_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^pol_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "name": { "description": "Policy name.", "example": "GDPR Compliance Policy", "minLength": 1, "title": "name", "type": "string" } }, "required": [ "id", "name", "created_at" ], "title": "Policy", "type": "object" }, "ProcessingStatus": { "enum": [ "processing", "ready", "failed" ] }, "QuotaTier": { "enum": [ "free", "custom" ] }, "RemoveOrganizationMemberRequest": { "additionalProperties": false, "description": "RemoveOrganizationMemberRequest identifies a member to remove.", "properties": { "organization_id": { "description": "Organization to remove the member from.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "user_id": { "description": "User account ID of the member to remove.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } }, "required": [ "organization_id", "user_id" ], "title": "RemoveOrganizationMemberRequest", "type": "object" }, "RemoveOrganizationMemberResponse": { "additionalProperties": false, "description": "RemoveOrganizationMemberResponse is empty on success.", "title": "RemoveOrganizationMemberResponse", "type": "object" }, "ResendOrganizationInviteRequest": { "additionalProperties": false, "description": "ResendOrganizationInviteRequest identifies an invitation to resend.", "properties": { "invite_id": { "description": "Invitation ID to resend.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^inv_[0-9a-hjkmnp-tv-z]{26}$", "title": "invite_id", "type": "string" }, "organization_id": { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "required": [ "organization_id", "invite_id" ], "title": "ResendOrganizationInviteRequest", "type": "object" }, "ResendOrganizationInviteResponse": { "additionalProperties": false, "description": "ResendOrganizationInviteResponse contains the updated invitation.", "properties": { "invite": { "$ref": "#/components/schemas/OrganizationInvite", "description": "The invitation with updated send count and timestamp.", "title": "invite" } }, "required": [ "invite" ], "title": "ResendOrganizationInviteResponse", "type": "object" }, "RevokeApiKeyRequest": { "additionalProperties": false, "description": "RevokeApiKeyRequest identifies an API key to revoke.", "properties": { "api_key_id": { "description": "API key ID to revoke.\n Pattern: key_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" }, "reason": { "description": "Optional reason for revocation (for audit purposes).\n The revoking user's identity and timestamp are captured in audit logs separately.", "maxLength": 500, "minLength": 1, "nullable": true, "title": "reason", "type": "string" } }, "required": [ "api_key_id" ], "title": "RevokeApiKeyRequest", "type": "object" }, "RevokeApiKeyResponse": { "additionalProperties": false, "description": "RevokeApiKeyResponse contains the revoked API key.", "properties": { "api_key": { "$ref": "#/components/schemas/ApiKey", "description": "The revoked API key with updated revoked_at timestamp.", "title": "api_key" } }, "required": [ "api_key" ], "title": "RevokeApiKeyResponse", "type": "object" }, "RevokeOrganizationInviteRequest": { "additionalProperties": false, "description": "RevokeOrganizationInviteRequest identifies an invitation to revoke.", "properties": { "invite_id": { "description": "Invitation ID to revoke.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^inv_[0-9a-hjkmnp-tv-z]{26}$", "title": "invite_id", "type": "string" }, "organization_id": { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "required": [ "organization_id", "invite_id" ], "title": "RevokeOrganizationInviteRequest", "type": "object" }, "RevokeOrganizationInviteResponse": { "additionalProperties": false, "description": "RevokeOrganizationInviteResponse contains the revoked invitation.", "properties": { "invite": { "$ref": "#/components/schemas/OrganizationInvite", "description": "The revoked invitation with updated status.", "title": "invite" } }, "required": [ "invite" ], "title": "RevokeOrganizationInviteResponse", "type": "object" }, "SetAPIKeyQuotaRequest": { "additionalProperties": false, "description": "SetAPIKeyQuotaRequest creates or updates a per-key quota.", "properties": { "api_key_id": { "description": "The API key ID (required).", "minLength": 1, "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" }, "limit": { "description": "The limit for this key. Must be \u003e 0.", "exclusiveMinimum": 0, "format": "int32", "nullable": true, "title": "limit", "type": "integer" }, "organization_id": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "SetAPIKeyQuotaRequest", "type": "object" }, "SetAPIKeyQuotaResponse": { "additionalProperties": false, "description": "SetAPIKeyQuotaResponse returns the updated key quota.", "properties": { "quota": { "$ref": "#/components/schemas/APIKeyQuota", "description": "The updated key quota status.", "title": "quota" } }, "title": "SetAPIKeyQuotaResponse", "type": "object" }, "SetOrganizationQuotaRequest": { "additionalProperties": false, "description": "SetOrganizationQuotaRequest is a request to set quota configuration.", "properties": { "limit": { "description": "Optional limit override. If not set, uses the configured tier default.\n Must be \u003e 0 when set. Use a very high value (e.g., 999999999) for unlimited.", "exclusiveMinimum": 0, "format": "int32", "nullable": true, "title": "limit", "type": "integer" }, "organization_id": { "description": "The organization ID (required).", "minLength": 1, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "tier": { "$ref": "#/components/schemas/QuotaTier", "description": "The quota tier to set.", "not": { "enum": [ 0 ] }, "title": "tier" } }, "title": "SetOrganizationQuotaRequest", "type": "object" }, "SetOrganizationQuotaResponse": { "additionalProperties": false, "description": "SetOrganizationQuotaResponse returns the updated quota configuration.", "properties": { "quota": { "$ref": "#/components/schemas/OrganizationQuotaConfig", "description": "The updated quota configuration.", "title": "quota" } }, "title": "SetOrganizationQuotaResponse", "type": "object" }, "StringFilter": { "additionalProperties": false, "description": "StringFilter provides flexible string matching options.\n Used with Vanguard dot notation: ?email.contains=john or ?email.exact=john@example.com\n\n Note on case sensitivity: `contains` is case-insensitive for user-friendly partial\n matching (e.g., finding \"john\" matches \"John.Doe@...\"). `exact` is case-sensitive\n for precise lookups where the caller knows the exact value. For email addresses,\n this matches RFC 5321 behavior where the domain is case-insensitive but local-part\n handling varies by provider.\nmutually_exclusive // only one of contains or exact can be specified\n", "properties": { "contains": { "description": "Case-insensitive substring match.\n REST: ?field.contains=value", "nullable": true, "title": "contains", "type": "string" }, "exact": { "description": "Exact match (case-sensitive).\n REST: ?field.exact=value", "nullable": true, "title": "exact", "type": "string" } }, "title": "StringFilter", "type": "object" }, "Subject": { "additionalProperties": false, "description": "Subject is a lightweight reference to either a user or a bot.\n Used in embedded fields like created_by.\n For full details, call GetUser or GetBot with the subject's id.\nsubject_type_matches_id_prefix // id prefix must match type (user_ for user, bot_ for bot)\n", "discriminator": { "propertyName": "type" }, "properties": { "id": { "description": "Unique ID. user_xxx for users, bot_xxx for bots.", "example": "user_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^(user|bot)_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "name": { "description": "Display name of the user or bot.", "minLength": 1, "title": "name", "type": "string" }, "type": { "$ref": "#/components/schemas/SubjectType", "description": "Discriminator indicating whether this subject is a user or a bot.", "title": "type" } }, "required": [ "id", "type", "name" ], "title": "Subject", "type": "object" }, "SubjectType": { "enum": [ "user", "bot" ] }, "TimestampFilter": { "additionalProperties": false, "description": "TimestampFilter specifies a time range for filtering.\n Used with Vanguard dot notation: ?created.after=...\u0026created.before=...", "properties": { "after": { "description": "Return results after this timestamp (inclusive).", "format": "date-time", "nullable": true, "title": "after", "type": "string" }, "before": { "description": "Return results before this timestamp (inclusive).", "format": "date-time", "nullable": true, "title": "before", "type": "string" } }, "title": "TimestampFilter", "type": "object" }, "UpdateDocumentRequest": { "additionalProperties": false, "description": "UpdateDocumentRequest specifies fields to update on a document.", "properties": { "description": { "description": "New description (max 2000 characters).", "maxLength": 2000, "nullable": true, "title": "description", "type": "string" }, "document_id": { "description": "Document ID to update.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "title": { "description": "New title (1-255 characters).", "maxLength": 255, "minLength": 1, "nullable": true, "title": "title", "type": "string" } }, "title": "UpdateDocumentRequest", "type": "object" }, "UpdateDocumentResponse": { "additionalProperties": false, "description": "UpdateDocumentResponse contains the updated document.", "properties": { "document": { "$ref": "#/components/schemas/Document", "description": "The updated document.", "title": "document" } }, "required": [ "document" ], "title": "UpdateDocumentResponse", "type": "object" }, "UpdateOrganizationMemberRequest": { "additionalProperties": false, "description": "UpdateOrganizationMemberRequest identifies a member and the new role.", "properties": { "organization_id": { "description": "Organization the member belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" }, "role": { "$ref": "#/components/schemas/OrganizationRole", "description": "New role for the member. Cannot be UNSPECIFIED or OWNER.\n OWNER transfer is not supported — the owner is set at organization creation.", "not": { "enum": [ 0, 1 ] }, "title": "role" }, "user_id": { "description": "User account ID of the member to update.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } }, "required": [ "organization_id", "user_id", "role" ], "title": "UpdateOrganizationMemberRequest", "type": "object" }, "UpdateOrganizationMemberResponse": { "additionalProperties": false, "description": "UpdateOrganizationMemberResponse contains the updated member.", "properties": { "member": { "$ref": "#/components/schemas/OrganizationMember", "description": "The updated organization member with the new role.", "title": "member" } }, "required": [ "member" ], "title": "UpdateOrganizationMemberResponse", "type": "object" }, "UpdateVersionRequest": { "additionalProperties": false, "description": "UpdateVersionRequest specifies fields to update on a version.", "properties": { "description": { "description": "New description.", "nullable": true, "title": "description", "type": "string" }, "title": { "description": "New title (max 255 characters).", "maxLength": 255, "nullable": true, "title": "title", "type": "string" }, "version_id": { "description": "Version ID to update.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "version_id", "type": "string" } }, "title": "UpdateVersionRequest", "type": "object" }, "User": { "additionalProperties": false, "description": "User represents a human user account.\n Returned by GetUser (endpoint deferred).", "properties": { "email": { "format": "email", "title": "email", "type": "string" }, "id": { "example": "user_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "name": { "description": "Display name of the user.", "minLength": 1, "title": "name", "type": "string" } }, "required": [ "id", "name", "email" ], "title": "User", "type": "object" }, "Version": { "additionalProperties": false, "description": "Version represents a document version.", "properties": { "created_at": { "description": "Timestamp when version was created.", "format": "date-time", "title": "created_at", "type": "string" }, "created_by": { "$ref": "#/components/schemas/Subject", "description": "Subject who created the version.", "title": "created_by" }, "description": { "description": "Description of changes in this version.", "nullable": true, "title": "description", "type": "string" }, "document_id": { "description": "Parent document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "example": "doc_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" }, "id": { "description": "Unique ID for the version.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "example": "ver_01h2abcd1234efgh5678jkmnpt", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" }, "processing_status": { "$ref": "#/components/schemas/ProcessingStatus", "description": "Processing status.", "title": "processing_status" }, "title": { "description": "Optional version title.", "example": "Version 2.0", "maxLength": 255, "nullable": true, "title": "title", "type": "string" }, "url": { "description": "URL for accessing this version on Factify.", "example": "https://app.factify.com/d/01h2xcejqtf2nbrexx3vqjhp41/v/1", "format": "uri", "title": "url", "type": "string" } }, "required": [ "id", "document_id", "url", "processing_status", "created_at", "created_by" ], "title": "Version", "type": "object" }, "VersionRef": { "additionalProperties": false, "description": "VersionRef is a lightweight reference to a version.", "properties": { "id": { "description": "Version ID.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "example": "ver_01h2abcd1234efgh5678jkmnpt", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "id", "type": "string" } }, "required": [ "id" ], "title": "VersionRef", "type": "object" }, "connect-protocol-version": { "const": 1, "description": "Define the version of the Connect protocol", "enum": [ 1 ], "title": "Connect-Protocol-Version", "type": "number" }, "connect-timeout-header": { "description": "Define the timeout, in ms", "title": "Connect-Timeout-Ms", "type": "number" }, "connect.error": { "additionalProperties": true, "description": "Error type returned by Connect: https://connectrpc.com/docs/go/errors/#http-representation", "properties": { "code": { "description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].", "enum": [ "canceled", "unknown", "invalid_argument", "deadline_exceeded", "not_found", "already_exists", "permission_denied", "resource_exhausted", "failed_precondition", "aborted", "out_of_range", "unimplemented", "internal", "unavailable", "data_loss", "unauthenticated" ], "example": "not_found", "type": "string" }, "details": { "description": "A list of messages that carry the error details. There is no limit on the number of messages.", "items": { "$ref": "#/components/schemas/connect.error_details.Any" }, "type": "array" }, "message": { "description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.", "type": "string" } }, "title": "Connect Error", "type": "object" }, "connect.error_details.Any": { "additionalProperties": true, "description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message, with an additional debug field for ConnectRPC error details.", "properties": { "debug": { "description": "Deserialized error detail payload. The 'type' field indicates the schema. This field is for easier debugging and should not be relied upon for application logic.", "discriminator": { "propertyName": "type" }, "oneOf": [ { "additionalProperties": true, "description": "Detailed error information.", "title": "Any", "type": "object" } ], "title": "Debug" }, "type": { "description": "A URL that acts as a globally unique identifier for the type of the serialized message. For example: `type.googleapis.com/google.rpc.ErrorInfo`. This is used to determine the schema of the data in the `value` field and is the discriminator for the `debug` field.", "type": "string" }, "value": { "description": "The Protobuf message, serialized as bytes and base64-encoded. The specific message type is identified by the `type` field.", "format": "binary", "type": "string" } }, "type": "object" } }, "securitySchemes": { "bearerAuth": { "bearerFormat": "API Key", "description": "Bearer authentication header of the form Bearer \u003ctoken\u003e, where \u003ctoken\u003e is your auth token.", "scheme": "bearer", "type": "http" } } }, "info": { "contact": { "email": "api@factify.com", "name": "Factify API Support", "url": "https://factify.com/support" }, "description": "Factify API enables you to create, manage, and control access to legally-binding documents that replace PDFs.\n\n## Authentication\n\nBearer authentication header of the form Bearer \u003ctoken\u003e, where \u003ctoken\u003e is your auth token.\n\n```\nAuthorization: Bearer ffy...\n```\n\n## Rate Limiting\n\n- 1000 requests per minute per API key\n- 100 requests per minute for resource creation (POST)\n\n## Errors\n\nFactify uses conventional HTTP status codes and returns structured error responses\nusing the [ConnectRPC error format](https://connectrpc.com/docs/protocol#error-codes):\n\n```json\n{\n \"code\": \"invalid_argument\",\n \"message\": \"limit must be positive\",\n \"details\": [\n {\n \"reason\": \"invalid_field_value\",\n \"request_id\": \"req_01arwx4k8xrgqskvxq69gdn019\",\n \"param\": \"limit\"\n }\n ]\n}\n```\n", "license": { "name": "Proprietary", "url": "https://factify.com/terms" }, "title": "Factify API", "version": "1.0.0" }, "openapi": "3.1.0", "paths": { "/factify.api.v1beta.QuotaService/DeleteOrganizationQuota": { "post": { "description": "DeleteOrganizationQuota removes quota configuration for an organization.\n The organization will fall back to default free tier limits.\n Requires platform admin permission. ConnectRPC only (not exposed via REST).", "operationId": "QuotaService_DeleteOrganizationQuota", "parameters": [ { "in": "header", "name": "Connect-Protocol-Version", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "in": "header", "name": "Connect-Timeout-Ms", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteOrganizationQuotaRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteOrganizationQuotaResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } }, "description": "Error" } }, "summary": "DeleteOrganizationQuota removes quota configuration for an organization. The organization will fall back to default free tier limits. Requires platform admin permission. ConnectRPC only (not exposed via REST).", "tags": [ "Quotas" ] } }, "/factify.api.v1beta.QuotaService/SetOrganizationQuota": { "post": { "description": "SetOrganizationQuota creates or updates quota configuration for an organization.\n Requires platform admin permission. ConnectRPC only (not exposed via REST).", "operationId": "QuotaService_SetOrganizationQuota", "parameters": [ { "in": "header", "name": "Connect-Protocol-Version", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "in": "header", "name": "Connect-Timeout-Ms", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetOrganizationQuotaRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetOrganizationQuotaResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } }, "description": "Error" } }, "summary": "SetOrganizationQuota creates or updates quota configuration for an organization. Requires platform admin permission. ConnectRPC only (not exposed via REST).", "tags": [ "Quotas" ] } }, "/v1beta/api-keys": { "get": { "description": "Lists API keys for an organization.", "operationId": "listApiKeys", "parameters": [ { "description": "Organization ID to list keys for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "query", "name": "organization_id", "required": true, "schema": { "description": "Organization ID to list keys for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Whether to include revoked keys in the response.\n Default: false (only active and expired-but-not-revoked keys are returned).\n When true, all keys including revoked ones are returned.\n Note: Expired keys are always included unless also revoked; use is_active to filter.", "in": "query", "name": "include_revoked", "schema": { "description": "Whether to include revoked keys in the response.\n Default: false (only active and expired-but-not-revoked keys are returned).\n When true, all keys including revoked ones are returned.\n Note: Expired keys are always included unless also revoked; use is_active to filter.", "title": "include_revoked", "type": "boolean" } }, { "description": "Opaque pagination token from a previous response.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListApiKeysResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List API keys", "tags": [ "API Keys" ], "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Creates a new API key for the specified organization. The secret is only returned once in the response and cannot be retrieved later.", "operationId": "createApiKey", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateApiKeyRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateApiKeyResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Create an API key", "tags": [ "API Keys" ], "x-speakeasy-name-override": "create" } }, "/v1beta/api-keys/{api_key_id}/revoke": { "post": { "description": "Revokes an API key, immediately preventing it from being used for authentication.", "operationId": "revokeApiKey", "parameters": [ { "description": "API key ID to revoke.\n Pattern: key_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "api_key_id", "required": true, "schema": { "description": "API key ID to revoke.\n Pattern: key_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "RevokeApiKeyRequest identifies an API key to revoke.", "properties": { "reason": { "description": "Optional reason for revocation (for audit purposes).\n The revoking user's identity and timestamp are captured in audit logs separately.", "maxLength": 500, "minLength": 1, "nullable": true, "title": "reason", "type": "string" } }, "required": [], "title": "RevokeApiKeyRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RevokeApiKeyResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Revoke an API key", "tags": [ "API Keys" ], "x-speakeasy-name-override": "revoke" } }, "/v1beta/documents": { "get": { "description": "List documents with cursor-based pagination.", "operationId": "listDocuments", "parameters": [ { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6ImRvY18wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJuZXh0In0", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } }, { "description": "Filter by creator ID(s). Returns documents matching ANY of the specified IDs.", "explode": false, "in": "query", "name": "created_by_id", "required": false, "schema": { "items": { "description": "User or bot TypeID (e.g., user_xxx, bot_yyy)", "type": "string" }, "type": "array" }, "style": "form" }, { "description": "Filter by access level(s). Returns documents matching ANY of the specified levels.", "explode": false, "in": "query", "name": "access_level", "required": false, "schema": { "items": { "description": "Access level", "enum": [ "private", "organization", "public" ], "type": "string" }, "type": "array" }, "style": "form" }, { "description": "Filter by processing status(es). Returns documents matching ANY of the specified statuses.", "explode": false, "in": "query", "name": "processing_status", "required": false, "schema": { "items": { "description": "Processing status", "enum": [ "processing", "ready", "failed" ], "type": "string" }, "type": "array" }, "style": "form" }, { "description": "Filter by created.after (RFC 3339 format, e.g., 2024-01-15T09:30:00Z)", "in": "query", "name": "created.after", "schema": { "format": "date-time", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListDocumentsResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List documents", "tags": [ "Documents" ], "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" }, "x-speakeasy-usage-example": true }, "post": { "description": "Creates a new document by uploading a PDF file.", "operationId": "createDocument", "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/CreateDocumentRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateDocumentResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Create a document", "tags": [ "Documents" ], "x-speakeasy-name-override": "create" } }, "/v1beta/documents/{document_id}": { "get": { "description": "Retrieve a document by ID.", "operationId": "getDocument", "parameters": [ { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetDocumentResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Retrieve a document", "tags": [ "Documents" ], "x-speakeasy-name-override": "get" }, "patch": { "description": "Update document title and description.", "operationId": "updateDocument", "parameters": [ { "description": "Document ID to update.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID to update.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "UpdateDocumentRequest specifies fields to update on a document.", "properties": { "description": { "description": "New description (max 2000 characters).", "maxLength": 2000, "nullable": true, "title": "description", "type": "string" }, "title": { "description": "New title (1-255 characters).", "maxLength": 255, "minLength": 1, "nullable": true, "title": "title", "type": "string" } }, "title": "UpdateDocumentRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateDocumentResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Update a document", "tags": [ "Documents" ], "x-speakeasy-name-override": "update" } }, "/v1beta/documents/{document_id}/entry_page": { "post": { "description": "Generate and return a temporary downloadable URL for the document entry page PDF.", "operationId": "generateDocumentEntryPage", "parameters": [ { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenerateEntryPageResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Generate entry page", "tags": [ "Sharing \u0026 Distribution" ], "x-speakeasy-group": "entryPages", "x-speakeasy-name-override": "generate" } }, "/v1beta/documents/{document_id}/policies": { "get": { "description": "List policies attached to a document.", "operationId": "listDocumentPolicies", "parameters": [ { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } }, { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6InBvbF8wMWgyeGNlanF0ZjJuYnJleHgzdnFqaHA0MSIsImQiOiJuZXh0IiwiZiI6eyJkb2NfaWQiOiJkb2NfMDFoMnhjZWpxdGYybmJyZXh4M3ZxamhwNDEifX0", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListDocumentPoliciesResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List document policies", "tags": [ "Policies" ], "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Attach a policy to a document.", "operationId": "attachDocumentPolicy", "parameters": [ { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "AttachPolicyRequest specifies a policy to attach to a document.", "properties": { "policy_id": { "description": "Policy ID to attach.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^pol_[0-9a-hjkmnp-tv-z]{26}$", "title": "policy_id", "type": "string" } }, "required": [ "policy_id" ], "title": "AttachPolicyRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocumentPolicy" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Attach a policy", "tags": [ "Policies" ], "x-speakeasy-name-override": "attach" } }, "/v1beta/documents/{document_id}/policies/{policy_id}": { "delete": { "description": "Detach a policy from a document.", "operationId": "detachDocumentPolicy", "parameters": [ { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } }, { "description": "Policy ID to detach.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "policy_id", "required": true, "schema": { "description": "Policy ID to detach.\n Pattern: pol_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^pol_[0-9a-hjkmnp-tv-z]{26}$", "title": "policy_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Empty" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Detach a policy", "tags": [ "Policies" ], "x-speakeasy-name-override": "detach" } }, "/v1beta/documents/{document_id}/versions": { "get": { "description": "List versions for a document with cursor-based pagination.", "operationId": "listDocumentVersions", "parameters": [ { "description": "Document ID to list versions for.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID to list versions for.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } }, { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.\n Pass next_page_token or prev_page_token from a previous response to continue pagination.\n Empty or omitted for the first page.", "example": "eyJpZCI6InZlcl8wMWgyYWJjZDEyMzRlZmdoNTY3OGprbW5wdCIsImQiOiJuZXh0IiwiZiI6eyJkb2NfaWQiOiJkb2NfMDFoMnhjZWpxdGYybmJyZXh4M3ZxamhwNDEifX0", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListVersionsResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List document versions", "tags": [ "Versions" ], "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Creates a new version by uploading a PDF file.", "operationId": "createDocumentVersion", "parameters": [ { "description": "Document ID to create version for.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "document_id", "required": true, "schema": { "description": "Document ID to create version for.\n Pattern: doc_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^doc_[0-9a-hjkmnp-tv-z]{26}$", "title": "document_id", "type": "string" } } ], "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/CreateVersionRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Version" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Create a new version", "tags": [ "Versions" ], "x-speakeasy-name-override": "create" } }, "/v1beta/organizations": { "get": { "description": "List organizations the caller has access to.", "operationId": "listOrganizations", "parameters": [ { "description": "Opaque pagination token from a previous response.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } }, { "description": "Filter by the caller's role in the organization.\n If omitted or empty, returns all organizations the caller can view (no filtering).\n REST: ?role=admin or ?role=admin\u0026role=owner", "in": "query", "name": "role", "schema": { "description": "Filter by the caller's role in the organization.\n If omitted or empty, returns all organizations the caller can view (no filtering).\n REST: ?role=admin or ?role=admin\u0026role=owner", "items": { "$ref": "#/components/schemas/OrganizationRole" }, "title": "role", "type": "array" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListOrganizationsResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List organizations", "tags": [ "Organizations" ], "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Creates a new organization. The authenticated user becomes the organization owner.", "operationId": "createOrganization", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateOrganizationRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateOrganizationResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Create an organization", "tags": [ "Organizations" ], "x-speakeasy-name-override": "create" } }, "/v1beta/organizations/{organization_id}": { "get": { "description": "Retrieve an organization by ID.", "operationId": "getOrganization", "parameters": [ { "description": "Organization ID.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization ID.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetOrganizationResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Retrieve an organization", "tags": [ "Organizations" ], "x-speakeasy-name-override": "get" } }, "/v1beta/organizations/{organization_id}/invites": { "get": { "description": "List invitations for an organization. Requires permission to invite organization members.", "operationId": "listOrganizationInvites", "parameters": [ { "description": "Organization to list invitations for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization to list invitations for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Filter by invitation status.\n If empty, returns all invitations.\n REST: ?status=pending or ?status=pending\u0026status=expired", "in": "query", "name": "status", "schema": { "description": "Filter by invitation status.\n If empty, returns all invitations.\n REST: ?status=pending or ?status=pending\u0026status=expired", "items": { "$ref": "#/components/schemas/OrganizationInviteStatus" }, "title": "status", "type": "array" } }, { "description": "Opaque pagination token from a previous response.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } }, { "description": "Case-insensitive substring match.\n REST: ?field.contains=value", "in": "query", "name": "email.contains", "schema": { "description": "Case-insensitive substring match.\n REST: ?field.contains=value", "title": "contains", "type": "string" } }, { "description": "Exact match (case-sensitive).\n REST: ?field.exact=value", "in": "query", "name": "email.exact", "schema": { "description": "Exact match (case-sensitive).\n REST: ?field.exact=value", "title": "exact", "type": "string" } }, { "description": "Filter by sender. Only returns invitations sent by this user.\n REST: ?sender_id=user_01h2xcejqtf2nbrexx3vqjhp41\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "in": "query", "name": "sender_id", "schema": { "description": "Filter by sender. Only returns invitations sent by this user.\n REST: ?sender_id=user_01h2xcejqtf2nbrexx3vqjhp41\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "sender_id", "type": "string" } }, { "description": "Filter by created.after (RFC 3339 format, e.g., 2024-01-15T09:30:00Z)", "in": "query", "name": "created.after", "schema": { "format": "date-time", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListOrganizationInvitesResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List organization invitations", "tags": [ "Organizations" ], "x-speakeasy-group": "organizations.invites", "x-speakeasy-name-override": "list", "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Creates an invitation and sends an email to the specified address. Returns FAILED_PRECONDITION if the email belongs to an existing organization member. Idempotency: If a PENDING invitation already exists for this email, the existing invitation is resent with a new token and refreshed expiration. Expired or revoked invitations are ignored - a new invitation is created.", "operationId": "createOrganizationInvite", "parameters": [ { "description": "Organization to invite the user to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization to invite the user to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "CreateOrganizationInviteRequest contains the data needed to create an invitation.", "properties": { "email": { "description": "Email address of the recipient.", "format": "email", "title": "email", "type": "string" }, "idempotency_key": { "description": "Reserved for future use. Currently, idempotency is based on email matching:\n if a PENDING invitation exists for the same email in this organization,\n that invitation is resent rather than creating a duplicate.", "maxLength": 255, "nullable": true, "title": "idempotency_key", "type": "string" }, "message": { "description": "Optional custom message from the sender (max 2000 bytes to support ~500 multibyte characters).", "maxLength": 2000, "nullable": true, "title": "message", "type": "string" } }, "required": [ "email" ], "title": "CreateOrganizationInviteRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateOrganizationInviteResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Invite a user to join an organization", "tags": [ "Organizations" ], "x-speakeasy-group": "organizations.invites", "x-speakeasy-name-override": "create" } }, "/v1beta/organizations/{organization_id}/invites/accept": { "post": { "description": "Accepts the invitation and adds the authenticated user as a member of the organization. The authenticated user's verified email must match the invitation email (case-insensitive). Returns PERMISSION_DENIED if emails don't match, FAILED_PRECONDITION if the user is already a member, or NOT_FOUND if the invitation is invalid/expired.", "operationId": "acceptOrganizationInvite", "parameters": [ { "description": "Organization the invitation belongs to (for validation).\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization the invitation belongs to (for validation).\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "AcceptOrganizationInviteRequest contains the token to accept an invitation.", "properties": { "token": { "description": "The invitation token from the email link.", "maxLength": 128, "title": "token", "type": "string" } }, "required": [ "token" ], "title": "AcceptOrganizationInviteRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AcceptOrganizationInviteResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Accept an invitation", "tags": [ "Organizations" ] } }, "/v1beta/organizations/{organization_id}/invites/{invite_id}/resend": { "post": { "description": "Resend an invitation email to the recipient. Useful if the original email was lost or expired. Requires permission to invite organization members.", "operationId": "resendOrganizationInvite", "parameters": [ { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Invitation ID to resend.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "invite_id", "required": true, "schema": { "description": "Invitation ID to resend.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^inv_[0-9a-hjkmnp-tv-z]{26}$", "title": "invite_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "ResendOrganizationInviteRequest identifies an invitation to resend.", "properties": {}, "required": [], "title": "ResendOrganizationInviteRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResendOrganizationInviteResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Resend an invitation email", "tags": [ "Organizations" ] } }, "/v1beta/organizations/{organization_id}/invites/{invite_id}/revoke": { "post": { "description": "Revoke a pending invitation, preventing the recipient from joining. Requires permission to manage organization members.", "operationId": "revokeOrganizationInvite", "parameters": [ { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization the invitation belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Invitation ID to revoke.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "invite_id", "required": true, "schema": { "description": "Invitation ID to revoke.\n Pattern: inv_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^inv_[0-9a-hjkmnp-tv-z]{26}$", "title": "invite_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "RevokeOrganizationInviteRequest identifies an invitation to revoke.", "properties": {}, "required": [], "title": "RevokeOrganizationInviteRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RevokeOrganizationInviteResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Revoke an invitation", "tags": [ "Organizations" ] } }, "/v1beta/organizations/{organization_id}/members": { "get": { "description": "List members of an organization. Requires organization membership.", "operationId": "listOrganizationMembers", "parameters": [ { "description": "Organization to list members for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization to list members for.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Opaque pagination token from a previous response.", "in": "query", "name": "page_token", "schema": { "description": "Opaque pagination token from a previous response.", "title": "page_token", "type": "string" } }, { "description": "Maximum number of items to return per page (1-100). Default: 50.", "in": "query", "name": "page_size", "schema": { "description": "Maximum number of items to return per page (1-100). Default: 50.", "format": "int32", "maximum": 100, "minimum": 1, "title": "page_size", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListOrganizationMembersResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List organization members", "tags": [ "Organizations" ], "x-speakeasy-pagination": { "inputs": [ { "in": "parameters", "name": "page_token", "type": "cursor" } ], "outputs": { "nextCursor": "$.pagination.next_page_token" }, "type": "cursor" } }, "post": { "description": "Directly adds a user as a member of an organization. Requires manage permission (owner or admin).", "operationId": "addOrganizationMember", "parameters": [ { "description": "Organization to add the member to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization to add the member to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "AddOrganizationMemberRequest identifies a user to add as a member.", "properties": { "role": { "$ref": "#/components/schemas/OrganizationRole", "description": "Role for the new member. Cannot be UNSPECIFIED or OWNER.", "not": { "enum": [ 0, 1 ] }, "title": "role" }, "user_id": { "description": "User account ID of the member to add.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } }, "required": [ "user_id", "role" ], "title": "AddOrganizationMemberRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddOrganizationMemberResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Add a member to an organization", "tags": [ "Organizations" ] } }, "/v1beta/organizations/{organization_id}/members/{user_id}": { "delete": { "description": "Remove a member from an organization. Requires manage permission, or the member can remove themselves. The organization owner cannot be removed.", "operationId": "removeOrganizationMember", "parameters": [ { "description": "Organization to remove the member from.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization to remove the member from.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "User account ID of the member to remove.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "user_id", "required": true, "schema": { "description": "User account ID of the member to remove.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoveOrganizationMemberResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Remove an organization member", "tags": [ "Organizations" ] }, "patch": { "description": "Update a member's role within an organization. Requires manage permission (owner or admin). The organization owner's role cannot be changed.", "operationId": "updateOrganizationMember", "parameters": [ { "description": "Organization the member belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "organization_id", "required": true, "schema": { "description": "Organization the member belongs to.\n Pattern: org_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "User account ID of the member to update.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "user_id", "required": true, "schema": { "description": "User account ID of the member to update.\n Pattern: user_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^user_[0-9a-hjkmnp-tv-z]{26}$", "title": "user_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "UpdateOrganizationMemberRequest identifies a member and the new role.", "properties": { "role": { "$ref": "#/components/schemas/OrganizationRole", "description": "New role for the member. Cannot be UNSPECIFIED or OWNER.\n OWNER transfer is not supported — the owner is set at organization creation.", "not": { "enum": [ 0, 1 ] }, "title": "role" } }, "required": [ "role" ], "title": "UpdateOrganizationMemberRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateOrganizationMemberResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Update an organization member", "tags": [ "Organizations" ] } }, "/v1beta/quota": { "get": { "description": "Returns the current quota status for an organization including usage, limits, tier, and reset date.", "operationId": "getOrganizationQuota", "parameters": [ { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.\n Only admins can query other organizations.", "in": "query", "name": "organization_id", "schema": { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.\n Only admins can query other organizations.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetOrganizationQuotaResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Get organization quota status", "tags": [ "Usage" ] } }, "/v1beta/quota/keys": { "get": { "description": "Returns all per-key quota configurations and current usage for an organization.", "operationId": "listAPIKeyQuotas", "parameters": [ { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "in": "query", "name": "organization_id", "schema": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListAPIKeyQuotasResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "List API key quotas", "tags": [ "Usage" ] } }, "/v1beta/quota/keys/{api_key_id}": { "delete": { "description": "Removes the per-key quota limit. The key will only be subject to the organization-level quota.", "operationId": "deleteAPIKeyQuota", "parameters": [ { "description": "The API key ID (required).", "in": "path", "name": "api_key_id", "required": true, "schema": { "description": "The API key ID (required).", "minLength": 1, "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" } }, { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "in": "query", "name": "organization_id", "schema": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteAPIKeyQuotaResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Delete API key quota", "tags": [ "Usage" ] }, "put": { "description": "Creates or updates a per-key quota limit. The key will be enforced independently of the organization quota.", "operationId": "setAPIKeyQuota", "parameters": [ { "description": "The API key ID (required).", "in": "path", "name": "api_key_id", "required": true, "schema": { "description": "The API key ID (required).", "minLength": 1, "pattern": "^key_[0-9a-hjkmnp-tv-z]{26}$", "title": "api_key_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "SetAPIKeyQuotaRequest creates or updates a per-key quota.", "properties": { "limit": { "description": "The limit for this key. Must be \u003e 0.", "exclusiveMinimum": 0, "format": "int32", "nullable": true, "title": "limit", "type": "integer" }, "organization_id": { "description": "Optional: organization ID. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "nullable": true, "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, "title": "SetAPIKeyQuotaRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetAPIKeyQuotaResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Set API key quota", "tags": [ "Usage" ] } }, "/v1beta/quota/usage": { "get": { "description": "Returns daily usage records for an organization within a specified date range.", "operationId": "getUsageHistory", "parameters": [ { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.", "in": "query", "name": "organization_id", "schema": { "description": "Optional: organization ID to query. If not provided, uses the caller's organization.", "example": "org_01h2xcejqtf2nbrexx3vqjhp41", "pattern": "^org_[0-9a-hjkmnp-tv-z]{26}$", "title": "organization_id", "type": "string" } }, { "description": "Filter by date.after (RFC 3339 format, e.g., 2024-01-15T09:30:00Z)", "in": "query", "name": "date.after", "schema": { "format": "date-time", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetUsageHistoryResponse" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Get usage history", "tags": [ "Usage" ] } }, "/v1beta/versions/{version_id}": { "get": { "description": "Retrieve a specific version by ID.", "operationId": "getVersion", "parameters": [ { "description": "Version ID to retrieve.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "version_id", "required": true, "schema": { "description": "Version ID to retrieve.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "version_id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Version" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Retrieve a version", "tags": [ "Versions" ], "x-speakeasy-name-override": "get" }, "patch": { "description": "Update version title and description.", "operationId": "updateVersion", "parameters": [ { "description": "Version ID to update.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "in": "path", "name": "version_id", "required": true, "schema": { "description": "Version ID to update.\n Pattern: ver_[0-9a-hjkmnp-tv-z]{26}", "pattern": "^ver_[0-9a-hjkmnp-tv-z]{26}$", "title": "version_id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": false, "description": "UpdateVersionRequest specifies fields to update on a version.", "properties": { "description": { "description": "New description.", "nullable": true, "title": "description", "type": "string" }, "title": { "description": "New title (max 255 characters).", "maxLength": 255, "nullable": true, "title": "title", "type": "string" } }, "title": "UpdateVersionRequest", "type": "object" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Version" } } }, "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimitExceeded" }, "500": { "$ref": "#/components/responses/InternalServerError" } }, "summary": "Update a version", "tags": [ "Versions" ], "x-speakeasy-name-override": "update" } } }, "security": [ { "bearerAuth": [] } ], "servers": [ { "description": "Production", "url": "https://api.factify.com" }, { "description": "Development (internal only)", "url": "https://api.factify-dev.com" } ], "tags": [ { "description": "Create, retrieve, update, and manage documents.", "name": "Documents" }, { "description": "Manage document versions and version history.", "name": "Versions" }, { "description": "Create and manage organizations and member invitations.", "name": "Organizations" }, { "description": "Generate and manage API keys for authentication.", "name": "API Keys" }, { "description": "Query API usage and quota information for your organization.", "name": "Usage" }, { "description": "Attach and manage access policies for documents.", "name": "Policies" }, { "description": "Generate shareable entry pages for documents.", "name": "Sharing \u0026 Distribution" } ] }