openapi: 3.1.0
info:
  title: Tango Contracts Inbound API
  version: "0.4"
  description: |
    Async REST API integration: client system submits contract records to Tango's
    Supplier Management batch endpoint. Tango acknowledges synchronously with a
    `gu_id`; final processing status is retrieved by polling the Status API with
    that `gu_id`.

    The combination of `supplier_site_number` + `contract_number` is the upsert
    key. `contract_amount` is set once on creation and cannot be updated; later
    changes flow through `modification_amount` (accumulative).
  x-direction: inbound
  x-source: Client System
  x-destination: Tango
servers:
  - url: https://api.tangoanalytics.com
    description: Production
  - url: https://testapi.tangoanalytics.com
    description: Test (SIT/UAT)
tags:
  - name: Contracts
    description: Contract record submission.
  - name: Status
    description: Async processing status polling.
paths:
  /v1/suppliermgmt/batch/agreements:
    put:
      summary: Submit a batch of contract records (async)
      operationId: putContractsBatch
      tags: [Contracts]
      parameters:
        - $ref: "#/components/parameters/XClient"
        - $ref: "#/components/parameters/XApiKey"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContractsBatchRequest"
            examples:
              default:
                value:
                  records:
                    - contract_number: "104267-13-B-0005"
                      contract_name: "104267-13-B-0005"
                      supplier_site_number: "670234-1"
                      contract_start_date: "06/11/2013"
                      contract_end_date: "03/20/2026"
                      contract_amount: 5000000
                      modification_amount: 70241015.18
                      max_contract_amount: 250000000
                      contract_status: "A"
                      description: "Contract for reconstruction"
      responses:
        "200":
          description: Accepted for async processing.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AcceptedResponse"
              examples:
                ok:
                  value:
                    status: "OK"
                    status_message: ""
                    gu_id: "721c54c4-c7aa-4fa1-8fdfd6-c0cee161694d"
  /v1/batch/status:
    get:
      summary: Poll processing status by gu_id
      operationId: getBatchStatus
      tags: [Status]
      parameters:
        - $ref: "#/components/parameters/XClient"
        - $ref: "#/components/parameters/XApiKey"
        - in: query
          name: gu_id
          required: true
          schema:
            type: string
            format: uuid
          description: The gu_id returned by the submission API.
      responses:
        "200":
          description: Status payload (PROCESSING, COMPLETED, or ERROR).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusResponse"
components:
  securitySchemes:
    xClientHeader:
      type: apiKey
      in: header
      name: x-client
      description: Tango-issued client identifier.
    xApiKeyHeader:
      type: apiKey
      in: header
      name: x-api-key
      description: Tango-issued 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:
    ContractsBatchRequest:
      type: object
      required: [records]
      properties:
        records:
          type: array
          items:
            $ref: "#/components/schemas/ContractRecord"
    ContractRecord:
      type: object
      required:
        - contract_number
        - contract_name
        - supplier_site_number
        - contract_start_date
        - contract_end_date
        - contract_amount
      properties:
        contract_number:
          type: string
          description: Unique contract identifier (with supplier_site_number forms the upsert key).
        contract_name:
          type: string
        supplier_site_number:
          type: string
          description: Must reference an existing supplier site in Tango.
        contract_start_date:
          type: string
          description: "Format MM/DD/YYYY."
          example: "06/11/2013"
        contract_end_date:
          type: string
          description: "Format MM/DD/YYYY."
        contract_amount:
          type: number
          description: Initial amount. Immutable after creation; subsequent changes go through modification_amount.
        modification_amount:
          type: number
          description: Added to existing modification amount on each update.
        max_contract_amount:
          type: number
        contract_status:
          type: string
          description: Source doc shows sample value "A" but does not enumerate allowed statuses.
        description:
          type: string
        c_ext_attr01: { type: string }
        c_ext_attr02: { type: string }
        c_ext_attr03: { type: string }
        c_ext_attr04: { type: string }
        c_ext_attr05: { type: string }
        c_ext_attr06: { type: string }
        c_ext_attr07: { type: string }
        c_ext_attr08: { type: string }
        c_ext_attr09: { type: string }
        c_ext_attr10: { type: string }
        c_ext_lov01:  { type: string }
        c_ext_lov02:  { type: string }
        c_ext_lov03:  { type: string }
        c_ext_lov04:  { type: string }
        c_ext_lov05:  { type: string }
        c_ext_lov06:  { type: string }
        c_ext_lov07:  { type: string }
        c_ext_lov08:  { type: string }
        c_ext_lov09:  { type: string }
        c_ext_lov10:  { type: string }
        d_ext_attr01: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr02: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr03: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr04: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr05: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr06: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr07: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr08: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr09: { type: string, description: "Format MM/DD/YYYY." }
        d_ext_attr10: { type: string, description: "Format MM/DD/YYYY." }
        n_ext_attr01: { type: number }
        n_ext_attr02: { type: number }
        n_ext_attr03: { type: number }
        n_ext_attr04: { type: number }
        n_ext_attr05: { type: number }
        n_ext_attr06: { type: number }
        n_ext_attr07: { type: number }
        n_ext_attr08: { type: number }
        n_ext_attr09: { type: number }
        n_ext_attr10: { type: number }
    AcceptedResponse:
      type: object
      required: [status, gu_id]
      properties:
        status:
          type: string
          enum: [OK, Error]
        status_message:
          type: string
        gu_id:
          type: string
          format: uuid
    StatusResponse:
      oneOf:
        - type: object
          required: [status]
          properties:
            status:
              type: string
              const: PROCESSING
        - type: object
          required: [status, total_records]
          properties:
            status:
              type: string
              const: COMPLETED
            total_records:
              type: integer
            errors:
              type: 'null'
        - type: object
          required: [status, total_records, errors]
          properties:
            status:
              type: string
              const: ERROR
            total_records:
              type: integer
            errors:
              type: array
              items:
                $ref: "#/components/schemas/StatusError"
    StatusError:
      type: object
      required: [record_index, error]
      properties:
        record_index:
          type: integer
        record_key:
          type: string
        error:
          type: string
          description: Comma-separated when multiple errors apply to the same record_key.
security:
  - xClientHeader: []
    xApiKeyHeader: []
