openapi: 3.1.0
info:
  title: Tango Budget Outbound API
  version: "0.3"
  description: |
    Async **delta** REST API: client GETs newly-approved or updated budget
    line items from Tango. Paginated (page_size 5000, page_no parameter).
    Null fields are omitted from the JSON.

    NOTE: source's `integration type` header says "space Area outBOUND api"
    while the document title is "BUDGET outbound API". The descriptive
    content (project budget lines, tasks, milestones) clearly indicates
    budgets, not space areas — assumed a stale header. Flagged in Open
    Questions.
  x-direction: outbound
  x-source: Tango
  x-destination: Client System
servers:
  - url: https://api.tangoanalytics.com
    description: Production
  - url: https://testapi.tangoanalytics.com
    description: Test (SIT/UAT)
tags:
  - name: Budgets (Delta)
  - name: Status
paths:
  /v1/projectmgmt/delta/budgets:
    get:
      summary: Initiate delta budget export (async)
      operationId: getBudgetsDelta
      tags: [Budgets (Delta)]
      parameters:
        - $ref: "#/components/parameters/XClient"
        - $ref: "#/components/parameters/XApiKey"
      responses:
        "200":
          description: Async ack with gu_id.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AcceptedResponse"
  /v1/batch/status:
    get:
      summary: Retrieve paginated budget records by gu_id
      operationId: getBudgetsByGuId
      tags: [Status]
      parameters:
        - $ref: "#/components/parameters/XClient"
        - $ref: "#/components/parameters/XApiKey"
        - in: query
          name: gu_id
          required: true
          schema: { type: string, format: uuid }
        - in: query
          name: page_no
          required: false
          schema: { type: integer, minimum: 1 }
          description: Page number; defaults to 1 if omitted (5000 records/page).
      responses:
        "200":
          description: Paginated budget records.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BudgetPage"
components:
  securitySchemes:
    xClientHeader: { type: apiKey, in: header, name: x-client }
    xApiKeyHeader: { type: apiKey, in: header, name: x-api-key }
  parameters:
    XClient:
      name: x-client
      in: header
      required: true
      schema: { type: string }
    XApiKey:
      name: x-api-key
      in: header
      required: true
      schema: { type: string }
  schemas:
    AcceptedResponse:
      type: object
      required: [status]
      properties:
        status: { type: string, enum: [OK, Error] }
        status_message: { type: string }
        gu_id: { type: string, format: uuid }
    BudgetPage:
      type: object
      required: [status, total_records, total_pages, page_size, page_no, records]
      properties:
        status: { type: string, enum: [PROCESSING, COMPLETED, ERROR] }
        total_records: { type: integer }
        total_pages: { type: integer }
        page_size: { type: integer, default: 5000 }
        page_no: { type: integer }
        records:
          type: array
          items:
            $ref: "#/components/schemas/BudgetRecord"
    BudgetRecord:
      type: object
      properties:
        transaction_type:
          type: string
          enum: [NEW, UPDATE]
          description: "NEW for newly approved budget; UPDATE for changes to an existing budget."
        entity_type: { type: string, description: "e.g., PROJECT." }
        project_number: { type: string }
        store_number:
          type: string
          description: Store or site number, depending on the entity the project was created from.
        ownership_type: { type: string, description: "e.g., Owned, Leased." }
        budget_id: { type: number }
        line_number: { type: number }
        client_unique_num: { type: string }
        milsetone_name:
          type: string
          description: |
            NOTE: typo in source (`milsetone_name` rather than `milestone_name`).
            Preserved verbatim — Client Label is "Template Name".
        task_start_date: { type: string, description: "MM/DD/YYYY." }
        task_completion_date: { type: string, description: "MM/DD/YYYY." }
        task_description: { type: string }
        division: { type: string, description: "e.g., Construction Hard Costs." }
        task_number:
          type: string
          description: |
            Source data-mapping table types as NUMBER but sample shows `TSK125`
            (alphanumeric). Schema uses string; flagged in Open Questions.
        task_name: { type: string }
        line_item_name: { type: string }
        sub_task_type: { type: string }
        sub_task_name: { type: string }
        sub_line_item_name: { type: string }
        task_type: { type: string }
        account_code: { type: string }
        proposed_budget: { type: number, description: "Forecast." }
        approved_budget: { type: number }
        actual_cost: { type: number }
        commitment:
          type: number
          description: Includes any associated change-order values.
        change_order: { type: number }
        budget_line_type: { type: string }
        master_project_id: { type: number }
        expense_type: { type: string }
        n_ext_attr1: { type: number }
        n_ext_attr2: { type: number }
        segment1: { type: string }
        segment2: { type: string }
        segment3: { type: string }
        segment4: { type: string }
        segment5: { type: string }
        segment6: { type: string }
        comments: { type: string }
        brand_name:
          type: string
          description: |
            NOTE: source data-mapping table types as NUMBER but sample shows
            `Tango` (string). Preserved as string; confirm.
security:
  - xClientHeader: []
    xApiKeyHeader: []
