openapi: 3.1.0
info:
  title: Influencer API
  version: 0.1.0-draft
  description: |
    Influencer / Affiliate / Referral management.

    Contract notes:
    - API Gateway base path: `/influencer`
    - Org-gated: supply `x-orgcode`.
    - Channel context is required for attribution and earnings.
    - Request context is captured for auditability (org/facility/channel/roles/cost-centre).
    - Auth: either `x-session-guid` (user session) or `x-api-key` (org-bound service account).
      Headers are canonical; body `session_guid`/`api_key` accepted for compatibility on POST.
servers:
  - url: https://api.g3nretailstack.com/influencer
security:
  - sessionAuth: []
  - apiKeyAuth: []
components:
  securitySchemes:
    sessionAuth:
      type: apiKey
      in: header
      name: x-session-guid
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
  parameters:
    OrgHeader:
      in: header
      name: x-orgcode
      required: true
      schema: { type: string }
    LogicalHeader:
      in: header
      name: x-logical-guid
      required: false
      schema: { type: string }
    ChannelHeader:
      in: header
      name: x-channel-code
      required: false
      schema: { type: string }
  schemas:
    BuildMeta:
      type: object
      properties:
        build_major: { type: string }
        build_minor: { type: string }
        build_id: { type: string }
      required: [build_major, build_minor, build_id]
    Stats:
      type: object
      properties:
        call: { type: string }
        service: { type: string, enum: [influencer] }
        request_id: { type: string }
        timestamp_utc: { type: string, format: date-time }
        actor: { type: string }
        context_source:
          type: string
          enum: [session, api_key, operator, system]
        session_fingerprint:
          type: string
          description: Non-reversible SHA-256 fingerprint of the caller session (`session_guid`) for correlation (never an auth credential).
        api_key_fingerprint:
          type: string
          description: Non-reversible SHA-256 fingerprint of the caller `api_key` for correlation (never an auth credential).
        orgcode: { type: string }
        cccode: { type: string }
        logical_guid: { type: string }
        channel_code: { type: string }
        roles:
          type: array
          items: { type: string }
        build:
          $ref: '#/components/schemas/BuildMeta'
      required: [call, service, timestamp_utc, build]
    Error:
      type: object
      properties:
        error_code: { type: string }
        http_status: { type: integer }
        retryable: { type: boolean }
        request_id: { type: string }
        trace_id: { type: string }
        major: { type: string }
        minor: { type: string }
        message: { type: string }
        details: { type: object }
    Envelope:
      type: object
      properties:
        success: { type: boolean }
        data: { type: object }
        error: { $ref: '#/components/schemas/Error' }
        stats: { $ref: '#/components/schemas/Stats' }
      required: [success]
    SourceRef:
      type: object
      properties:
        kind: { type: string }
        id: { type: string }
      required: [kind, id]
    SourceRefs:
      type: array
      items: { $ref: '#/components/schemas/SourceRef' }
    RequestContext:
      type: object
      properties:
        orgcode: { type: string }
        logical_guid: { type: string }
        channel_code: { type: string }
        cccode: { type: string }
        actor: { type: string }
        roles:
          type: array
          items: { type: string }
        context_source:
          type: string
          enum: [session, api_key, operator, system]
        session_fingerprint: { type: string }
        api_key_fingerprint: { type: string }
      required: [orgcode, actor, context_source]
      additionalProperties: false
    PolicyRefs:
      type: object
      properties:
        tax_policy_version: { type: string }
        pricing_policy_version: { type: string }
        promotion_policy_version: { type: string }
        discount_policy_version: { type: string }
        stacking_policy_version: { type: string }
        approval_policy_version: { type: string }
        tender_policy_version: { type: string }
        returns_policy_version: { type: string }
        loyalty_policy_version: { type: string }
        stored_value_policy_version: { type: string }
        earning_policy_version: { type: string }
        backorder_policy_version: { type: string }
        special_order_policy_version: { type: string }
        transfer_policy_version: { type: string }
        count_policy_version: { type: string }
        adjustment_policy_version: { type: string }
        po_policy_version: { type: string }
        matching_policy_version: { type: string }
        tolerance_policy_version: { type: string }
        receiving_policy_version: { type: string }
        qc_policy_version: { type: string }
        rtv_policy_version: { type: string }
        credit_policy_version: { type: string }
        shipping_policy_version: { type: string }
        export_policy_version: { type: string }
      additionalProperties: true
    Money:
      type: object
      properties:
        currency: { type: string }
        amount: { type: number }
      required: [currency, amount]
    AttributionIdentifier:
      type: object
      properties:
        kind: { type: string, enum: [coupon, link, qr, campaign, affiliate_id] }
        value: { type: string }
      required: [kind, value]
    InfluencerProfileDraft:
      type: object
      properties:
        request_context: { $ref: '#/components/schemas/RequestContext' }
        policy_refs: { $ref: '#/components/schemas/PolicyRefs' }
        reason: { type: string }
        display_name: { type: string }
        handle: { type: string }
        contact_email: { type: string }
        attribution_ids:
          type: array
          items: { $ref: '#/components/schemas/AttributionIdentifier' }
        default_channel_code: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        notes: { type: string }
      required: [request_context, reason, source_refs]
    InfluencerProfile:
      type: object
      properties:
        influencer_guid: { type: string }
        status: { type: string, enum: [active, inactive, suspended, doomed] }
        display_name: { type: string }
        handle: { type: string }
        contact_email: { type: string }
        attribution_ids:
          type: array
          items: { $ref: '#/components/schemas/AttributionIdentifier' }
        default_channel_code: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        revision: { type: integer }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
    InfluencerProfileCreateRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        profile: { $ref: '#/components/schemas/InfluencerProfileDraft' }
        idempotency_key: { type: string }
        cccode: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [profile, reason, source_refs]
    InfluencerProfileGetRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        handle: { type: string }
        attribution_id: { $ref: '#/components/schemas/AttributionIdentifier' }
      anyOf:
        - required: [influencer_guid]
        - required: [handle]
        - required: [attribution_id]
    InfluencerProfileEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                profile: { $ref: '#/components/schemas/InfluencerProfile' }
              required: [profile]
    DiscountRule:
      type: object
      properties:
        type: { type: string, enum: [percent, fixed] }
        value: { type: number }
        currency: { type: string }
        max_amount: { $ref: '#/components/schemas/Money' }
        min_order_amount: { $ref: '#/components/schemas/Money' }
        cap_amount: { $ref: '#/components/schemas/Money' }
      required: [type, value]
    DiscountTierDraft:
      type: object
      properties:
        request_context: { $ref: '#/components/schemas/RequestContext' }
        policy_refs: { $ref: '#/components/schemas/PolicyRefs' }
        reason: { type: string }
        influencer_guid: { type: string }
        channel_code: { type: string }
        tier_code: { type: string, description: 'Optional tier code (default: default).' }
        status: { type: string, enum: [active, inactive] }
        discount: { $ref: '#/components/schemas/DiscountRule' }
        earning: { $ref: '#/components/schemas/DiscountRule' }
        effective_from: { type: string, format: date-time }
        effective_to: { type: string, format: date-time }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [request_context, reason, source_refs, influencer_guid, channel_code, discount]
    DiscountTier:
      type: object
      properties:
        influencer_guid: { type: string }
        channel_code: { type: string }
        tier_code: { type: string }
        status: { type: string, enum: [active, inactive] }
        discount: { $ref: '#/components/schemas/DiscountRule' }
        earning: { $ref: '#/components/schemas/DiscountRule' }
        effective_from: { type: string, format: date-time }
        effective_to: { type: string, format: date-time }
        policy_refs: { $ref: '#/components/schemas/PolicyRefs' }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        revision: { type: integer }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
      required: [influencer_guid, channel_code, tier_code, status, discount, revision]
    DiscountTierSetRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        discount_tier: { $ref: '#/components/schemas/DiscountTierDraft' }
        expected_revision: { type: integer }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [discount_tier, reason, source_refs]
    DiscountTierGetRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        channel_code: { type: string }
        tier_code: { type: string }
      required: [influencer_guid, channel_code]
    DiscountTierListRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        channel_code: { type: string }
        limit: { type: integer }
        next_token: { type: string }
      required: [influencer_guid]
    DiscountTierEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                discount_tier: { $ref: '#/components/schemas/DiscountTier' }
              required: [discount_tier]
    DiscountTierListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                discount_tiers:
                  type: array
                  items: { $ref: '#/components/schemas/DiscountTier' }
                next_token: { type: string }
              required: [discount_tiers]
    PayoutReadyDraft:
      type: object
      properties:
        request_context: { $ref: '#/components/schemas/RequestContext' }
        reason: { type: string }
        influencer_guid: { type: string }
        status: { type: string, enum: [ready, pending, blocked] }
        min_payout_amount: { $ref: '#/components/schemas/Money' }
        payout_method_ref: { type: string }
        reasons:
          type: array
          items: { type: string }
        notes: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [request_context, reason, source_refs, influencer_guid, status]
    PayoutReady:
      type: object
      properties:
        influencer_guid: { type: string }
        status: { type: string, enum: [ready, pending, blocked] }
        min_payout_amount: { $ref: '#/components/schemas/Money' }
        payout_method_ref: { type: string }
        reasons:
          type: array
          items: { type: string }
        notes: { type: string }
        revision: { type: integer }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
      required: [influencer_guid, status, revision]
    PayoutReadySetRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        payout_ready: { $ref: '#/components/schemas/PayoutReadyDraft' }
        expected_revision: { type: integer }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [payout_ready, reason, source_refs]
    PayoutReadyGetRequest:
      type: object
      properties:
        influencer_guid: { type: string }
      required: [influencer_guid]
    PayoutReadyEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                payout_ready: { $ref: '#/components/schemas/PayoutReady' }
              required: [payout_ready]
    CampaignDraft:
      type: object
      properties:
        request_context: { $ref: '#/components/schemas/RequestContext' }
        policy_refs: { $ref: '#/components/schemas/PolicyRefs' }
        reason: { type: string }
        name: { type: string }
        description: { type: string }
        campaign_code: { type: string }
        attribution_model: { type: string, enum: [first_touch, last_touch, coupon, link, qr, custom] }
        attribution_window_days: { type: integer }
        channel_codes:
          type: array
          items: { type: string }
        start_at: { type: string, format: date-time }
        end_at: { type: string, format: date-time }
        rules:
          type: object
          description: Campaign-specific eligibility or exclusion rules (opaque to the API).
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [request_context, reason, source_refs, name]
    CampaignRecord:
      type: object
      properties:
        campaign_id: { type: string }
        status: { type: string, enum: [draft, active, paused, closed] }
        name: { type: string }
        description: { type: string }
        campaign_code: { type: string }
        attribution_model: { type: string }
        attribution_window_days: { type: integer }
        channel_codes:
          type: array
          items: { type: string }
        start_at: { type: string, format: date-time }
        end_at: { type: string, format: date-time }
        rules: { type: object }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
    CampaignCreateRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        campaign: { $ref: '#/components/schemas/CampaignDraft' }
        idempotency_key: { type: string }
        cccode: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [campaign, reason, source_refs]
    CampaignGetRequest:
      type: object
      properties:
        campaign_id: { type: string }
      required: [campaign_id]
    CampaignListRequest:
      type: object
      properties:
        status: { type: string }
        start_from: { type: string, format: date-time }
        start_to: { type: string, format: date-time }
        limit: { type: integer }
        next_token: { type: string }
    CampaignStatusSetRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        campaign_id: { type: string }
        status: { type: string, enum: [draft, active, paused, closed] }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [campaign_id, status, reason, source_refs]
    CampaignEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                campaign: { $ref: '#/components/schemas/CampaignRecord' }
              required: [campaign]
    CampaignListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                campaigns:
                  type: array
                  items: { $ref: '#/components/schemas/CampaignRecord' }
                next_token: { type: string }
              required: [campaigns]
    AttributionRecord:
      type: object
      properties:
        attribution_id: { type: string }
        influencer_guid: { type: string }
        order_ref: { type: string }
        channel_code: { type: string }
        amount: { $ref: '#/components/schemas/Money' }
        occurred_at: { type: string, format: date-time }
        touch_at: { type: string, format: date-time }
        campaign_id: { type: string }
        attribution_window_days: { type: integer }
        customer_ref: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
    AttributionRecordRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        attribution_id: { $ref: '#/components/schemas/AttributionIdentifier' }
        order_ref: { type: string }
        channel_code: { type: string }
        amount: { $ref: '#/components/schemas/Money' }
        occurred_at: { type: string, format: date-time }
        touch_at: { type: string, format: date-time }
        campaign_id: { type: string }
        customer_ref: { type: string }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [order_ref, channel_code, amount, reason, source_refs]
    EarningsRecord:
      type: object
      properties:
        earning_id: { type: string }
        influencer_guid: { type: string }
        order_ref: { type: string }
        amount: { $ref: '#/components/schemas/Money' }
        status: { type: string, enum: [accrued, held, payable, paid, clawed_back] }
        policy_versions:
          type: object
          properties:
            earning_policy_version: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        hold_until: { type: string, format: date-time }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
    EarningsHoldRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        earning_id: { type: string }
        created_at: { type: string, format: date-time }
        hold_until: { type: string, format: date-time }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, earning_id, reason, source_refs]
    EarningsReleaseRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        earning_id: { type: string }
        created_at: { type: string, format: date-time }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, earning_id, reason, source_refs]
    EarningsClawbackRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        earning_id: { type: string }
        created_at: { type: string, format: date-time }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, earning_id, reason, source_refs]
    EarningEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                earning: { $ref: '#/components/schemas/EarningsRecord' }
              required: [earning]
    EarningsListRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        status: { type: string }
        created_from: { type: string, format: date-time }
        created_to: { type: string, format: date-time }
        limit: { type: integer }
        next_token: { type: string }
      required: [influencer_guid]
    EarningsListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                earnings:
                  type: array
                  items: { $ref: '#/components/schemas/EarningsRecord' }
                next_token: { type: string }
              required: [earnings]
    DisputeSubject:
      type: object
      properties:
        kind: { type: string }
        id: { type: string }
        ref: { type: string }
      required: [kind, id]
    DisputeRecord:
      type: object
      properties:
        dispute_id: { type: string }
        influencer_guid: { type: string }
        subject: { $ref: '#/components/schemas/DisputeSubject' }
        amount: { $ref: '#/components/schemas/Money' }
        status: { type: string, enum: [open, under_review, resolved, rejected, withdrawn] }
        reason_code: { type: string }
        notes: { type: string }
        resolution: { type: object }
        policy_versions:
          type: object
          properties:
            dispute_policy_version: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
        resolved_at: { type: string, format: date-time }
        revision: { type: integer }
    DisputeDraft:
      type: object
      properties:
        dispute_id: { type: string }
        influencer_guid: { type: string }
        subject: { $ref: '#/components/schemas/DisputeSubject' }
        amount: { $ref: '#/components/schemas/Money' }
        status: { type: string, enum: [open, under_review, resolved, rejected, withdrawn] }
        reason_code: { type: string }
        notes: { type: string }
        resolution: { type: object }
        policy_refs:
          type: object
          properties:
            dispute_policy_version: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, subject]
    DisputeCreateRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        dispute: { $ref: '#/components/schemas/DisputeDraft' }
        idempotency_key: { type: string }
        cccode: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [dispute, reason, source_refs]
    DisputeGetRequest:
      type: object
      properties:
        dispute_id: { type: string }
      required: [dispute_id]
    DisputeListRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        status: { type: string }
        created_from: { type: string, format: date-time }
        created_to: { type: string, format: date-time }
        limit: { type: integer }
        next_token: { type: string }
      required: [influencer_guid]
    DisputeStatusSetRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        dispute_id: { type: string }
        status: { type: string, enum: [open, under_review, resolved, rejected, withdrawn] }
        expected_revision: { type: integer }
        resolution: { type: object }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [dispute_id, status, expected_revision, reason, source_refs]
    DisputeEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                dispute: { $ref: '#/components/schemas/DisputeRecord' }
              required: [dispute]
    DisputeListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                disputes:
                  type: array
                  items: { $ref: '#/components/schemas/DisputeRecord' }
                next_token: { type: string }
              required: [disputes]
    StatementRecord:
      type: object
      properties:
        statement_id: { type: string }
        influencer_guid: { type: string }
        period_from: { type: string, format: date-time }
        period_to: { type: string, format: date-time }
        status: { type: string, enum: [issued, paid, void] }
        totals:
          type: object
          properties:
            earned: { $ref: '#/components/schemas/Money' }
            payable: { $ref: '#/components/schemas/Money' }
            paid: { $ref: '#/components/schemas/Money' }
            clawed_back: { $ref: '#/components/schemas/Money' }
          required: [earned, payable, paid, clawed_back]
        earning_ids:
          type: array
          items: { type: string }
        policy_versions:
          type: object
          properties:
            earning_policy_version: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
    StatementCreateRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        period_from: { type: string, format: date-time }
        period_to: { type: string, format: date-time }
        totals:
          type: object
          properties:
            earned: { $ref: '#/components/schemas/Money' }
            payable: { $ref: '#/components/schemas/Money' }
            paid: { $ref: '#/components/schemas/Money' }
            clawed_back: { $ref: '#/components/schemas/Money' }
          required: [earned, payable, paid, clawed_back]
        earning_ids:
          type: array
          items: { type: string }
        policy_refs:
          type: object
          properties:
            earning_policy_version: { type: string }
        status: { type: string }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, period_from, period_to, totals, reason, source_refs]
    StatementGetRequest:
      type: object
      properties:
        statement_id: { type: string }
      required: [statement_id]
    StatementListRequest:
      type: object
      properties:
        influencer_guid: { type: string }
        period_from: { type: string, format: date-time }
        period_to: { type: string, format: date-time }
        limit: { type: integer }
        next_token: { type: string }
      required: [influencer_guid]
    StatementEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                statement: { $ref: '#/components/schemas/StatementRecord' }
              required: [statement]
    StatementListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                statements:
                  type: array
                  items: { $ref: '#/components/schemas/StatementRecord' }
                next_token: { type: string }
              required: [statements]
    PayoutSubmitRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        influencer_guid: { type: string }
        amount: { $ref: '#/components/schemas/Money' }
        payout_method_ref: { type: string }
        idempotency_key: { type: string }
        reason: { type: string }
        source_refs: { $ref: '#/components/schemas/SourceRefs' }
      required: [influencer_guid, amount, reason, source_refs]
    PayoutEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                payout_id: { type: string }
                status: { type: string }
              required: [payout_id, status]
    CommentAttachment:
      type: object
      properties:
        mrs_guid: { type: string }
        caption: { type: string }
        filename: { type: string }
        content_type: { type: string }
        size_bytes: { type: integer, minimum: 0 }
      required: [mrs_guid]
    Comment:
      type: object
      properties:
        comment_id: { type: string }
        target_type: { type: string }
        target_id: { type: string }
        parent_comment_id: { type: string }
        caption: { type: string }
        body: { type: string }
        attachments:
          type: array
          items: { $ref: '#/components/schemas/CommentAttachment' }
        total_size_bytes: { type: integer }
        hashtags:
          type: array
          items: { type: string }
        mentions_users:
          type: array
          items: { type: string }
        mentions_teams:
          type: array
          items: { type: string }
        status: { type: string, enum: [current, archived, doomed] }
        current_revision: { type: integer }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
        author_guid: { type: string }
      required: [comment_id, target_type, target_id, status, current_revision, created_at]
    CommentAddRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        target_type: { type: string }
        target_id: { type: string }
        parent_comment_id: { type: string }
        caption: { type: string }
        body: { type: string }
        attachments:
          type: array
          items: { $ref: '#/components/schemas/CommentAttachment' }
        hashtags:
          type: array
          items: { type: string }
        mentions_users:
          type: array
          items: { type: string }
        mentions_teams:
          type: array
          items: { type: string }
        idempotency_key: { type: string }
      required: [target_type, target_id]
    CommentGetRequest:
      type: object
      properties:
        comment_id: { type: string }
        target_type: { type: string }
        target_id: { type: string }
      required: [comment_id, target_type, target_id]
    CommentListRequest:
      type: object
      properties:
        target_type: { type: string }
        target_id: { type: string }
        user_guid: { type: string }
        org_wide: { type: boolean }
        status: { type: string, enum: [current, archived, doomed] }
        hashtag: { type: string }
        created_after: { type: string, format: date-time }
        created_before: { type: string, format: date-time }
        limit: { type: integer, minimum: 1, maximum: 100 }
        next_token: { type: string }
      description: Requires target_type+target_id, user_guid, or org_wide=true.
    CommentReviseRequest:
      type: object
      properties:
        comment_id: { type: string }
        target_type: { type: string }
        target_id: { type: string }
        caption: { type: string }
        body: { type: string }
        attachments:
          type: array
          items: { $ref: '#/components/schemas/CommentAttachment' }
        hashtags:
          type: array
          items: { type: string }
        mentions_users:
          type: array
          items: { type: string }
        mentions_teams:
          type: array
          items: { type: string }
        expected_revision: { type: integer }
      required: [comment_id, target_type, target_id]
    CommentStatusRequest:
      type: object
      properties:
        comment_id: { type: string }
        target_type: { type: string }
        target_id: { type: string }
        status: { type: string, enum: [current, archived, doomed] }
      required: [comment_id, target_type, target_id, status]
    CommentReportRequest:
      type: object
      properties:
        limit: { type: integer, minimum: 1, maximum: 100 }
    CommentEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                comment: { $ref: '#/components/schemas/Comment' }
              required: [comment]
    CommentListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                items:
                  type: array
                  items: { $ref: '#/components/schemas/Comment' }
                next_token: { type: string }
              required: [items]
    CommentReportEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      comment_id: { type: string }
                      target_type: { type: string }
                      target_id: { type: string }
                      total_size_bytes: { type: integer }
                      created_at: { type: string, format: date-time }
                    required: [comment_id, target_type, target_id]
              required: [items]
    InboxNotification:
      type: object
      properties:
        notification_id: { type: string }
        team_guid: { type: string }
        status: { type: string, enum: [inbox, archived] }
        state: { type: string, enum: [pending, completed, deferred] }
        priority: { type: string, enum: [low, medium, high, show_stopper] }
        act_by: { type: string, format: date-time }
        record_type: { type: string }
        record_id: { type: string }
        title: { type: string }
        body: { type: string }
        created_at: { type: string, format: date-time }
        updated_at: { type: string, format: date-time }
        created_by: { type: string }
      required: [notification_id, team_guid, status, state, priority, title]
    InboxCreateRequest:
      type: object
      x-idempotency-scope: orgcode+route+idempotency_key
      x-idempotency-retention-hours: 24
      x-idempotency-replay: return_original_response
      properties:
        team_guid: { type: string }
        record_type: { type: string }
        record_id: { type: string }
        title: { type: string }
        body: { type: string }
        priority: { type: string, enum: [low, medium, high, show_stopper] }
        act_by: { type: string, format: date-time }
        idempotency_key: { type: string }
      required: [team_guid, title]
    InboxGetRequest:
      type: object
      properties:
        notification_id: { type: string }
      required: [notification_id]
    InboxListRequest:
      type: object
      properties:
        team_guid: { type: string }
        org_wide: { type: boolean }
        status: { type: string, enum: [inbox, archived] }
        state: { type: string, enum: [pending, completed, deferred] }
        limit: { type: integer, minimum: 1, maximum: 100 }
        next_token: { type: string }
      description: Requires team_guid unless org_wide=true (owner-only).
    InboxStatusRequest:
      type: object
      properties:
        notification_id: { type: string }
        status: { type: string, enum: [inbox, archived] }
      required: [notification_id, status]
    InboxStateRequest:
      type: object
      properties:
        notification_id: { type: string }
        state: { type: string, enum: [pending, completed, deferred] }
      required: [notification_id, state]
    InboxEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                notification: { $ref: '#/components/schemas/InboxNotification' }
              required: [notification]
    InboxListEnvelope:
      allOf:
        - { $ref: '#/components/schemas/Envelope' }
        - type: object
          properties:
            data:
              type: object
              properties:
                items:
                  type: array
                  items: { $ref: '#/components/schemas/InboxNotification' }
                next_token: { type: string }
              required: [items]
paths:
  /stat:
    get:
      summary: Health check
      description: |
        Health check. Tenant routes require x-orgcode; /stat health checks do not. Org-scoped reads may
        return 404 for non-associated callers (anti-enumeration). Route class Tier A (p95 500ms).
      x-route-class: Tier A
      x-qps-target: 5
      x-concurrency-target: 2
      x-latency-p95-ms: 500
      responses:
        '200':
          description: ok
          content:
            application/json:
              schema:
                allOf:
                  - { $ref: '#/components/schemas/Envelope' }
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          service: { type: string }
                          status: { type: string }
  /profile/create:
    post:
      summary: Create influencer profile (draft)
      description: |
        Create influencer profile (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. If this updates a revisioned record, expected_revision is required (428 if
        missing; 409 on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InfluencerProfileCreateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InfluencerProfileEnvelope' }
  /profile/get:
    post:
      summary: Get influencer profile (draft)
      description: |
        Get influencer profile (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InfluencerProfileGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InfluencerProfileEnvelope' }
  /campaign/create:
    post:
      summary: Create campaign (draft)
      description: |
        Create campaign (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignCreateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignEnvelope' }
  /campaign/get:
    post:
      summary: Get campaign (draft)
      description: |
        Get campaign (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignEnvelope' }
  /campaign/list:
    post:
      summary: List campaigns (draft)
      description: |
        List campaigns (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignListEnvelope' }
  /campaign/status/set:
    post:
      summary: Set campaign status (draft)
      description: |
        Set campaign status (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CampaignStatusSetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CampaignEnvelope' }
  /discount-tier/set:
    post:
      summary: Set channel discount tier (draft)
      description: |
        Set channel discount tier (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. If this updates a revisioned record, expected_revision is required (428 if
        missing; 409 on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DiscountTierSetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DiscountTierEnvelope' }
  /discount-tier/get:
    post:
      summary: Get channel discount tier (draft)
      description: |
        Get channel discount tier (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. Org-scoped reads may return 404 for non-associated callers
        (anti-enumeration). Route class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DiscountTierGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DiscountTierEnvelope' }
  /discount-tier/list:
    post:
      summary: List channel discount tiers (draft)
      description: |
        List channel discount tiers (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier
        B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DiscountTierListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DiscountTierListEnvelope' }
  /attribution/record:
    post:
      summary: Record attribution (draft)
      description: |
        Record attribution (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier D (p95 300ms, p99 600ms).
      x-status: draft
      x-route-class: Tier D
      x-qps-target: 1000
      x-concurrency-target: 2000
      x-latency-p95-ms: 300
      x-latency-p99-ms: 600
      parameters:
        - { $ref: '#/components/parameters/OrgHeader' }
        - { $ref: '#/components/parameters/ChannelHeader' }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/AttributionRecordRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Envelope' }
  /earnings/list:
    post:
      summary: List earnings (draft)
      description: |
        List earnings (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/EarningsListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/EarningsListEnvelope' }
  /earnings/hold:
    post:
      summary: Hold earnings (draft)
      description: |
        Hold earnings (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Route class Tier B (p95 400ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 200
      x-concurrency-target: 400
      x-latency-p95-ms: 400
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/EarningsHoldRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/EarningEnvelope' }
  /earnings/release:
    post:
      summary: Release earnings to payable (draft)
      description: |
        Release earnings to payable (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. Route class Tier B (p95 400ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 200
      x-concurrency-target: 400
      x-latency-p95-ms: 400
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/EarningsReleaseRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/EarningEnvelope' }
  /earnings/clawback:
    post:
      summary: Apply earnings clawback (draft)
      description: |
        Apply earnings clawback (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. Route class Tier B (p95 400ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 200
      x-concurrency-target: 400
      x-latency-p95-ms: 400
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/EarningsClawbackRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/EarningEnvelope' }
  /dispute/create:
    post:
      summary: Create dispute (draft)
      description: |
        Create dispute (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier B (p95 400ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 200
      x-concurrency-target: 400
      x-latency-p95-ms: 400
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DisputeCreateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DisputeEnvelope' }
  /dispute/get:
    post:
      summary: Get dispute (draft)
      description: |
        Get dispute (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DisputeGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DisputeEnvelope' }
  /dispute/list:
    post:
      summary: List disputes (draft)
      description: |
        List disputes (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DisputeListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DisputeListEnvelope' }
  /dispute/status/set:
    post:
      summary: Set dispute status (draft)
      description: |
        Set dispute status (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier B (p95 400ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 200
      x-concurrency-target: 400
      x-latency-p95-ms: 400
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/DisputeStatusSetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/DisputeEnvelope' }
  /payout/submit:
    post:
      summary: Submit payout (draft)
      description: |
        Submit payout (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/PayoutSubmitRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/PayoutEnvelope' }
  /payout/ready/set:
    post:
      summary: Set payout readiness (draft)
      description: |
        Set payout readiness (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/PayoutReadySetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/PayoutReadyEnvelope' }
  /payout/ready/get:
    post:
      summary: Get payout readiness (draft)
      description: |
        Get payout readiness (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/PayoutReadyGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/PayoutReadyEnvelope' }
  /statement/create:
    post:
      summary: Create payout statement (draft)
      description: |
        Create payout statement (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. If this updates a revisioned record, expected_revision is required (428 if missing;
        409 on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/StatementCreateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/StatementEnvelope' }
  /statement/get:
    post:
      summary: Get payout statement (draft)
      description: |
        Get payout statement (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/StatementGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/StatementEnvelope' }
  /statement/list:
    post:
      summary: List payout statements (draft)
      description: |
        List payout statements (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/StatementListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/StatementListEnvelope' }
  /comment:
    post:
      summary: Add comment (draft)
      description: |
        Add comment (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentAddRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentEnvelope' }
  /comment/get:
    post:
      summary: Get comment (draft)
      description: |
        Get comment (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentEnvelope' }
  /comment/list:
    post:
      summary: List comments (draft)
      description: |
        List comments (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentListEnvelope' }
  /comment/revise:
    post:
      summary: Revise comment (draft)
      description: |
        Revise comment (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentReviseRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentEnvelope' }
  /comment/status:
    post:
      summary: Update comment status (draft)
      description: |
        Update comment status (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentStatusRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentEnvelope' }
  /comment/report:
    post:
      summary: Report top-N largest comments (draft)
      description: |
        Report top-N largest comments (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CommentReportRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CommentReportEnvelope' }
  /inbox/create:
    post:
      summary: Create inbox notification (draft)
      description: |
        Create inbox notification (draft). Auth is via headers; org identity uses x-orgcode or body
        placement as documented. If this updates a revisioned record, expected_revision is required (428 if
        missing; 409 on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InboxCreateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InboxEnvelope' }
  /inbox/get:
    post:
      summary: Get inbox notification (draft)
      description: |
        Get inbox notification (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. Org-scoped reads may return 404 for non-associated callers (anti-enumeration). Route
        class Tier B (p95 300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InboxGetRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InboxEnvelope' }
  /inbox/list:
    post:
      summary: List inbox notifications (draft)
      description: |
        List inbox notifications (draft). Auth is via headers; org identity uses x-orgcode or body placement
        as documented. Paginated with limit/next_token (default 8; clamp 1–256). Route class Tier B (p95
        300ms).
      x-status: draft
      x-route-class: Tier B
      x-qps-target: 300
      x-concurrency-target: 500
      x-latency-p95-ms: 300
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InboxListRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InboxListEnvelope' }
  /inbox/status:
    post:
      summary: Update inbox status (draft)
      description: |
        Update inbox status (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. If this updates a revisioned record, expected_revision is required (428 if missing; 409
        on mismatch). Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InboxStatusRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InboxEnvelope' }
  /inbox/state:
    post:
      summary: Update inbox state (draft)
      description: |
        Update inbox state (draft). Auth is via headers; org identity uses x-orgcode or body placement as
        documented. Route class Tier A (p95 500ms).
      x-status: draft
      x-route-class: Tier A
      x-qps-target: 50
      x-concurrency-target: 200
      x-latency-p95-ms: 500
      parameters: [ { $ref: '#/components/parameters/OrgHeader' }, { $ref: '#/components/parameters/LogicalHeader' } ]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/InboxStateRequest' }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/InboxEnvelope' }
