Tackle.io public API

The public API from Tackle.io — 7 operation(s) for public.

Operations 9

POST /api/private-offers/{id} Update a Microsoft offer #
GET /api/private-offers/{id} Get an offer #
POST /api/private-offers Create or import a Microsoft offer #
GET /api/private-offers List offers #
GET /api/products List Microsoft products #
GET /api/products/{id} Get Microsoft product details #
POST /api/private-offers/{id}/notifications Create an offer notification #
GET /api/currencies Get Microsoft market currencies #
POST /api/currencies/convert Convert currencies #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/tackleio-public-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

tackleio-public-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Tackle Contracts Authentication Public API
  description: "Customer-facing read API for cloud marketplace contracts that Tackle has\ningested for your Tackle account.\n\nThe response shape is a stable projection of the underlying\ncontract document. It is intended to be safe to consume long-term: fields\nwill be added over time, but documented fields will not be removed without\ndeprecation notice.\n\n## Authentication\n\nEvery request must include a valid Tackle JWT in the `Authorization`\nheader (`Authorization: Bearer <token>`). Machine-to-machine (MTM) tokens\nissued for your Tackle account are accepted. The token scopes every\nresponse to the account it represents.\n\n## Pagination\n\n`GET /api/contracts` is the only paginated endpoint. Pagination uses an\nopaque `cursor` query parameter:\n\n1. The first request omits `cursor`.\n2. If more pages exist, the response includes a `next` field. Pass that\n   value verbatim back as `cursor` on the next request.\n3. The last page omits `next`.\n\nCursors are opaque tokens. Do not parse, modify, or persist them across\nschema changes — request a fresh page from the start instead.\n"
  version: 1.0.0
servers:
- url: https://contracts.tackle.io
  description: Production
security:
- tackleJwt: []
tags:
- name: public
paths:
  /api/private-offers/{id}:
    post:
      tags:
      - public
      summary: Update a Microsoft offer
      description: 'Updates an existing Microsoft private offer. If `status` is

        `submit_to_cloud`, the handler merges EULA documents when present,

        validates the request, and stores the Microsoft submission payload.


        Required RBAC action: `offers:UpdateOffer`. Submitting to Microsoft also

        requires `offers:CreateOfferOnMarketplace`.

        '
      operationId: updatePrivateOffer
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/OfferId'
      - $ref: '#/components/parameters/TackleOperationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateOffer'
            examples:
              updateDraftOffer:
                summary: Update and keep the offer in Tackle only
                description: 'Use `draft_status` to save the update in Tackle without preparing

                  or submitting a Microsoft marketplace payload.

                  '
                value:
                  status: draft_status
                  name: Updated draft offer
                  description: Updated draft description
              updateCloudOffer:
                summary: Update and submit the offer to Microsoft
                description: 'Use `submit_to_cloud` to validate the offer, merge EULA documents

                  when present, and prepare the Microsoft marketplace payload. This

                  also requires the `offers:CreateOfferOnMarketplace` RBAC action.

                  '
                value:
                  status: submit_to_cloud
                  name: Updated cloud offer
                  description: Updated cloud offer description
                  eula:
                    type: custom
                    document_urns:
                    - document-urn-1
      responses:
        '200':
          description: Offer updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrivateOffer'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      tags:
      - public
      summary: Get an offer
      description: 'Returns one private offer by Tackle offer ID after checking that the

        caller can access the offer''s vendor.


        Required RBAC action: `offers:GetOffer`.

        '
      operationId: getPrivateOffer
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/OfferId'
      - $ref: '#/components/parameters/TackleOperationId'
      responses:
        '200':
          description: Offer found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrivateOffer'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/private-offers:
    post:
      tags:
      - public
      summary: Create or import a Microsoft offer
      description: 'Creates a new Microsoft private offer from a full offer payload, or

        imports an existing live Microsoft private offer when the body contains

        `microsoftOfferId` and `buyer_company_name`.


        For full create payloads, if `status` is `submit_to_cloud`, the handler

        validates and transforms the request for Microsoft submission before

        saving the offer. For import payloads, the vendor context is derived

        from the authenticated principal; sandbox vendors use their production

        parent vendor''s Microsoft credentials.


        Required RBAC action: `offers:CreateDraftOffer`. Submitting to Microsoft

        also requires `offers:CreateOfferOnMarketplace`.

        '
      operationId: createPrivateOffer
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/TackleOperationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
              - $ref: '#/components/schemas/CreateOffer'
              - $ref: '#/components/schemas/ImportMicrosoftOfferRequest'
            examples:
              createDraftOffer:
                summary: Create a Tackle-only draft
                description: 'Use `draft_status` to save the offer in Tackle without preparing

                  or submitting a Microsoft marketplace payload.

                  '
                value:
                  offer_type: direct
                  vendor_id: vendor-123
                  status: draft_status
                  vendor_name: Example Vendor
                  product_id: product-123
                  product_name: Example Product
                  buyer_details:
                    company_name: Example Buyer
                    billing_account_id: billing-account-123
                  eula:
                    type: standard
                    document_urns: []
                  pricing:
                    plan_name: Example Plan
                    description: Annual plan
                    contract_duration:
                      type: month
                      frequency: 12
                    payment_model: OneTime
                    payment_installments:
                      price_per_payment_in_usd: 1200
                    pricing_type: flat_rate
              createCloudOffer:
                summary: Create and submit to Microsoft
                description: 'Use `submit_to_cloud` to validate the offer and prepare the

                  Microsoft marketplace payload. This also requires the

                  `offers:CreateOfferOnMarketplace` RBAC action.

                  '
                value:
                  offer_type: direct
                  vendor_id: vendor-123
                  status: submit_to_cloud
                  vendor_name: Example Vendor
                  product_id: product-123
                  product_name: Example Product
                  name: Example Microsoft Offer
                  preparer_email: seller@example.com
                  start_on: acceptance
                  end_date: '2027-04-30'
                  accept_by_date: '2026-05-31'
                  buyer_details:
                    company_name: Example Buyer
                    billing_account_id: billing-account-123
                    buyers:
                    - full_name: Buyer User
                      email_address: buyer@example.com
                      title: Procurement
                  eula:
                    type: custom
                    document_urns:
                    - document-urn-1
                  pricing:
                    plan_name: Example Plan
                    description: Annual plan
                    contract_duration:
                      type: month
                      frequency: 12
                    payment_model: OneTime
                    payment_installments:
                      price_per_payment_in_usd: 1200
                    pricing_type: flat_rate
              importMicrosoftOffer:
                summary: Import an existing Microsoft offer
                description: 'Use `microsoftOfferId` with `buyer_company_name` to import an

                  existing live Microsoft private offer into Tackle. Optionally

                  include `salesforce_opportunity_id` to associate the imported

                  offer with a Salesforce opportunity. The Microsoft offer must

                  be supported by Tackle: live state, a single product listing

                  and plan, a single buyer, and supported USD pricing.

                  '
                value:
                  microsoftOfferId: ms-offer-123
                  buyer_company_name: Example Buyer
                  salesforce_opportunity_id: 6000000000001
      responses:
        '200':
          description: Offer created or imported
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrivateOffer'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      tags:
      - public
      summary: List offers
      description: 'Finds the authenticated seller''s offers, optionally filtered by Microsoft

        offer reference or Microsoft plan reference. Vendor scope is derived

        from the bearer token; no vendor identifier is accepted from the caller.


        Required RBAC action: `offers:ListOffers`.

        '
      operationId: listPrivateOffers
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/OfferRef'
      - $ref: '#/components/parameters/PlanRef'
      - $ref: '#/components/parameters/TackleOperationId'
      responses:
        '200':
          description: Offers matching the search
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PrivateOffer'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/products:
    get:
      tags:
      - public
      summary: List Microsoft products
      description: 'Returns the Microsoft Marketplace product listings owned by the

        authenticated seller. Use this to populate a product picker before

        creating a private offer. The seller is identified by the vendor in

        the bearer token; no path or query parameter is required.


        Each product object includes the Tackle product identifier

        (`productid`), the listing type (`listing_type`), and human-readable

        `name` and `status` fields. Pass `productid` as the `id` path

        parameter to `GET /api/products/{id}` to fetch plan and pricing

        details for a specific product.


        Required RBAC action: `offers:ListProducts`.

        '
      operationId: listProducts
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/TackleOperationId'
      responses:
        '200':
          description: List of Microsoft products owned by the seller.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/products/{id}:
    get:
      tags:
      - public
      summary: Get Microsoft product details
      description: 'Preferred route for retrieving Microsoft product plan and pricing details.

        The vendor context is derived from the authenticated principal; sandbox

        vendors use their production parent vendor''s Microsoft credentials.

        Demo vendors receive static demo product details; other vendors retrieve

        product details from Microsoft Partner Center.


        Required RBAC action: `offers:CreateDraftOffer`.

        '
      operationId: getProductDetails
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/ProductId'
      - $ref: '#/components/parameters/TackleOperationId'
      responses:
        '200':
          description: Product details found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductDetailsResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/private-offers/{id}/notifications:
    post:
      tags:
      - public
      summary: Create an offer notification
      description: 'Creates an offer notification. Currently only buyer instruction emails

        are supported. To send buyer instructions, use `type:

        buyer_instructions` and `channel: email`. The handler publishes through

        Tackle Notification Service and marks the offer as email sent.


        Required RBAC action: `offers:SendOfferInstructions`.

        '
      operationId: createPrivateOfferNotification
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/OfferId'
      - $ref: '#/components/parameters/TackleOperationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOfferNotificationRequest'
            examples:
              sendBuyerInstructionsEmail:
                summary: Send buyer instruction email
                value:
                  type: buyer_instructions
                  channel: email
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/currencies:
    get:
      tags:
      - public
      summary: Get Microsoft market currencies
      description: 'Returns accepted currencies and the Microsoft marketplace countries

        grouped by accepted currency.


        Required RBAC action: `offers:CreateDraftOffer`.

        '
      operationId: getMarketCurrencies
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/TackleOperationId'
      responses:
        '200':
          description: Market currencies found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketCurrenciesResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/currencies/convert:
    post:
      tags:
      - public
      summary: Convert currencies
      description: 'Converts one or more amounts from a base currency to a target currency

        using cached Microsoft foreign exchange rates. Row-level conversion

        errors are returned in `results[].error` without failing the entire

        request.


        Required RBAC action: `offers:CreateDraftOffer`.

        '
      operationId: convertCurrencies
      security:
      - bearerAuth: []
      parameters:
      - $ref: '#/components/parameters/TackleOperationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CurrencyConversionRequest'
      responses:
        '200':
          description: Currency conversion results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrencyConversionResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    CurrencyOption:
      type: object
      properties:
        value:
          type: string
          description: ISO 4217 currency code.
          example: USD
        display:
          type: string
          example: United States Dollar | USD ($)
    RecurrentPrice:
      type: object
      properties:
        price_input_option:
          type: string
        recurrent_price_mode:
          type: string
        user_limits:
          $ref: '#/components/schemas/PlanUserLimits'
        prices:
          type: array
          items:
            $ref: '#/components/schemas/PlanPrice'
    PlanUserLimits:
      type: object
      properties:
        min:
          type: integer
        max:
          type: integer
    PrivateOfferActivity:
      type: object
      properties:
        slug:
          type:
          - string
          - 'null'
          example: created-draft-offer
        user_id:
          type:
          - string
          - 'null'
        created_at:
          type: string
          format: date-time
        metadata:
          type:
          - object
          - 'null'
          additionalProperties: true
        user:
          oneOf:
          - $ref: '#/components/schemas/PrivateOfferActivityUser'
          - type: 'null'
    UpdateContractDuration:
      type: object
      properties:
        type:
          type:
          - string
          - 'null'
        frequency:
          type:
          - integer
          - 'null'
    Dimension:
      type: object
      properties:
        enabled:
          type: boolean
        id:
          type: string
        unit_of_measure:
          type: string
        price_per_unit_in_usd:
          type: number
          format: double
        included_quantities:
          type: array
          items:
            $ref: '#/components/schemas/DimensionQuantity'
    PaymentInstallment:
      type: object
      properties:
        price_per_payment_in_usd:
          type: number
          format: double
    CurrencyConversionPayload:
      type: object
      required:
      - id
      - base_currency
      - target_currency
      - amount
      properties:
        id:
          type: string
          description: Caller-provided row ID echoed in the response.
        base_currency:
          type: string
          example: USD
        target_currency:
          type: string
          example: EUR
        amount:
          type: number
          format: double
          example: 100
    OfferPricing:
      type: object
      properties:
        plan_ref:
          type: string
          description: Microsoft plan ID.
        plan_name:
          type: string
        description:
          type: string
        contract_duration:
          $ref: '#/components/schemas/ContractDuration'
        payment_model:
          $ref: '#/components/schemas/PaymentModel'
        payment_installments:
          oneOf:
          - $ref: '#/components/schemas/PaymentInstallment'
          - type: 'null'
        payment_schedule:
          oneOf:
          - $ref: '#/components/schemas/PaymentSchedule'
          - type: 'null'
        pricing_type:
          oneOf:
          - $ref: '#/components/schemas/PricingType'
          - type: 'null'
        user_limits:
          oneOf:
          - $ref: '#/components/schemas/UserLimits'
          - type: 'null'
        dimensions:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Dimension'
    ProductType:
      type: string
      enum:
      - saas
      - ami
      - professional_services
    ContractDuration:
      type: object
      properties:
        type:
          type: string
          example: month
        frequency:
          type: integer
          example: 12
    PaymentSchedule:
      type: object
      properties:
        initial_charge:
          $ref: '#/components/schemas/InitialCharge'
        payment_schedule:
          type: array
          items:
            $ref: '#/components/schemas/ScheduleDetail'
    PrivateOffer:
      type: object
      description: Stored Tackle Microsoft private offer.
      properties:
        po_id:
          type: string
        accepted_at:
          type:
          - string
          - 'null'
          format: date-time
        accepted_source:
          type:
          - string
          - 'null'
        archived_at:
          type:
          - string
          - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        cancelled_at:
          type:
          - string
          - 'null'
          format: date-time
        last_modified_at:
          type: string
          format: date-time
        last_update_source:
          type:
          - string
          - 'null'
        viewed_offer_at:
          type:
          - string
          - 'null'
          format: date-time
        sent_at:
          type:
          - string
          - 'null'
          format: date-time
        submitted_at:
          type:
          - string
          - 'null'
          format: date-time
        opened_instructions_at:
          type:
          - string
          - 'null'
          format: date-time
        subscribed_at:
          type:
          - string
          - 'null'
          format: date-time
        partner_marked_up_at:
          type:
          - string
          - 'null'
          format: date-time
        marketplace_acceptance_link:
          type:
          - string
          - 'null'
          format: uri
        salesforce:
          $ref: '#/components/schemas/PrivateOfferSalesforce'
        vendor_id:
          type: string
        vendor_name:
          type: string
        product_contact_email:
          type: string
          format: email
        state:
          $ref: '#/components/schemas/OfferStateValue'
        status:
          $ref: '#/components/schemas/OfferStatus'
        offer_type:
          $ref: '#/components/schemas/OfferType'
        marketplace_fee:
          type: number
          format: double
        activities:
          type: array
          items:
            $ref: '#/components/schemas/PrivateOfferActivity'
        archived:
          type: boolean
        version:
          type: string
        product_id:
          type: string
        product_name:
          type: string
        source:
          $ref: '#/components/schemas/Source'
        marketplace_created_at:
          type:
          - string
          - 'null'
          format: date-time
        clone:
          oneOf:
          - $ref: '#/components/schemas/Clone'
          - type: 'null'
        metadata:
          type: object
          additionalProperties:
            type: string
        product_type:
          $ref: '#/components/schemas/ProductType'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/PrivateOfferError'
        pre_registration_details:
          $ref: '#/components/schemas/PreRegistrationDetails'
        ui_state:
          $ref: '#/components/schemas/OfferStateValue'
        partner:
          oneOf:
          - $ref: '#/components/schemas/Partner'
          - type: 'null'
        total_contract_value_gross_amount:
          type: number
          format: double
        total_contract_value_net_amount:
          type: number
          format: double
        est_min_total_contract_value_gross_amount:
          type: number
          format: double
        est_min_total_contract_value_net_amount:
          type: number
          format: double
        est_max_total_contract_value_gross_amount:
          type: number
          format: double
        est_max_total_contract_value_net_amount:
          type: number
          format: double
        name:
          type:
          - string
          - 'null'
        description:
          type:
          - string
          - 'null'
        buyer_details:
          $ref: '#/components/schemas/BuyerDetails'
        renewal:
          type: boolean
        eula:
          $ref: '#/components/schemas/EULA'
        product_ref:
          type: string
        users_to_notify:
          type: array
          items:
            $ref: '#/components/schemas/UserToNotify'
        pricing:
          $ref: '#/components/schemas/OfferPricing'
        preparer_email:
          type: string
          format: email
        start_on:
          $ref: '#/components/schemas/StartOn'
        start_date:
          type: string
          format: date
        end_date:
          type: string
          format: date
        accept_by_date:
          type: string
          format: date
        offer_ref:
          type:
          - string
          - 'null'
        plan_template:
          $ref: '#/components/schemas/PlanTemplate'
        plan_ref:
          type:
          - string
          - 'null'
        subscription_ref:
          type:
          - string
          - 'null'
        notes:
          type:
          - string
          - 'null'
        offer_state:
          $ref: '#/components/schemas/PrivateOfferState'
        msft_response:
          $ref: '#/components/schemas/MsftResponse'
    BuyerDetails:
      type: object
      properties:
        company_name:
          type: string
        billing_account_id:
          type: string
        buyers:
          type: array
          items:
            $ref: '#/components/schemas/Buyer'
    PrivateOfferSalesforce:
      type: object
      properties:
        created_at:
          type:
          - string
          - 'null'
          format: date-time
        custom_object_id:
          type:
          - string
          - 'null'
        opportunity_id:
          type:
          - string
          - 'null'
    CustomMeters:
      type: object
      properties:
        price_input_option:
          type: string
        meters:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Meter'
    PricingType:
      type: string
      enum:
      - flat_rate
      - per_user
    Partner:
      type: object
      properties:
        partner_name:
          type:
          - string
          - 'null'
        partner_seller_id:
          type: string
    Buyer:
      type: object
      properties:
        full_name:
          type: string
        email_address:
          type: string
          format: email
        title:
          type: string
    MsftResponse:
      type: object
      properties:
        job_id:
          type: string
        offer_id:
          type:
          - string
          - 'null'
        resource_uri:
          type:
          - string
          - 'null'
        raw_response:
          type: string
    CurrencyConversionError:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
    UpdateSalesforce:
      type: object
      properties:
        custom_object_id:
          type:
          - string
          - 'null'
        opportunity_id:
          type:
          - string
          - 'null'
    PriceDetail:
      type: object
      properties:
        markets:
          type: array
          items:
            type: string
        currency:
          type: string
        price:
          type: number
          format: double
    IncludedQuantity:
      type: object
      properties:
        billing_term:
          $ref: '#/components/schemas/TermValue'
        is_infinite:
          type: boolean
        quantity:
          type: number
          format: double
    EULA:
      type: object
      properties:
        type:
          type:
          - string
          - 'null'
          description: Offer EULA type.
          example: standard
        document_urns:
          type: array
          items:
            type: string
        merged_urn:
          type:
          - string
          - 'null'
        presigned_url:
          type:
          - string
          - 'null'
          format: uri
    OfferType:
      type: string
      enum:
      - direct
      - partner
    UpdateUserToNotify:
      type: object
      properties:
        contact_type:
          type: string
        value:
          type: string
        email:
          type: string
          format: email
    ImportMicrosoftOfferRequest:
      type: object
      required:
      - microsoftOfferId
      - buyer_company_name
      properties:
        microsoftOfferId:
          type: string
          description: Microsoft private offer ID to import.
          example: ms-offer-123
        buyer_company_name:
          type: string
          description: Buyer company name to store on the imported offer.
          example: Example Buyer
        salesforce_opportunity_id:
          type: string
          description: Optional Salesforce opportunity ID to associate to the imported offer.
          example: 6000000000001
    Source:
      type: string
      enum:
      - salesforce
      - tackle
      - microsoft
    PlanPrice:
      type: object
      properties:
        billing_term:
          $ref: '#/components/schemas/TermValue'
        payment_option:
          $ref: '#/components/schemas/TermValue'
        prices:
          type: array
          items:
            $ref: '#/components/schemas/PriceDetail'
        price_per_payment_in_usd:
          type: number
          format: double
    CurrencyConversionResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/CurrencyConversionResult'
        success:
          type: boolean
          example: true
    PrivateOfferActivityUser:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        principal_type:
          type: string
    CurrencyConversionRequest:
      type: object
      required:
      - conversions
      properties:
        as_of_date:
          type: string
          format: date
          description: Requested FX rate date. Defaults to the current UTC date.
          example: '2026-04-30'
        conversions:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/CurrencyConversionPayload'
    UpdateOffer:
      type: object
      description: Partial request body for updating a Microsoft SaaS private offer.
      properties:
        salesforce:
          oneOf:
          - $ref: '#/components/schemas/UpdateSalesforce'
          - type: 'null'
        marketplace_fee:
          type:
          - number
          - 'null'
          format: double
        state:
          oneOf:
          - $ref: '#/components/schemas/OfferStateValue'
          - type: 'null'
        status:
          description: 'Use `draft_status` to update the offer

# --- truncated at 32 KB (51 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/tackleio/refs/heads/main/openapi/tackleio-public-api-openapi.yml