openapi: 3.1.0
info:
  title: Cratio CRM API
  version: 1.0.0
  description: |
    REST API for Cratio CRM. Push and pull leads, log calls, and automate workflows.
    6 endpoints. No SDK needed.

    **Authentication:** Bearer token in the Authorization header.
    Keys start with `le_live_`. Generate from Settings → Integrations → API.

    **Rate limit:** 100 requests per minute per key. Exceeded requests receive 429.

    **Base URL:** https://api.cratio.com
  contact:
    name: Cratio Support
    url: https://cratio.com/help

servers:
  - url: https://api.cratio.com
    description: Production

security:
  - bearerAuth: []

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: "API key starting with le_live_. Generate from Settings → Integrations → API."

  schemas:
    Lead:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier
        name:
          type: string
          description: Full name
        email:
          type: ["string", "null"]
          description: Email address
        phone:
          type: ["string", "null"]
          description: Phone number
        company:
          type: ["string", "null"]
          description: Company or organisation
        city:
          type: ["string", "null"]
          description: City
        source:
          type: string
          description: Lead source (e.g., API, IVR, Facebook Ads)
        status:
          type: string
          enum: [New, Contacted, Qualified, Proposal, Won, Lost]
          description: Lead status
        priority:
          type: string
          enum: [Low, Medium, High]
          description: Lead priority
        tags:
          type: array
          items:
            type: string
          description: Array of string tags
        deal_value:
          type: ["number", "null"]
          description: Expected value in INR
        notes:
          type: ["string", "null"]
          description: Free-text notes
        assigned_to:
          type: ["string", "null"]
          description: Assigned user email
        created_at:
          type: string
          format: date-time
          description: ISO 8601 UTC creation timestamp
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 UTC last-modified timestamp

    CallLog:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier
        lead_id:
          type: string
          format: uuid
          description: Parent lead UUID
        call_type:
          type: string
          enum: [Inbound, Outbound]
          description: Call direction
        duration_seconds:
          type: integer
          description: Duration in seconds. 0 = missed.
        outcome:
          type: string
          enum: [Completed, Busy, "No Answer", Voicemail, Missed]
          description: Call outcome
        notes:
          type: ["string", "null"]
          description: Call notes
        called_at:
          type: string
          format: date-time
          description: ISO 8601 UTC timestamp of the call
        created_at:
          type: string
          format: date-time
          description: ISO 8601 UTC creation timestamp

    Pagination:
      type: object
      properties:
        limit:
          type: integer
        offset:
          type: integer
        total:
          type: integer
        has_more:
          type: boolean

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            field:
              type: string
              description: Present when the error is tied to a specific parameter

paths:
  /api/v1/leads:
    get:
      operationId: listLeads
      summary: List leads
      description: Retrieve leads with optional filters. Default returns last 30 days, limit 50.
      tags: [Leads]
      parameters:
        - name: from_date
          in: query
          schema:
            type: string
            format: date
          description: Leads created on or after this date (YYYY-MM-DD, IST)
        - name: to_date
          in: query
          schema:
            type: string
            format: date
          description: Leads created on or before this date (YYYY-MM-DD, IST)
        - name: status
          in: query
          schema:
            type: string
            enum: [New, Contacted, Qualified, Proposal, Won, Lost]
          description: Filter by status
        - name: source
          in: query
          schema:
            type: string
          description: Filter by lead source
        - name: priority
          in: query
          schema:
            type: string
            enum: [Low, Medium, High]
          description: Filter by priority
        - name: assigned_to
          in: query
          schema:
            type: string
          description: Filter by assigned user email
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 500
          description: Number of results to return
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
          description: Pagination offset
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Lead"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the rate limit resets

    post:
      operationId: createLead
      summary: Create a lead
      description: |
        Create a new lead. If a lead with the same phone or email already exists,
        the record is merged and updated (200 returned instead of 201).
        Minimum required: name + phone or email.
      tags: [Leads]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                company:
                  type: string
                city:
                  type: string
                source:
                  type: string
                  default: API
                status:
                  type: string
                  enum: [New, Contacted, Qualified, Proposal, Won, Lost]
                  default: New
                priority:
                  type: string
                  enum: [Low, Medium, High]
                  default: Medium
                tags:
                  type: array
                  items:
                    type: string
                deal_value:
                  type: number
                notes:
                  type: string
                assigned_to:
                  type: string
      responses:
        "201":
          description: Lead created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Lead"
        "200":
          description: Existing lead merged and updated (duplicate phone/email)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Lead"
        "400":
          description: Invalid parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden (missing Write permission or non-whitelisted IP)

  /api/v1/leads/{id}:
    delete:
      operationId: deleteLead
      summary: Delete a lead
      description: |
        Permanently delete a lead by UUID. Deletes all associated activities,
        call logs, and notes. This action is irreversible.
      tags: [Leads]
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Lead UUID
      responses:
        "200":
          description: Lead deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      deleted:
                        type: boolean
        "401":
          description: Unauthorized
        "403":
          description: Forbidden (missing Delete permission)
        "404":
          description: Lead not found

  /api/v1/call-logs:
    get:
      operationId: listCallLogs
      summary: List call logs
      description: Retrieve call logs. Default returns last 30 days, limit 50.
      tags: [Call Logs]
      parameters:
        - name: from_date
          in: query
          schema:
            type: string
            format: date
          description: Calls on or after this date (YYYY-MM-DD, IST)
        - name: to_date
          in: query
          schema:
            type: string
            format: date
          description: Calls on or before this date (YYYY-MM-DD, IST)
        - name: lead_id
          in: query
          schema:
            type: string
            format: uuid
          description: Filter by lead UUID
        - name: call_type
          in: query
          schema:
            type: string
            enum: [Inbound, Outbound]
          description: Filter by call direction
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 500
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/CallLog"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
        "401":
          description: Unauthorized
        "429":
          description: Rate limit exceeded

    post:
      operationId: createCallLog
      summary: Log a call
      description: Log a call against a lead. Use duration_seconds 0 for missed calls.
      tags: [Call Logs]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [lead_id, call_type, duration_seconds]
              properties:
                lead_id:
                  type: string
                  format: uuid
                call_type:
                  type: string
                  enum: [Inbound, Outbound]
                duration_seconds:
                  type: integer
                  minimum: 0
                outcome:
                  type: string
                  enum: [Completed, Busy, "No Answer", Voicemail, Missed]
                  default: Completed
                notes:
                  type: string
                called_at:
                  type: string
                  format: date-time
                  description: Defaults to now if omitted
      responses:
        "201":
          description: Call log created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CallLog"
        "400":
          description: Invalid parameters
        "401":
          description: Unauthorized
        "403":
          description: Forbidden (missing Write permission)

  /api/v1/call-logs/{id}:
    delete:
      operationId: deleteCallLog
      summary: Delete a call log
      description: Permanently delete a call log by UUID.
      tags: [Call Logs]
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Call log UUID
      responses:
        "200":
          description: Call log deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      deleted:
                        type: boolean
        "401":
          description: Unauthorized
        "403":
          description: Forbidden (missing Delete permission)
        "404":
          description: Call log not found
