yams/docs/api/openapi.yaml
2025-08-10 23:41:49 -04:00

716 lines
18 KiB
YAML

openapi: 3.0.3
info:
title: YAMS Content Store API
description: |
HTTP REST API for the YAMS content-addressed storage system.
## Features
- Content-addressed storage with SHA-256 hashing
- Automatic deduplication
- Metadata management
- Batch operations
- Progress tracking
## Authentication
The API supports multiple authentication methods:
- **API Key**: Include `X-API-Key` header
- **Bearer Token**: Include `Authorization: Bearer <token>` header
- **Basic Auth**: Include `Authorization: Basic <base64>` header
version: 1.0.0
contact:
name: YAMS Team
url: https://github.com/trvon/yams
license:
name: Apache-2.0
url: https://www.apache.org/licenses/LICENSE-2.0
servers:
- url: http://localhost:8080/api/v1
description: Local development server
- url: https://api.yams.example.com/api/v1
description: Production server
security:
- ApiKeyAuth: []
- BearerAuth: []
tags:
- name: Content
description: Content storage and retrieval operations
- name: Metadata
description: Content metadata management
- name: Batch
description: Batch operations
- name: System
description: System information and health
paths:
/content:
post:
tags:
- Content
summary: Store content
description: Upload a file to the content store
operationId: storeContent
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
description: The file to upload
metadata:
type: string
description: JSON-encoded metadata
encoding:
file:
contentType: application/octet-stream
responses:
"201":
description: Content stored successfully
content:
application/json:
schema:
$ref: "#/components/schemas/StoreResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"500":
$ref: "#/components/responses/InternalError"
/content/{hash}:
parameters:
- $ref: "#/components/parameters/ContentHash"
get:
tags:
- Content
summary: Retrieve content
description: Download content by its hash
operationId: retrieveContent
parameters:
- name: Accept
in: header
description: |
Response format:
- `application/octet-stream` (default) - Returns the file
- `application/json` - Returns metadata only
schema:
type: string
enum:
- application/octet-stream
- application/json
responses:
"200":
description: Content retrieved successfully
content:
application/octet-stream:
schema:
type: string
format: binary
application/json:
schema:
$ref: "#/components/schemas/MetadataResponse"
"404":
$ref: "#/components/responses/NotFound"
"500":
$ref: "#/components/responses/InternalError"
delete:
tags:
- Content
summary: Delete content
description: Remove content from the store
operationId: deleteContent
responses:
"200":
description: Content deleted successfully
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteResponse"
"404":
$ref: "#/components/responses/NotFound"
"401":
$ref: "#/components/responses/Unauthorized"
"500":
$ref: "#/components/responses/InternalError"
head:
tags:
- Content
summary: Check if content exists
description: Check if content with given hash exists
operationId: checkExists
responses:
"204":
description: Content exists
"404":
description: Content not found
/content/{hash}/metadata:
parameters:
- $ref: "#/components/parameters/ContentHash"
get:
tags:
- Metadata
summary: Get metadata
description: Retrieve metadata for content
operationId: getMetadata
responses:
"200":
description: Metadata retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/MetadataResponse"
"404":
$ref: "#/components/responses/NotFound"
put:
tags:
- Metadata
summary: Update metadata
description: Update metadata for content
operationId: updateMetadata
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ContentMetadata"
responses:
"200":
description: Metadata updated successfully
content:
application/json:
schema:
$ref: "#/components/schemas/SuccessResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
/content/batch:
post:
tags:
- Batch
summary: Store multiple files
description: Upload multiple files in a single request
operationId: storeBatch
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BatchStoreRequest"
responses:
"200":
description: Batch operation completed
content:
application/json:
schema:
$ref: "#/components/schemas/BatchStoreResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
delete:
tags:
- Batch
summary: Delete multiple files
description: Remove multiple files by their hashes
operationId: deleteBatch
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BatchDeleteRequest"
responses:
"200":
description: Batch delete completed
content:
application/json:
schema:
$ref: "#/components/schemas/BatchDeleteResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
/content/search:
get:
tags:
- Content
summary: Search content
description: Search for content by metadata
operationId: searchContent
parameters:
- name: mimeType
in: query
description: Filter by MIME type
schema:
type: string
- name: namePattern
in: query
description: Filter by name pattern (regex)
schema:
type: string
- name: tags
in: query
description: Filter by tags (comma-separated)
schema:
type: string
- name: limit
in: query
description: Maximum results to return
schema:
type: integer
default: 100
minimum: 1
maximum: 1000
- name: offset
in: query
description: Number of results to skip
schema:
type: integer
default: 0
minimum: 0
responses:
"200":
description: Search results
content:
application/json:
schema:
$ref: "#/components/schemas/SearchResponse"
/content/stats:
get:
tags:
- System
summary: Get statistics
description: Retrieve storage statistics
operationId: getStats
responses:
"200":
description: Statistics retrieved
content:
application/json:
schema:
$ref: "#/components/schemas/StatsResponse"
/health:
get:
tags:
- System
summary: Health check
description: Check system health status
operationId: healthCheck
security: [] # No auth required
responses:
"200":
description: System is healthy
content:
application/json:
schema:
$ref: "#/components/schemas/HealthResponse"
"503":
description: System is unhealthy
content:
application/json:
schema:
$ref: "#/components/schemas/HealthResponse"
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: API key for authentication
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT bearer token
parameters:
ContentHash:
name: hash
in: path
required: true
description: SHA-256 hash of the content
schema:
type: string
pattern: "^[a-fA-F0-9]{64}$"
example: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
schemas:
ContentMetadata:
type: object
properties:
mimeType:
type: string
description: MIME type of the content
example: "application/pdf"
originalName:
type: string
description: Original filename
example: "document.pdf"
description:
type: string
description: Content description
tags:
type: array
items:
type: string
description: Tags for categorization
example: ["important", "work"]
customFields:
type: object
additionalProperties:
type: string
description: Custom metadata fields
encoding:
type: string
description: Character encoding (for text)
language:
type: string
description: Language code
version:
type: integer
description: Version number
default: 1
owner:
type: string
description: Owner identifier
permissions:
type: string
description: Permission string
StoreResult:
type: object
required:
- contentHash
- bytesStored
- bytesDeduped
- dedupRatio
- duration
properties:
contentHash:
type: string
description: SHA-256 hash of stored content
bytesStored:
type: integer
format: int64
description: Total bytes stored
bytesDeduped:
type: integer
format: int64
description: Bytes saved by deduplication
dedupRatio:
type: number
format: double
description: Deduplication ratio (0.0-1.0)
duration:
type: integer
format: int64
description: Operation duration in milliseconds
StoreResponse:
type: object
required:
- success
- data
properties:
success:
type: boolean
example: true
data:
$ref: "#/components/schemas/StoreResult"
MetadataResponse:
type: object
required:
- success
- data
properties:
success:
type: boolean
data:
type: object
properties:
hash:
type: string
metadata:
$ref: "#/components/schemas/ContentMetadata"
DeleteResponse:
type: object
required:
- success
- data
properties:
success:
type: boolean
data:
type: object
properties:
deleted:
type: boolean
hash:
type: string
BatchStoreRequest:
type: object
required:
- items
properties:
items:
type: array
items:
type: object
required:
- filename
- content
properties:
filename:
type: string
content:
type: string
format: base64
description: Base64-encoded file content
metadata:
$ref: "#/components/schemas/ContentMetadata"
BatchStoreResponse:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
items:
type: array
items:
type: object
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/StoreResult"
error:
type: string
BatchDeleteRequest:
type: object
required:
- hashes
properties:
hashes:
type: array
items:
type: string
pattern: "^[a-fA-F0-9]{64}$"
BatchDeleteResponse:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
items:
type: array
items:
type: object
properties:
hash:
type: string
deleted:
type: boolean
error:
type: string
SearchResponse:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
items:
type: array
items:
type: object
properties:
hash:
type: string
metadata:
$ref: "#/components/schemas/ContentMetadata"
total:
type: integer
limit:
type: integer
offset:
type: integer
ContentStats:
type: object
properties:
totalObjects:
type: integer
format: int64
totalBytes:
type: integer
format: int64
uniqueBlocks:
type: integer
format: int64
deduplicatedBytes:
type: integer
format: int64
dedupRatio:
type: number
format: double
storeOperations:
type: integer
format: int64
retrieveOperations:
type: integer
format: int64
deleteOperations:
type: integer
format: int64
lastOperation:
type: string
format: date-time
StatsResponse:
type: object
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/ContentStats"
HealthStatus:
type: object
properties:
isHealthy:
type: boolean
status:
type: string
warnings:
type: array
items:
type: string
errors:
type: array
items:
type: string
lastCheck:
type: string
format: date-time
HealthResponse:
type: object
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/HealthStatus"
SuccessResponse:
type: object
properties:
success:
type: boolean
example: true
message:
type: string
ErrorResponse:
type: object
required:
- error
- message
- code
properties:
error:
type: string
description: Error type
message:
type: string
description: Human-readable error message
code:
type: integer
description: HTTP status code
requestId:
type: string
description: Request ID for tracking
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: Bad Request
message: Invalid request parameters
code: 400
requestId: 123e4567-e89b-12d3-a456-426614174000
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: Unauthorized
message: Invalid or missing authentication credentials
code: 401
requestId: 123e4567-e89b-12d3-a456-426614174000
NotFound:
description: Not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: Not Found
message: Content not found
code: 404
requestId: 123e4567-e89b-12d3-a456-426614174000
InternalError:
description: Internal server error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: Internal Server Error
message: An unexpected error occurred
code: 500
requestId: 123e4567-e89b-12d3-a456-426614174000