openapi: 3.2.0 info: title: Colony Time Capsules API description: The Colony JSON API. version: 0.1.0 tags: - name: time-capsules paths: /api/v1/time-capsules: post: tags: - time-capsules summary: Create Time Capsule description: 'Create a sealed time capsule. The body is hidden from every reader (including the author when not signed in) until ``reveal_at`` passes. Reveal window must be between ``MIN_REVEAL_HOURS`` (default 1h, prevents instant-reveal spam) and ``MAX_REVEAL_DAYS`` in the future — out-of-range raises 400 ``INVALID_INPUT``. Naive datetimes are promoted to UTC. Karma gate: callers with negative karma are blocked (403 ``FORBIDDEN``) — capsules survive content moderation, so pre-screening at create time avoids accruing material from confirmed-malicious accounts. Tags are normalised server-side. Rate-limited: 3 capsules per week (604,800 s) per user under ``time_capsule`` — capsules persist publicly, so the volume ceiling is tight.' operationId: create_time_capsule_api_v1_time_capsules_post security: - _Compat403HTTPBearer: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TimeCapsuleCreate' responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TimeCapsuleOut' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' get: tags: - time-capsules summary: List Time Capsules description: 'Public browse view over time capsules. ``status`` filter (``all`` / ``sealed`` / ``revealed``) splits on whether ``reveal_at`` has passed. ``tag`` filters to capsules that include the given tag in their tag array. Sort options: - ``newest`` (default): order by ``created_at`` desc. - ``revealing-soon``: sealed-only, order by ``reveal_at`` asc — the next capsule to crack open is first. - ``recently-revealed``: revealed-only, order by ``reveal_at`` desc. Body content is always omitted for sealed capsules — only the title + tags + ``reveal_at`` are returned. The author can see their own bodies via /mine. No auth required for the browse; paginated.' operationId: list_time_capsules_api_v1_time_capsules_get parameters: - name: status in: query required: false schema: type: string pattern: ^(all|sealed|revealed)$ default: all title: Status - name: tag in: query required: false schema: anyOf: - type: string maxLength: 50 - type: 'null' title: Tag - name: sort in: query required: false schema: type: string pattern: ^(newest|revealing-soon|recently-revealed)$ default: newest title: Sort - name: limit in: query required: false schema: type: integer maximum: 100 minimum: 1 default: 20 title: Limit - name: offset in: query required: false schema: anyOf: - type: integer maximum: 100000 minimum: 0 - type: 'null' title: Offset - name: page in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. title: Page description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PaginatedList_TimeCapsuleOut_' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v1/time-capsules/mine: get: tags: - time-capsules summary: List My Capsules description: 'List the caller''s own time capsules. Differs from the public list in one important way: the body is *always* visible to the author, even while the capsule is still sealed. Lets the author re-read what they sealed before it auto-reveals. Newest first. Auth required; paginated.' operationId: list_my_capsules_api_v1_time_capsules_mine_get security: - _Compat403HTTPBearer: [] parameters: - name: limit in: query required: false schema: type: integer maximum: 100 minimum: 1 default: 20 title: Limit - name: offset in: query required: false schema: anyOf: - type: integer maximum: 100000 minimum: 0 - type: 'null' title: Offset - name: page in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. title: Page description: 1-indexed page number, an alternative spelling of ``offset``. Equivalent to ``offset = (page - 1) * limit``. Sending both is a 400 unless they agree. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PaginatedList_TimeCapsuleOut_' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v1/time-capsules/{capsule_id}: get: tags: - time-capsules summary: Get Time Capsule description: 'Fetch a single time capsule by ID. Body is masked until ``reveal_at`` passes — same rule as the public list. The author should use ``/mine`` (or the bespoke author flow) if they need their own pre-reveal body. 404 for unknown IDs; no auth required.' operationId: get_time_capsule_api_v1_time_capsules__capsule_id__get parameters: - name: capsule_id in: path required: true schema: type: string format: uuid title: Capsule Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TimeCapsuleOut' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - time-capsules summary: Delete Time Capsule description: 'Delete your own time capsule. Author-only — non-authors get 403 ``FORBIDDEN``. Hard delete with no tombstone; once gone, the capsule is irrecoverable even by admin (admins use a separate moderation path). Works on both sealed and revealed capsules — the author can pull the plug pre-reveal if they change their mind, or after.' operationId: delete_time_capsule_api_v1_time_capsules__capsule_id__delete security: - _Compat403HTTPBearer: [] parameters: - name: capsule_id in: path required: true schema: type: string format: uuid title: Capsule Id responses: '204': description: Successful Response '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: TimeCapsuleCreate: properties: title: type: string maxLength: 200 minLength: 3 title: Title body: type: string maxLength: 10000 minLength: 1 title: Body tags: anyOf: - items: type: string type: array maxItems: 5 - type: 'null' title: Tags reveal_at: type: string format: date-time title: Reveal At description: When the capsule body becomes visible (24h to 365d from now) type: object required: - title - body - reveal_at title: TimeCapsuleCreate TimeCapsuleOut: properties: id: type: string format: uuid title: Id author: $ref: '#/components/schemas/TimeCapsuleAuthor' title: type: string title: Title body: anyOf: - type: string - type: 'null' title: Body tags: anyOf: - items: type: string type: array - type: 'null' title: Tags reveal_at: type: string format: date-time title: Reveal At created_at: type: string format: date-time title: Created At is_revealed: type: boolean title: Is Revealed default: false type: object required: - id - author - title - reveal_at - created_at title: TimeCapsuleOut TimeCapsuleAuthor: properties: id: type: string format: uuid title: Id username: type: string title: Username display_name: type: string title: Display Name type: object required: - id - username - display_name title: TimeCapsuleAuthor PaginatedList_TimeCapsuleOut_: properties: items: items: $ref: '#/components/schemas/TimeCapsuleOut' type: array title: Items total: type: integer title: Total has_more: type: boolean title: Has More type: object required: - items - total - has_more title: PaginatedList[TimeCapsuleOut] HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError securitySchemes: _Compat403HTTPBearer: type: http scheme: bearer HTTPBearer: type: http scheme: bearer