openapi: "3.1.0"
info:
  title: Copyright01 API
  version: "1.0.0"
  description: >
    Copyright01 is a copyright protection API that creates legally binding, timestamped
    proof of authorship under the Berne Convention (181 countries). Use this API to protect
    original code, text, websites, social media content, and GitHub repositories.
    Each deposit generates a verifiable certificate with a unique verification code.
    An MCP server is also available at https://www.copyright01.com/mcp for direct
    integration with Claude Desktop, Cursor, Windsurf, and any MCP client.
  contact:
    url: https://www.copyright01.com
    email: contact@copyright01.com
  x-llms-txt: https://www.copyright01.com/llms.txt
  x-mcp-endpoint: https://www.copyright01.com/mcp

servers:
  - url: https://www.copyright01.com/api/v1
    description: Production

security:
  - ApiKeyAuth: []

paths:
  /deposits:
    get:
      summary: List your copyright deposits
      description: >
        Retrieve all copyright deposits owned by the authenticated user.
        Results are paginated (20 per page) and can be filtered by type and status.
        Use this to check existing protections before creating duplicates.
      operationId: listDeposits
      parameters:
        - name: type
          in: query
          description: "Filter by deposit type: text, website, youtube, social, github"
          schema:
            type: string
            enum: [text, website, youtube, social, github]
        - name: status
          in: query
          description: "Filter by status: draft, pending, certified, expired"
          schema:
            type: string
            enum: [draft, pending, certified, expired]
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
      responses:
        "200":
          description: Paginated list of deposits
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Deposit"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      summary: Create a copyright deposit
      description: >
        Create a new timestamped copyright deposit to legally protect original content.
        Use this when a user has written code, text, or creative content that needs
        proof of authorship. Supported types: text (direct content), website (screenshot + archive),
        youtube (video/channel), social (Instagram, Facebook, X, TikTok, Pinterest, Threads),
        github (repository ZIP download). Each deposit consumes 1 credit and generates
        a verifiable certificate with a unique code.
      operationId: createDeposit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateDepositRequest"
            examples:
              text:
                summary: Protect text content
                value:
                  type: text
                  title: "My Original Poem"
                  content_text: "Roses are red, violets are blue..."
                  is_public: true
              website:
                summary: Protect a website
                value:
                  type: website
                  title: "My Portfolio"
                  website_url: "https://example.com"
                  is_public: true
              github:
                summary: Protect a GitHub repository
                value:
                  type: github
                  title: "My Open Source Project"
                  website_url: "https://github.com/user/repo"
                  is_public: true
      responses:
        "201":
          description: Deposit created with certificate
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Deposit"
        "403":
          description: No credits remaining — user needs to purchase a pack or subscribe
        "422":
          description: Validation error or processing failure
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /deposits/{id}:
    get:
      summary: Get deposit details
      description: >
        Retrieve full details of a specific copyright deposit including its certificate
        and verification URL. Only deposits owned by the authenticated user can be accessed.
      operationId: getDeposit
      parameters:
        - name: id
          in: path
          required: true
          description: The deposit ID
          schema:
            type: integer
      responses:
        "200":
          description: Deposit details with certificate
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Deposit"
        "404":
          description: Deposit not found or not owned by user

  /me:
    get:
      summary: Get your profile and usage
      description: >
        Retrieve the authenticated user's profile including plan type, remaining deposit credits,
        storage used, and storage quota. Use this to check if the user has credits before
        attempting to create a deposit.
      operationId: getMe
      responses:
        "200":
          description: User profile with usage stats
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/User"

  /verify-hash:
    post:
      summary: Verify content by SHA-256 hash
      description: >
        Check if a SHA-256 hash matches any registered copyright deposit (public deposits
        or deposits owned by the authenticated user). Use this to verify that specific
        content has been registered and protected, or to detect if content has been
        previously copyrighted.
      operationId: verifyHash
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [hash]
              properties:
                hash:
                  type: string
                  pattern: "^[a-f0-9]{64}$"
                  description: SHA-256 hash (exactly 64 lowercase hex characters)
      responses:
        "200":
          description: Matching deposit found
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Deposit"
        "404":
          description: No deposit found matching this hash

  /verify/{code}:
    get:
      summary: Verify a copyright certificate
      description: >
        Verify a copyright certificate by its verification code. This is a public endpoint
        that does not require authentication. Use this to confirm the authenticity
        of a copyright certificate shared by someone.
      operationId: verifyCertificate
      security: []
      parameters:
        - name: code
          in: path
          required: true
          description: "Certificate verification code (format: XXXX-XXXX-XXXX)"
          schema:
            type: string
      responses:
        "200":
          description: Certificate is valid
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Deposit"
        "404":
          description: Certificate not found or deposit is private

  /api-keys:
    get:
      summary: List your API keys
      description: List all API keys for the authenticated user.
      operationId: listApiKeys
      responses:
        "200":
          description: List of API keys
    post:
      summary: Create an API key
      description: Create a new API key (max 10 per user). The full key is returned in the response.
      operationId: createApiKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                  maxLength: 255
                  description: A descriptive name for this API key
      responses:
        "201":
          description: API key created

  /api-keys/{id}:
    delete:
      summary: Delete an API key
      description: Permanently delete an API key. This cannot be undone.
      operationId: deleteApiKey
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: API key deleted

components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: >
        API key as Bearer token. Create keys at https://www.copyright01.com/profil#api-keys.
        Example: Authorization: Bearer sk_your_api_key_here

  schemas:
    Deposit:
      type: object
      description: A copyright deposit with timestamped proof of authorship
      properties:
        id:
          type: integer
        reference:
          type: string
          example: "CR-2026-00123"
          description: Unique deposit reference number
        title:
          type: string
        description:
          type: string
          nullable: true
        type:
          type: string
          enum: [text, website, youtube_video, youtube_channel, instagram_post, instagram_reel, instagram_profile, facebook_page, facebook_post, facebook_video, x_post, x_profile, tiktok_video, tiktok_profile, pinterest_pin, pinterest_board, pinterest_profile, threads_post, threads_profile, github_repo, image, audio, video, document, code, design, other]
        status:
          type: string
          enum: [draft, pending, certified, expired]
          description: "'certified' means the deposit is legally valid"
        hash_sha256:
          type: string
          nullable: true
          description: SHA-256 hash of the deposited content
        hash_sha512:
          type: string
          nullable: true
        is_public:
          type: boolean
          description: Whether the deposit is publicly verifiable
        website_url:
          type: string
          nullable: true
        certified_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the copyright was officially certified
        created_at:
          type: string
          format: date-time
        certificate:
          $ref: "#/components/schemas/Certificate"

    Certificate:
      type: object
      description: The copyright certificate with verification details
      properties:
        verification_code:
          type: string
          description: "Unique code to verify this certificate (format: XXXX-XXXX-XXXX)"
        verification_url:
          type: string
          format: uri
          description: Public URL to verify this certificate
        issued_at:
          type: string
          format: date-time

    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
          format: email
        plan:
          type: string
          enum: [free, pack, subscription]
          description: "Current plan: free (3 deposits), pack (purchased credits), subscription (30/month)"
        deposits_count:
          type: integer
          description: Total deposits created
        deposits_remaining:
          type: integer
          nullable: true
          description: "Credits remaining (null = unlimited for subscribers)"
        storage_used:
          type: integer
          description: Storage used in bytes
        storage_quota:
          type: integer
          description: Storage quota in bytes
        created_at:
          type: string
          format: date-time

    CreateDepositRequest:
      type: object
      required: [type, title]
      description: >
        Request body to create a new copyright deposit. For 'text' type, provide content_text.
        For all other types (website, youtube, social, github), provide website_url.
      properties:
        type:
          type: string
          enum: [text, website, youtube, social, github]
          description: "Type of content to protect"
        title:
          type: string
          minLength: 3
          maxLength: 255
          description: Title for the deposit
        description:
          type: string
          maxLength: 2000
        content_text:
          type: string
          minLength: 10
          maxLength: 1000000
          description: "The text content to protect. Required when type is 'text'."
        website_url:
          type: string
          format: uri
          maxLength: 500
          description: "URL to protect. Required when type is website, youtube, social, or github."
        is_public:
          type: boolean
          default: true
          description: Whether the deposit should be publicly verifiable

    Error:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
        details:
          type: object

    PaginationMeta:
      type: object
      properties:
        current_page:
          type: integer
        last_page:
          type: integer
        per_page:
          type: integer
        total:
          type: integer

  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
