openapi: 3.0.3
info:
  title: CocoCloud Drive API
  version: "1.0.0"
  description: >
    REST API for CocoCloud Drive built on Laravel Sanctum. All authenticated requests
    must include a bearer token generated via login or the developer token endpoint.
servers:
  - url: https://cococloud-drive.com
    description: Production
  - url: http://localhost
    description: Local
tags:
  - name: System
  - name: Auth
  - name: Profile
  - name: Notifications
  - name: Files
  - name: Uploads
  - name: Developer Tokens
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Sanctum
  schemas:
    User:
      type: object
      properties:
        id: { type: integer }
        firstname: { type: string }
        lastname: { type: string }
        username: { type: string }
        email: { type: string, format: email }
        email_verified: { type: boolean }
        avatar: { type: string, nullable: true }
        mobile: { type: string, nullable: true }
        address:
          type: object
          additionalProperties: true
        subscription:
          type: object
          nullable: true
          properties:
            plan_id: { type: integer, nullable: true }
            status: { type: boolean, nullable: true }
            expiry_at: { type: string, format: date-time, nullable: true }
paths:
  /api/v1/status:
    get:
      tags: [System]
      summary: Public system status
      responses:
        "200":
          description: Status payload
  /api/v1/auth/register:
    post:
      tags: [Auth]
      summary: Register a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [firstname, lastname, username, email, password, password_confirmation, country]
              properties:
                firstname: { type: string }
                lastname: { type: string }
                username: { type: string }
                email: { type: string, format: email }
                password: { type: string, format: password }
                password_confirmation: { type: string, format: password }
                country: { type: integer }
      responses:
        "201": { description: Created }
  /api/v1/auth/login:
    post:
      tags: [Auth]
      summary: Login and obtain token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email: { type: string, format: email }
                password: { type: string, format: password }
                device_name: { type: string }
      responses:
        "200": { description: Logged in }
  /api/v1/auth/logout:
    post:
      tags: [Auth]
      security: [{ BearerAuth: [] }]
      summary: Revoke current token
      responses:
        "200": { description: Logged out }
  /api/v1/me:
    get:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Fetch authenticated profile
      responses:
        "200":
          description: Profile details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      user:
                        $ref: "#/components/schemas/User"
    put:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Update profile
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "200": { description: Updated }
  /api/v1/me/password:
    put:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Update password
      responses:
        "200": { description: Updated }
  /api/v1/me/2fa/setup:
    post:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Generate 2FA secret
      responses:
        "200": { description: Secret generated }
  /api/v1/me/2fa/enable:
    post:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Enable 2FA
      responses:
        "200": { description: Enabled }
  /api/v1/me/2fa/disable:
    post:
      tags: [Profile]
      security: [{ BearerAuth: [] }]
      summary: Disable 2FA
      responses:
        "200": { description: Disabled }
  /api/v1/notifications:
    get:
      tags: [Notifications]
      security: [{ BearerAuth: [] }]
      summary: List notifications
      responses:
        "200": { description: List }
  /api/v1/notifications/read-all:
    post:
      tags: [Notifications]
      security: [{ BearerAuth: [] }]
      summary: Mark all as read
      responses:
        "200": { description: Done }
  /api/v1/notifications/{notification}:
    delete:
      tags: [Notifications]
      security: [{ BearerAuth: [] }]
      summary: Delete notification
      parameters:
        - in: path
          name: notification
          required: true
          schema: { type: integer }
      responses:
        "200": { description: Deleted }
  /api/v1/files:
    get:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: List files
      parameters:
        - in: query
          name: search
          schema: { type: string }
      responses:
        "200": { description: Files list }
  /api/v1/files/{shared_id}:
    get:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: Show a file
      parameters:
        - in: path
          name: shared_id
          required: true
          schema: { type: string }
      responses:
        "200": { description: File }
    patch:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: Update metadata
      responses:
        "200": { description: Updated }
    delete:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: Delete file
      responses:
        "200": { description: Deleted }
  /api/v1/files/bulk/delete:
    post:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: Bulk delete
      responses:
        "200": { description: Deleted }
  /api/v1/files/{shared_id}/download-link:
    post:
      tags: [Files]
      security: [{ BearerAuth: [] }]
      summary: Generate download link
      responses:
        "200": { description: Link }
  /api/v1/uploads:
    post:
      tags: [Uploads]
      security: [{ BearerAuth: [] }]
      summary: Upload file
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [file, upload_auto_delete]
              properties:
                file:
                  type: string
                  format: binary
                upload_auto_delete:
                  type: integer
                password:
                  type: string
      responses:
        "201": { description: Uploaded }
  /api/v1/developer/tokens:
    get:
      tags: [Developer Tokens]
      security: [{ BearerAuth: [] }]
      summary: List tokens
      responses:
        "200": { description: Tokens }
    post:
      tags: [Developer Tokens]
      security: [{ BearerAuth: [] }]
      summary: Create token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, abilities]
              properties:
                name: { type: string }
                abilities:
                  type: array
                  items: { type: string }
                expires_at: { type: string, format: date-time, nullable: true }
      responses:
        "201": { description: Created }
  /api/v1/developer/tokens/{token}:
    delete:
      tags: [Developer Tokens]
      security: [{ BearerAuth: [] }]
      summary: Revoke token
      parameters:
        - in: path
          name: token
          required: true
          schema: { type: integer }
      responses:
        "200": { description: Revoked }
