{
  "openapi": "3.1.0",
  "info": {
    "title": "BotDigit Developer Platform API",
    "version": "1.0.0",
    "description": "Official, production-grade Developer Platform for Freelancers, Agencies, and Authorized AI Agents. Guided by the core principle: Autonomous for discovery and analysis. Human-controlled for commitments.",
    "contact": {
      "name": "BotDigit Platform Engineering",
      "url": "https://developer.botdigit.com"
    }
  },
  "servers": [
    {
      "url": "https://api.botdigit.com/api/developer/v1",
      "description": "Production API Server"
    },
    {
      "url": "https://api-staging.botdigit.com/api/developer/v1",
      "description": "Staging API Server"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    },
    {
      "ApiKeyAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Personal Access Token (`bdt_pat_...`) or Agency Token (`bdt_app_...`) passed in Authorization header."
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "API Key header alternative for environments where Authorization header is reserved."
      }
    },
    "schemas": {
      "DeveloperErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "nullable": true
              },
              "details": {
                "type": "object",
                "nullable": true
              },
              "documentation_url": {
                "type": "string",
                "nullable": true
              }
            }
          }
        }
      },
      "DeveloperProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "priority": {
            "type": "string"
          },
          "skills_required": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "duration": {
            "type": "string",
            "nullable": true
          },
          "experience_level": {
            "type": "string"
          },
          "project_type": {
            "type": "string"
          },
          "budget_min": {
            "type": "string",
            "nullable": true
          },
          "budget_max": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "bid_count": {
            "type": "integer"
          },
          "client": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "display_name": {
                "type": "string"
              },
              "avatar_url": {
                "type": "string",
                "nullable": true
              },
              "member_since": {
                "type": "string",
                "format": "date-time"
              },
              "total_projects_posted": {
                "type": "integer"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StageProposalDraftRequest": {
        "type": "object",
        "required": [
          "bid_amount",
          "delivery_days",
          "proposal_text"
        ],
        "properties": {
          "bid_amount": {
            "type": "string",
            "description": "Proposed bid amount in decimal format, e.g. '1500.00'"
          },
          "delivery_days": {
            "type": "integer",
            "minimum": 1
          },
          "proposal_text": {
            "type": "string"
          },
          "proposed_milestones": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "title",
                "amount"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "amount": {
                  "type": "string"
                },
                "duration_days": {
                  "type": "integer"
                }
              }
            }
          },
          "ai_agent_id": {
            "type": "string",
            "description": "Identifier of the agent or model proposing this draft"
          },
          "ai_agent_notes": {
            "type": "string"
          }
        }
      },
      "DeveloperProposalDraft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "freelancer_id": {
            "type": "string",
            "format": "uuid"
          },
          "token_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "bid_amount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "delivery_days": {
            "type": "integer"
          },
          "proposal_text": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_approval",
              "approved",
              "rejected"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StageMessageDraftRequest": {
        "type": "object",
        "required": [
          "content"
        ],
        "properties": {
          "content": {
            "type": "string"
          },
          "ai_agent_id": {
            "type": "string"
          }
        }
      },
      "DeveloperMessageDraft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "sender_id": {
            "type": "string",
            "format": "uuid"
          },
          "content": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_approval",
              "approved",
              "rejected"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWebhookSubscriptionRequest": {
        "type": "object",
        "required": [
          "target_url",
          "subscribed_events"
        ],
        "properties": {
          "target_url": {
            "type": "string",
            "format": "uri"
          },
          "subscribed_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "CreateWebhookSubscriptionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "target_url": {
            "type": "string"
          },
          "subscribed_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "secret_key": {
            "type": "string",
            "description": "Secret key displayed once with prefix 'whsec_'"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProjectBid": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "freelancer_id": {
            "type": "string",
            "format": "uuid"
          },
          "bid_amount": {
            "type": "string",
            "example": "450.00"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "delivery_days": {
            "type": "integer",
            "example": 5
          },
          "proposal": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "withdrawn",
              "rejected",
              "awarded"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MessageDraft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "author_id": {
            "type": "string",
            "format": "uuid"
          },
          "content": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_approval",
              "sent",
              "rejected"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  },
  "paths": {
    "/projects": {
      "get": {
        "summary": "List Sanitized Marketplace Projects",
        "description": "Discover open marketplace projects. Excludes internal scoring and private client data.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skills",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_budget",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "max_budget",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "project_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of sanitized projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DeveloperProject"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{project_id}": {
      "get": {
        "summary": "Get Sanitized Project Details",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sanitized project details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeveloperProject"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{project_id}/proposals/drafts": {
      "post": {
        "summary": "Stage Proposal Draft (AI Agent)",
        "description": "Stages a proposal draft for human review. Consumes 0 bid quota. Supports 'Idempotency-Key' header.",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StageProposalDraftRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Proposal draft staged awaiting human review",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeveloperProposalDraft"
                }
              }
            }
          }
        }
      }
    },
    "/proposals/drafts": {
      "get": {
        "summary": "List Staged Proposal Drafts",
        "description": "List proposal drafts created by AI agents for the authenticated freelancer.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending_approval",
                "approved",
                "rejected"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of drafts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DeveloperProposalDraft"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/proposals/drafts/{draft_id}/approve": {
      "post": {
        "summary": "Human Approve Proposal Draft",
        "description": "Human approves the draft, triggering domain validation, KYC check, quota deduction, and client notification.",
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Proposal approved and successfully submitted to client"
          }
        }
      }
    },
    "/proposals/drafts/{draft_id}/reject": {
      "post": {
        "summary": "Reject Proposal Draft",
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Proposal draft rejected"
          }
        }
      }
    },
    "/messages/threads": {
      "get": {
        "summary": "List Conversation Threads",
        "description": "List conversation threads the authenticated developer/freelancer is a participant in.",
        "responses": {
          "200": {
            "description": "List of user threads"
          }
        }
      }
    },
    "/messages/threads/{thread_id}": {
      "get": {
        "summary": "Get Messages in Thread",
        "parameters": [
          {
            "name": "thread_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Thread messages"
          }
        }
      }
    },
    "/messages/threads/{thread_id}/drafts": {
      "post": {
        "summary": "Stage Message Draft (AI Agent)",
        "description": "Stages a message draft for client conversation awaiting human approval.",
        "parameters": [
          {
            "name": "thread_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StageMessageDraftRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message draft staged",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeveloperMessageDraft"
                }
              }
            }
          }
        }
      }
    },
    "/messages/drafts/{draft_id}/approve": {
      "post": {
        "summary": "Human Approve and Send Message Draft",
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Message approved and dispatched"
          }
        }
      }
    },
    "/contracts": {
      "get": {
        "summary": "List User Contracts",
        "description": "List contracts where the authenticated user is either freelancer or client (IDOR safe).",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contracts"
          }
        }
      }
    },
    "/contracts/{contract_id}": {
      "get": {
        "summary": "Get Contract Details",
        "parameters": [
          {
            "name": "contract_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contract details"
          },
          "404": {
            "description": "Not found or unauthorized"
          }
        }
      }
    },
    "/contracts/{contract_id}/milestones": {
      "get": {
        "summary": "List Milestones for Contract",
        "parameters": [
          {
            "name": "contract_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contract milestones"
          }
        }
      }
    },
    "/contracts/milestones/{milestone_id}/delivery-drafts": {
      "post": {
        "summary": "Stage Milestone Delivery Draft",
        "description": "Allows an AI agent to stage completed milestone work and attachments for freelancer review prior to formal submission.",
        "parameters": [
          {
            "name": "milestone_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "work_summary"
                ],
                "properties": {
                  "work_summary": {
                    "type": "string"
                  },
                  "attachment_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "ai_agent_id": {
                    "type": "string"
                  },
                  "ai_agent_notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Staged delivery draft awaiting human review"
          }
        }
      }
    },
    "/contracts/delivery-drafts": {
      "get": {
        "summary": "List Staged Delivery Drafts",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending_approval",
                "approved",
                "rejected"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery drafts list"
          }
        }
      }
    },
    "/contracts/delivery-drafts/{draft_id}/approve": {
      "post": {
        "summary": "Human Approval & Formal Submission of Delivery Draft",
        "description": "Submits milestone work to client, marks milestone status submitted, and notifies client.",
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Milestone submitted successfully"
          }
        }
      }
    },
    "/contracts/delivery-drafts/{draft_id}/reject": {
      "post": {
        "summary": "Reject Staged Delivery Draft",
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery draft rejected"
          }
        }
      }
    },
    "/workspaces": {
      "get": {
        "summary": "List Workspaces (Agency & Enterprise)",
        "responses": {
          "200": {
            "description": "List of accessible workspaces"
          }
        }
      }
    },
    "/workspaces/{workspace_id}": {
      "get": {
        "summary": "Get Workspace Details",
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace details"
          }
        }
      }
    },
    "/workspaces/{workspace_id}/members": {
      "get": {
        "summary": "List Workspace Team Members & Seats",
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of workspace team seats"
          }
        }
      }
    },
    "/workspaces/{workspace_id}/projects": {
      "get": {
        "summary": "List Projects in Workspace",
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace projects"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "summary": "List Webhook Subscriptions",
        "responses": {
          "200": {
            "description": "List of active webhook subscriptions"
          }
        }
      },
      "post": {
        "summary": "Create Webhook Subscription",
        "description": "Registers a new webhook destination with SSRF protection and unique HMAC-SHA256 signing secret.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook subscription created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWebhookSubscriptionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}": {
      "delete": {
        "summary": "Delete Webhook Subscription",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook subscription deleted"
          }
        }
      }
    },
    "/webhooks/test-ping": {
      "post": {
        "summary": "Dispatch Test Webhook Ping",
        "responses": {
          "200": {
            "description": "Ping dispatched"
          }
        }
      }
    },
    "/proposals/bids": {
      "get": {
        "tags": [
          "Proposals"
        ],
        "summary": "List my submitted bids",
        "description": "Returns all active marketplace bids submitted by the authenticated freelancer.",
        "operationId": "listMyBids",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of submitted bids",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProjectBid"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/proposals/bids/{project_id}": {
      "get": {
        "tags": [
          "Proposals"
        ],
        "summary": "Get my bid for project",
        "description": "Fetch the authenticated freelancer active bid for a specific project.",
        "operationId": "getProjectBid",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Target project UUID"
          }
        ],
        "responses": {
          "200": {
            "description": "Active bid or null if none",
            "content": {
              "application/json": {
                "schema": {
                  "nullable": true,
                  "$ref": "#/components/schemas/ProjectBid"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/messages/drafts": {
      "get": {
        "tags": [
          "Messages"
        ],
        "summary": "List staged message drafts",
        "description": "Lists message drafts staged by AI agents awaiting human approval before dispatch.",
        "operationId": "listMessageDrafts",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "thread_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter drafts by conversation thread"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending_approval",
                "sent",
                "rejected"
              ]
            },
            "description": "Filter by approval status"
          }
        ],
        "responses": {
          "200": {
            "description": "List of staged message drafts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MessageDraft"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/messages/drafts/{draft_id}/reject": {
      "post": {
        "tags": [
          "Messages"
        ],
        "summary": "Reject staged message draft",
        "description": "Rejects and archives a staged AI message draft without dispatching to the client.",
        "operationId": "rejectMessageDraft",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Staged message draft UUID"
          }
        ],
        "responses": {
          "200": {
            "description": "Message draft successfully rejected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Message draft rejected"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  }
}
