openapi: 3.0.3
info:
  title: 1ClickImpact Environmental Impact API
  description: >
    REST API for programmatic environmental impact — plant trees, remove ocean plastic,
    capture carbon, restore coral reefs, and make charitable donations. Integrate sustainability into any
    product in minutes. Real-time webhooks are also available to push impact lifecycle
    events to your endpoint (see the Webhooks tag and https://docs.1clickimpact.com/webhooks).
  version: 1.0.0
  contact:
    name: 1ClickImpact Support
    url: https://1clickimpact.com/contact
  license:
    name: Proprietary
    url: https://1clickimpact.com/terms

servers:
  - url: https://api.1clickimpact.com
    description: Production
  - url: https://sandbox.1clickimpact.com
    description: Sandbox (free testing — no real-world impact)

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key obtained from your 1ClickImpact dashboard.

  schemas:
    Sdg:
      type: object
      properties:
        id:
          type: string
          description: SDG identifier slug.
          example: climate-action
        number:
          type: integer
          description: Official UN SDG goal number.
          example: 13
        title:
          type: string
          description: Display title of the SDG.
          example: Climate Action
        description:
          type: string
          description: Official UN description of the goal.
        color:
          type: string
          description: Hex color code for the SDG.
          example: '#3F7E44'
        link:
          type: string
          format: uri
          description: URL to the official UN SDG page.
          example: https://sdgs.un.org/goals/goal13
        icon_url:
          type: string
          format: uri
          description: URL to the SDG icon image.

    Project:
      type: object
      properties:
        project_id:
          type: string
          description: Unique slug identifier for the project.
          example: trees-uganda-di
        name:
          type: string
          description: Display name of the project.
          example: Dream International Uganda
        type:
          type: string
          enum: [trees, ocean, carbon]
          description: Impact type of the project.
          example: trees
        location:
          type: string
          description: Human-readable location of the project.
          example: Uganda
        description:
          type: string
          description: One-sentence summary of the project.
        about:
          type: array
          items:
            type: string
          description: Array of paragraphs providing deeper detail about the project.
        country_code:
          type: string
          description: ISO 3166-1 alpha-2 country code where the project operates.
          example: UG
        organization:
          type: string
          description: Name of the non-profit or partner executing the project.
          example: Planting on Demand
        sdgs:
          type: array
          items:
            $ref: '#/components/schemas/Sdg'
          description: Array of UN Sustainable Development Goals this project contributes to.
        image_urls:
          type: array
          items:
            type: string
            format: uri
          description: Array of image URLs for the project.
        latitude:
          type: number
          description: Latitude coordinate of the project location.
          example: -12.3733
        longitude:
          type: number
          description: Longitude coordinate of the project location.
          example: 27.2903
        available:
          type: boolean
          description: Whether the project is currently accepting new impacts.
          example: true

    Metadata:
      type: object
      additionalProperties:
        type: string
        maxLength: 500
      maxProperties: 20
      description: >
        A set of key-value pairs for storing additional information about the impact.
        Keys must be strings (max 40 characters) and values must be strings (max 500 characters).
        Maximum 20 key-value pairs. Reserved keys (`gift`, `widgetID`) cannot be used.
      example:
        order_id: ORD-456
        source: shopify

    CarbonResult:
      type: object
      description: Website carbon analysis result.
      properties:
        url:
          type: string
          description: Normalized URL analyzed (lowercase, no protocol, no trailing slash).
          example: example.com
        cleaner_than:
          type: number
          format: float
          description: Fraction of websites this page is cleaner than (0.0–1.0).
          example: 0.91
        rating:
          type: string
          enum: ['A+', 'A', 'B', 'C', 'D', 'E', 'F']
          description: 'Carbon rating grade based on CO₂ per page view.'
          example: A
        green_hosting:
          type: boolean
          description: Whether the hosting uses renewable energy (verified by Green Web Foundation).
          example: false
        statistics:
          type: object
          properties:
            transfer_size:
              type: integer
              description: Total page weight in bytes.
              example: 495573
            energy:
              type: number
              format: float
              description: Energy consumed per page view in kWh.
              example: 0.000139
            co2:
              type: object
              properties:
                grid:
                  type: object
                  properties:
                    grams:
                      type: number
                      format: float
                      description: Grams CO₂ per view assuming standard grid energy.
                      example: 0.068
                renewable:
                  type: object
                  properties:
                    grams:
                      type: number
                      format: float
                      description: Grams CO₂ per view assuming renewable energy for data center.
                      example: 0.057
        tested_on:
          type: string
          format: date
          description: Date the page was analyzed (YYYY-MM-DD). Results cached for 7 days.
          example: '2026-04-21'

    AiEnergyBand:
      type: object
      description: A percentile summary of one quantity (p5 / median / p95 / mean).
      properties:
        p5: { type: number, format: float }
        p50: { type: number, format: float }
        p95: { type: number, format: float }
        mean: { type: number, format: float }
    AiEnergyBasis:
      type: object
      description: The eight quantities for one time basis; each is a p5/p50/p95/mean band.
      properties:
        energy: { $ref: '#/components/schemas/AiEnergyBand' }
        water_total: { $ref: '#/components/schemas/AiEnergyBand' }
        water_onsite: { $ref: '#/components/schemas/AiEnergyBand' }
        water_offsite: { $ref: '#/components/schemas/AiEnergyBand' }
        co2e_location_based: { $ref: '#/components/schemas/AiEnergyBand' }
        co2e_market_based: { $ref: '#/components/schemas/AiEnergyBand' }
        co2e_embodied: { $ref: '#/components/schemas/AiEnergyBand' }
        co2e_total: { $ref: '#/components/schemas/AiEnergyBand' }
    AiEnergyRequest:
      type: object
      required: [model_id, scale]
      description: AI energy calculate input. Only model_id and scale are required.
      properties:
        model_id:
          type: string
          description: Model to estimate. Use generic-frontier for a provider-agnostic frontier model. See GET /v1/ai_energy/options.
          example: claude-fable-5
        region_id:
          type: string
          description: Grid & water region. Defaults to us-average.
          example: us-average
        workload_id:
          type: string
          description: Task preset that sets typical token counts. Defaults to chat.
          example: chat
        regime_id:
          type: string
          description: Serving regime (how aggressively requests are batched). Defaults to production-saturated.
          example: production-saturated
        boundary_id:
          type: string
          enum: [accelerator, node, comprehensive]
          description: Energy boundary. Defaults to comprehensive.
          example: comprehensive
        scale:
          type: object
          required: [mode]
          description: How much the model is used per month.
          properties:
            mode: { type: string, enum: [queries, tokens, users], default: queries }
            queries_per_month: { type: number, example: 1000000 }
            input_tokens_per_month: { type: number }
            output_tokens_per_month: { type: number }
            users: { type: number }
            queries_per_user_per_day: { type: number }
        input_tokens: { type: number, description: Override the workload median input token count. }
        output_tokens: { type: number, description: Override the workload median output token count. }
        cache_hit_rate: { type: number, description: Share of input tokens served from a prompt cache (0.0-1.0). }
        reasoning: { type: boolean, description: Switch a hybrid model into extended-thinking mode. Defaults to false. }
        input_modality: { type: string, enum: [text, image, video], default: text }
        batch_size: { type: integer, description: Explicit serving batch size (self-hosted only). }
        include_embodied: { type: boolean, default: true, description: Include embodied (manufacturing) emissions in co2e_total. }
        samples: { type: integer, default: 4000, description: Monte-Carlo sample count. }
    AiEnergyResult:
      type: object
      description: Full AI inference footprint — energy, water, and carbon as p5/median/p95 bands.
      properties:
        per_query: { $ref: '#/components/schemas/AiEnergyBasis' }
        per_month: { $ref: '#/components/schemas/AiEnergyBasis' }
        per_year: { $ref: '#/components/schemas/AiEnergyBasis' }
        breakdown:
          type: object
          description: Where the energy goes, in percent (accelerator, host, idle, facility, prefill, decode, cache savings).
        equivalents:
          type: object
          description: Human-scale comparisons keyed by carbon, energy, and water.
        assumptions:
          type: object
          description: Every resolved input echoed back for reproducibility (model, provider, hardware, region, tokens, PUE, intensities, ...).
        confidence:
          type: object
          properties:
            overall: { type: string, enum: [measured, derived, estimated] }
            uncertainty_factor: { type: number, format: float, description: P95/P5 on monthly energy. }
            drivers: { type: array, items: { type: string } }
            caveats: { type: array, items: { type: string } }
        warnings:
          type: array
          items: { type: string }
        sources:
          type: array
          items:
            type: object
            properties:
              key: { type: string }
              citation: { type: string }
        units:
          type: object
          additionalProperties: { type: string }
          description: Map of each field path to its unit (e.g. per_query.energy -> Wh).
        data_version: { type: string, example: '2026.08' }
    AiEnergyOptions:
      type: object
      description: Catalog of models, providers, regions, workloads, regimes, boundaries, and defaults.
      properties:
        data_version: { type: string, example: '2026.08' }
        schema_version: { type: string, example: '1.0.0' }
        models: { type: array, items: { type: object } }
        models_by_provider: { type: object }
        providers: { type: object }
        hardware: { type: object }
        regions: { type: array, items: { type: object } }
        workloads: { type: array, items: { type: object } }
        regimes: { type: array, items: { type: object } }
        boundaries: { type: array, items: { type: object } }
        generative_units: { type: array, items: { type: object } }
        defaults: { type: object }
    CustomerFields:
      type: object
      properties:
        customer_email:
          type: string
          format: email
          description: Plant/clean/offset on behalf of this customer. Enables per-customer tracking.
        customer_name:
          type: string
          description: Display name for the customer.
        notify:
          type: boolean
          default: true
          description: Send an email notification to the customer.
        metadata:
          $ref: '#/components/schemas/Metadata'

    ImpactBreakdown:
      type: object
      properties:
        tree_planted:
          type: integer
          description: Total trees planted.
        waste_removed:
          type: number
          description: Total ocean waste removed in lbs.
        carbon_captured:
          type: number
          description: Total carbon captured in lbs.
        coral_restored:
          type: integer
          description: Total coral fragments restored.
        money_donated:
          type: integer
          description: Total money donated in cents.

    ImpactRecord:
      type: object
      properties:
        user_id:
          type: string
        type:
          type: string
          enum: [tree_planted, waste_removed, carbon_captured, coral_restored, money_donated]
        amount:
          type: number
        time_utc:
          type: string
          format: date-time
        metadata:
          $ref: '#/components/schemas/Metadata'

    Error:
      type: object
      properties:
        error:
          type: string
        message:
          type: string

    WebhookEvent:
      type: object
      description: >
        Envelope delivered via HTTP POST to your registered endpoint for each subscribed
        impact event. Signed with the X-1CI-Signature header (HMAC-SHA256 of "{t}.{rawBody}",
        keyed with your endpoint's whsec_ secret). See https://docs.1clickimpact.com/webhooks.
      required: [id, type, sent_at, data]
      properties:
        id:
          type: string
          description: Unique event identifier. Stable across retries, so deduplicate on this.
          example: U1234-2026-03-12T15:22:14.753Z#impact.donation_sent#2026-03-19T15:22:14.753Z
        type:
          type: string
          description: The event type.
          enum:
            - impact.initiated
            - impact.donation_available
            - impact.donation_sent
            - impact.completed
            - impact.cancelled
          example: impact.donation_sent
        sent_at:
          type: string
          format: date-time
          description: UTC timestamp (ISO 8601) when the event was generated.
          example: '2026-03-19T15:27:14.753Z'
        data:
          type: object
          required: [tracking_id, user_id, occurred_at, track]
          properties:
            tracking_id:
              type: string
              description: The tracking ID of the impact, formatted as user_id-time_utc.
              example: U1234-2026-03-12T15:22:14.753Z
            user_id:
              type: string
              description: The user ID the impact belongs to (your org's user or a customer).
              example: U1234
            org_id:
              type: string
              description: Organization ID, when the impact is associated with one. Omitted otherwise.
              example: O5678
            occurred_at:
              type: string
              format: date-time
              description: UTC timestamp of the lifecycle change that triggered this event.
              example: '2026-03-19T15:22:14.753Z'
            track:
              type: object
              additionalProperties: true
              description: The full GET /v1/track response for this impact (same snake_case fields).

paths:
  /v1/whoami:
    get:
      operationId: whoami
      summary: Verify API key and retrieve account details
      description: Confirms your API integration is working and returns your account information.
      tags: [Account]
      responses:
        '200':
          description: Account details
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  email:
                    type: string
                    example: my-email@email.com
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/plant_tree:
    post:
      operationId: plantTree
      summary: Plant trees
      description: >
        Plant trees for your organization or on behalf of a customer.
        Provide `customer_email` to attribute impact to a specific customer.
        Each unit = 1 tree.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/CustomerFields'
                - type: object
                  required: [amount]
                  properties:
                    amount:
                      type: integer
                      minimum: 1
                      description: Number of trees to plant.
                      example: 5
                    category:
                      type: string
                      enum: [food]
                      description: >-
                        Type of tree planting project. Only supported value is "food" — plants food-bearing trees that
                        provide nutrition and income for local communities, and grants access to exclusive live planting sessions.
                        If omitted, standard reforestation trees are planted.
            example:
              amount: 5
              customer_email: customer@example.com
              customer_name: Jane Doe
              category: food
              notify: true
              metadata:
                order_id: ORD-456
                source: shopify
      responses:
        '200':
          description: Trees planted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  tree_planted:
                    type: integer
                    example: 5
                  time_utc:
                    type: string
                    format: date-time
                    example: '2024-09-16T20:34:04.429Z'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/clean_ocean:
    post:
      operationId: cleanOcean
      summary: Remove ocean plastic waste
      description: >
        Remove plastic and waste from the ocean. Amount is in lbs.
        Provide `customer_email` to attribute impact to a specific customer.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/CustomerFields'
                - type: object
                  required: [amount]
                  properties:
                    amount:
                      type: integer
                      minimum: 1
                      description: Amount of ocean waste to remove in lbs (1–10,000,000).
                      example: 5
            example:
              amount: 5
              customer_email: customer@example.com
              notify: true
      responses:
        '200':
          description: Ocean cleaned successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  waste_removed:
                    type: number
                    example: 5
                  time_utc:
                    type: string
                    format: date-time
                    example: '2024-09-16T20:34:04.429Z'

  /v1/restore_coral:
    post:
      operationId: restoreCoral
      summary: Restore coral reef
      description: >
        Fund coral reef restoration by outplanting coral fragments. Amount is the
        number of coral fragments (~15 fragments ≈ 1 reef structure; each fragment
        restores ≈ 144 cm² / 22.32 in² of reef).
        Provide `customer_email` to attribute impact to a specific customer.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/CustomerFields'
                - type: object
                  required: [amount]
                  properties:
                    amount:
                      type: integer
                      minimum: 1
                      description: Number of coral fragments to restore (1–10,000,000).
                      example: 20
            example:
              amount: 20
              customer_email: customer@example.com
              notify: true
      responses:
        '200':
          description: Coral restored successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  coral_restored:
                    type: integer
                    example: 20
                  time_utc:
                    type: string
                    format: date-time
                    example: '2024-09-16T20:34:04.429Z'

  /v1/capture_carbon:
    post:
      operationId: captureCarbon
      summary: Capture carbon / offset CO₂
      description: >
        Capture carbon and offset CO₂ emissions. Amount is in lbs.
        Provide `customer_email` to attribute impact to a specific customer.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/CustomerFields'
                - type: object
                  required: [amount]
                  properties:
                    amount:
                      type: integer
                      minimum: 1
                      description: Amount of CO₂ to capture in lbs (1–10,000,000).
                      example: 5
            example:
              amount: 5
              customer_email: customer@example.com
              notify: true
      responses:
        '200':
          description: Carbon captured successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  carbon_captured:
                    type: number
                    example: 5
                  time_utc:
                    type: string
                    format: date-time
                    example: '2024-09-16T20:34:04.429Z'

  /v1/donate_money:
    post:
      operationId: donateMoney
      summary: Make a charitable donation
      description: >
        Donate money to a cause. Amount is in the smallest currency unit (cents for USD).
        Supports optional `category` to tag donations with a specific cause.
        Provide `customer_email` to attribute impact to a specific customer.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/CustomerFields'
                - type: object
                  required: [amount]
                  properties:
                    amount:
                      type: integer
                      minimum: 1
                      description: Amount to donate in cents (e.g. 500 = $5.00).
                      example: 500
                    category:
                      type: string
                      enum: [veterans, animals, hunger, education, climate, water, healthcare, housing, youth, disaster]
                      description: >-
                        Donation cause category ID. The corresponding full label will appear in the
                        /v1/track response as donation_category. Valid values: veterans (Veterans Support),
                        animals (Animal Welfare), hunger (Hunger Relief), education (Education),
                        climate (Climate Action), water (Clean Water), healthcare (Healthcare),
                        housing (Housing & Shelter), youth (Youth Development), disaster (Disaster Relief).
            example:
              amount: 500
              category: hunger
              customer_email: customer@example.com
              notify: true
      responses:
        '200':
          description: Donation made successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  money_donated:
                    type: integer
                    example: 500
                  category:
                    type: string
                    description: The donation cause category ID, if one was provided.
                    example: hunger
                  time_utc:
                    type: string
                    format: date-time
                    example: '2024-09-16T20:34:04.429Z'

  /v1/cancel_impact:
    post:
      operationId: cancelImpact
      summary: Cancel and reverse a previously created impact
      description: >
        Cancel and reverse a previously created impact. Designed for refund flows. Removes the impact
        from aggregate totals, reverses usage billing, and marks it as cancelled in the tracking system.
        The original record is preserved for audit purposes. This endpoint is idempotent — calling it
        multiple times for the same impact returns the same result without double-reversing aggregates.
        Impacts that have already been processed (donation received by a non-profit) cannot be cancelled
        via the API. You are not charged for cancelled impacts.
      tags: [Impact Actions]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [user_id, time_utc]
              properties:
                user_id:
                  type: string
                  description: The user ID associated with the impact to cancel (format U12345).
                  example: U1234
                time_utc:
                  type: string
                  format: date-time
                  description: The UTC timestamp of the original impact (ISO 8601 format).
                  example: '2025-03-12T15:22:14.753Z'
                reason:
                  type: string
                  maxLength: 200
                  description: Reason for the cancellation (max 200 characters).
                  example: order refunded
            example:
              user_id: U1234
              time_utc: '2025-03-12T15:22:14.753Z'
              reason: order refunded
      responses:
        '200':
          description: Impact cancelled successfully (or already cancelled)
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U1234
                  time_utc:
                    type: string
                    format: date-time
                    example: '2025-03-12T15:22:14.753Z'
                  cancelled_on:
                    type: string
                    format: date-time
                    description: UTC time when the impact was cancelled.
                    example: '2025-04-30T10:15:32.000Z'
                  reason:
                    type: string
                    description: Cancellation reason if provided.
                    example: order refunded
                  tree_planted:
                    type: integer
                    description: Number of trees reversed. Only present for tree planting impacts.
                  waste_removed:
                    type: integer
                    description: Ocean waste (lbs) reversed. Only present for ocean cleanup impacts.
                  carbon_captured:
                    type: integer
                    description: Carbon (lbs) reversed. Only present for carbon capture impacts.
                  coral_restored:
                    type: integer
                    description: Coral fragments reversed. Only present for coral restoration impacts.
                  money_donated:
                    type: integer
                    description: Money (cents) reversed. Only present for donation impacts.
                  category:
                    type: string
                    description: Category of the cancelled impact if one was set.
                  message:
                    type: string
                    description: '"impact cancelled successfully" or "impact was already cancelled".'
                    example: impact cancelled successfully
        '400':
          description: Bad request — impact not found, already processed, or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/impact:
    get:
      operationId: getAggregatedImpact
      summary: Retrieve aggregated lifetime impact
      description: >
        Returns total lifetime impact across all categories. Includes top-level totals (user + customer combined)
        and a breakdown between your direct impact (user_impact) and impact on behalf of customers (customer_impact).
      tags: [Impact Data]
      responses:
        '200':
          description: Aggregated impact totals
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  tree_planted:
                    type: integer
                    description: Total trees planted (user + customer combined).
                  waste_removed:
                    type: integer
                    description: Total ocean waste removed in lbs (user + customer combined).
                  carbon_captured:
                    type: integer
                    description: Total carbon captured in lbs (user + customer combined).
                  coral_restored:
                    type: integer
                    description: Total coral fragments restored (user + customer combined).
                  money_donated:
                    type: integer
                    description: Total money donated in cents (user + customer combined).
                  user_impact:
                    $ref: '#/components/schemas/ImpactBreakdown'
                  customer_impact:
                    $ref: '#/components/schemas/ImpactBreakdown'

  /v1/impact/daily:
    get:
      operationId: getDailyImpact
      summary: Retrieve daily impact time-series
      description: >
        Returns a time-series of daily impact data. Use optional query parameters to
        filter by date range. Useful for dashboards, reports, and trend analysis.
      tags: [Impact Data]
      parameters:
        - name: start_date
          in: query
          description: Filter from this date (ISO 8601 format).
          schema:
            type: string
            format: date
            example: '2025-01-01'
        - name: end_date
          in: query
          description: Filter to this date (ISO 8601 format).
          schema:
            type: string
            format: date
            example: '2025-03-01'
      responses:
        '200':
          description: Daily impact time-series
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: U123
                  daily_impact:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                          format: date
                          example: '2025-01-15'
                        tree_planted:
                          type: integer
                        waste_removed:
                          type: integer
                        carbon_captured:
                          type: integer
                        coral_restored:
                          type: integer
                        money_donated:
                          type: integer

  /v1/records:
    get:
      operationId: getRecords
      summary: Retrieve your organization's impact records
      description: >
        Returns your full impact history. Filter by impact type using `filter_by` (repeatable).
        Uses cursor-based pagination — pass `cursor` from response into next request.
      tags: [Records]
      parameters:
        - name: filter_by
          in: query
          description: Filter by impact type. Repeatable (e.g. ?filter_by=carbon_captured&filter_by=waste_removed).
          schema:
            type: string
            enum: [tree_planted, waste_removed, carbon_captured, coral_restored, money_donated]
        - name: start_date
          in: query
          description: Return records after this date (YYYY-MM-DD).
          schema:
            type: string
            format: date
            example: '2024-01-01'
        - name: end_date
          in: query
          description: Return records up to this date (YYYY-MM-DD).
          schema:
            type: string
            format: date
            example: '2024-12-31'
        - name: limit
          in: query
          description: Number of records per page. Default 10, max 1000.
          schema:
            type: integer
            example: 10
        - name: cursor
          in: query
          description: Cursor from previous response for fetching the next page.
          schema:
            type: string
        - name: sort_order
          in: query
          description: Sort by time_utc. "asc" (default) or "desc".
          schema:
            type: string
            enum: [asc, desc]
      responses:
        '200':
          description: List of impact records
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_records:
                    type: array
                    items:
                      $ref: '#/components/schemas/ImpactRecord'
                  cursor:
                    type: string
                    description: Present only when more pages exist. Pass as `cursor` param in next request.

  /v1/customer_records:
    get:
      operationId: getCustomerRecords
      summary: Retrieve customer impact records
      description: >
        Returns per-customer impact history. Each record contains a nested `customer` object
        with customer_id, customer_email, and customer_name. Uses cursor-based pagination.
      tags: [Records]
      parameters:
        - name: customer_email
          in: query
          description: Filter records for a specific customer.
          schema:
            type: string
            format: email
        - name: filter_by
          in: query
          description: Filter by impact type. Repeatable.
          schema:
            type: string
            enum: [tree_planted, waste_removed, carbon_captured, coral_restored, money_donated]
        - name: start_date
          in: query
          description: Return records after this date (YYYY-MM-DD).
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          description: Return records up to this date (YYYY-MM-DD).
          schema:
            type: string
            format: date
        - name: limit
          in: query
          description: Default 10, max 1000.
          schema:
            type: integer
            example: 10
        - name: cursor
          in: query
          description: Cursor from previous response for next page.
          schema:
            type: string
        - name: sort_order
          in: query
          description: Sort by time_utc. "asc" (default) or "desc".
          schema:
            type: string
            enum: [asc, desc]
      responses:
        '200':
          description: List of customer impact records
          content:
            application/json:
              schema:
                type: object
                properties:
                  customer_records:
                    type: array
                    items:
                      type: object
                      properties:
                        user_id:
                          type: string
                        customer:
                          type: object
                          properties:
                            customer_id:
                              type: string
                            customer_email:
                              type: string
                            customer_name:
                              type: string
                        time_utc:
                          type: string
                          format: date-time
                        tree_planted:
                          type: integer
                        waste_removed:
                          type: integer
                        carbon_captured:
                          type: integer
                        coral_restored:
                          type: integer
                        money_donated:
                          type: integer
                        metadata:
                          $ref: '#/components/schemas/Metadata'
                  cursor:
                    type: string
                    description: Present only when more pages exist.

  /v1/customers:
    get:
      operationId: getCustomers
      summary: List all onboarded customers
      description: >
        Returns a list of all customers who have had impact created on their behalf.
        Customers are auto-onboarded when you create impact using their customer_email.
      tags: [Records]
      parameters:
        - name: customer_email
          in: query
          description: Retrieve or check a specific customer.
          schema:
            type: string
            format: email
        - name: limit
          in: query
          description: Default 10, max 1000.
          schema:
            type: integer
            example: 10
        - name: cursor
          in: query
          description: Cursor from previous response for next page.
          schema:
            type: string
        - name: sort_order
          in: query
          description: Sort by onboarded_on. "asc" (default) or "desc".
          schema:
            type: string
            enum: [asc, desc]
      responses:
        '200':
          description: List of customers
          content:
            application/json:
              schema:
                type: object
                properties:
                  customers:
                    type: array
                    items:
                      type: object
                      properties:
                        customer_id:
                          type: string
                          example: U1234
                        customer_email:
                          type: string
                        customer_name:
                          type: string
                        onboarded_on:
                          type: string
                          format: date-time
                  cursor:
                    type: string
                    description: Present only when more pages exist.

  /v1/track:
    get:
      operationId: trackImpact
      summary: Track real-time lifecycle of a specific impact event
      description: >
        Returns real-time tracking data for a specific impact event across the complete environmental impact lifecycle.
        `user_id` and `time_utc` can be obtained from the POST action response (plant_tree, clean_ocean,
        capture_carbon, donate_money) OR from /v1/records or /v1/customer_records.
      tags: [Tracking]
      parameters:
        - name: user_id
          in: query
          required: true
          description: From the POST action response or /v1/records / /v1/customer_records.
          schema:
            type: string
            example: U1234
        - name: time_utc
          in: query
          required: true
          description: ISO 8601 timestamp. From the POST action response or /v1/records / /v1/customer_records.
          schema:
            type: string
            format: date-time
            example: '2025-03-12T15:22:14.753Z'
      responses:
        '200':
          description: Impact tracking details
          content:
            application/json:
              schema:
                type: object
                properties:
                  tracking_id:
                    type: string
                    description: Unique identifier formatted as user_id-time_utc.
                    example: U1234-2025-03-12T15:22:14.753Z
                  impact_initiated:
                    type: string
                    format: date-time
                    description: UTC time when the impact process was initiated.
                  tree_planted:
                    type: integer
                  waste_removed:
                    type: integer
                  carbon_captured:
                    type: integer
                  coral_restored:
                    type: integer
                  money_donated:
                    type: integer
                  category:
                    type: string
                    description: Impact category. "food" for food-bearing trees, or a donation cause ID (e.g., "hunger", "education", "veterans") for donations. See POST /v1/donate_money for the full list of supported categories.
                  donation_available:
                    type: string
                    format: date-time
                    description: UTC time when donation became available. Optional.
                  donation_sent:
                    type: string
                    format: date-time
                    description: UTC time when donation was transferred to nonprofit. Optional.
                  assigned_agent:
                    type: string
                    description: Name of nonprofit/agent assigned to execute the impact. Optional.
                    example: Planting On Demand
                  project_location:
                    type: string
                    description: Description of project location and implementing partners. Optional.
                    example: Rwenzori Mountains, Uganda with Dream International.
                  location_map:
                    type: string
                    description: Google Maps embed URL for visualizing project location. Optional.
                  impact_completed:
                    type: string
                    format: date-time
                    description: UTC time when the impact was completed. Optional.
                  project_id:
                    type: string
                    description: Slug identifier of the environmental project associated with this impact. Use with GET /v1/projects/:project_id. Optional.
                    example: trees-uganda-di
                  donation_category:
                    type: string
                    description: What type of impact the donation funded (e.g. "planting food trees"). Only for donate_money. Optional.
                  certificate:
                    type: string
                    format: uri
                    description: Certificate URL. Only present in production. Optional.
                  impact_video:
                    type: string
                    format: uri
                    description: URL to video recording or live session. Optional.
                  live_session_date:
                    type: string
                    format: date-time
                    description: UTC timestamp for scheduled live session. Optional.
                  metadata:
                    $ref: '#/components/schemas/Metadata'
                  is_test_transaction:
                    type: boolean
                    description: True if this was a test transaction. Optional.
                  is_bonus_impact:
                    type: boolean
                    description: True if this was a bonus impact from a subscription plan. Optional.
                  cancelled_on:
                    type: string
                    format: date-time
                    description: UTC time when the impact was cancelled. Only present for cancelled impacts. Optional.
                  cancellation_reason:
                    type: string
                    description: Reason provided for the cancellation. Only present for cancelled impacts that included a reason. Optional.

  /v1/projects:
    get:
      operationId: listProjects
      summary: List all environmental impact projects
      description: >
        Returns all available verified environmental impact projects. Filter by type
        and request localized content via the locale parameter.
      tags: [Projects]
      parameters:
        - name: type
          in: query
          description: Filter projects by impact type.
          schema:
            type: string
            enum: [trees, ocean, carbon]
        - name: locale
          in: query
          description: Return project content in the specified language. Falls back to English when translation is unavailable.
          schema:
            type: string
            enum: [en, de, es, fr, nl]
            default: en
      responses:
        '200':
          description: List of environmental impact projects
          content:
            application/json:
              schema:
                type: object
                properties:
                  projects:
                    type: array
                    items:
                      $ref: '#/components/schemas/Project'
              example:
                projects:
                  - project_id: trees-uganda-di
                    name: Dream International Uganda
                    type: trees
                    location: Uganda
                    description: Dream International is a community-led tree and forest restoration in the Rwenzori Mountain region for ecosystem services, biodiversity, and climate resilience.
                    country_code: UG
                    organization: Planting on Demand
                    latitude: -12.3733
                    longitude: 27.2903
                    available: true
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/projects/{project_id}:
    get:
      operationId: getProject
      summary: Retrieve a single project
      description: >
        Returns full details for a single environmental impact project by its ID,
        including SDG alignments, images, geographic coordinates, and localized content.
      tags: [Projects]
      parameters:
        - name: project_id
          in: path
          required: true
          description: Unique slug identifier of the project (e.g., "trees-uganda-di"). Obtain from GET /v1/projects or from the project_id field in a /v1/track response.
          schema:
            type: string
            example: trees-uganda-di
        - name: locale
          in: query
          description: Return project content in the specified language. Falls back to English when translation is unavailable.
          schema:
            type: string
            enum: [en, de, es, fr, nl]
            default: en
      responses:
        '200':
          description: Project details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
              example:
                project_id: trees-uganda-di
                name: Dream International Uganda
                type: trees
                location: Uganda
                description: Dream International is a community-led tree and forest restoration in the Rwenzori Mountain region for ecosystem services, biodiversity, and climate resilience.
                about:
                  - Dream International leads a community-driven tree and forest restoration initiative in the Rwenzori Mountain region of western Uganda — part of the globally important Albertine Rift biodiversity hotspot.
                  - Local communities are trained and employed as stewards of restored forest areas, receiving ongoing support in sustainable land management, agroforestry, and eco-enterprise development.
                  - By restoring tree cover in the Rwenzori highlands, the project directly protects headwaters that supply clean drinking water to thousands of downstream households.
                country_code: UG
                organization: Planting on Demand
                sdgs:
                  - id: climate-action
                    number: 13
                    title: Climate Action
                    description: Take urgent action to combat climate change and its impacts.
                    color: '#3F7E44'
                    link: https://sdgs.un.org/goals/goal13
                    icon_url: https://images.s3.us-east-1.amazonaws.com/projects/sdgs/E-WEB-Goal-13.jpg
                  - id: life-on-land
                    number: 15
                    title: Life On Land
                    description: Protect, restore and promote sustainable use of terrestrial ecosystems, sustainably manage forests, combat desertification, and halt and reverse land degradation and biodiversity loss.
                    color: '#56C02B'
                    link: https://sdgs.un.org/goals/goal15
                    icon_url: https://images.s3.us-east-1.amazonaws.com/projects/sdgs/E-WEB-Goal-15.jpg
                image_urls:
                  - https://images.s3.us-east-1.amazonaws.com/projects/trees-uganda-di/1.jpg
                  - https://images.s3.us-east-1.amazonaws.com/projects/trees-uganda-di/2.jpg
                  - https://images.s3.us-east-1.amazonaws.com/projects/trees-uganda-di/3.jpg
                  - https://images.s3.us-east-1.amazonaws.com/projects/trees-uganda-di/4.jpg
                  - https://images.s3.us-east-1.amazonaws.com/projects/trees-uganda-di/5.jpg
                latitude: -12.3733
                longitude: 27.2903
                available: true
        '404':
          description: Project not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/carbon:
    get:
      operationId: calculateWebsiteCarbon
      summary: Calculate website carbon emissions
      description: >
        Analyze any public URL and calculate its CO₂ emissions per page view using V4 of the
        Sustainable Web Design Model. Returns a carbon rating (A+ to F), green hosting status,
        transfer size, and energy statistics. Results are cached for 7 days. Each call counts
        as 2 API calls toward usage. Sandbox keys return a mock response.
      tags:
        - Website Carbon
      parameters:
        - name: url
          in: query
          required: true
          description: >
            Website URL to analyze. Bare domains, subdomains, and full URLs with paths are supported.
            Redirects are followed automatically. Maximum 2048 characters.
          schema:
            type: string
            maxLength: 2048
          example: example.com
        - name: recalculate
          in: query
          required: false
          description: Set to true to bypass the 7-day cache and force a fresh analysis.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Carbon analysis result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CarbonResult'
              example:
                url: example.com
                cleaner_than: 0.91
                rating: A
                green_hosting: false
                statistics:
                  transfer_size: 495573
                  energy: 0.000139
                  co2:
                    grid:
                      grams: 0.068
                    renewable:
                      grams: 0.057
                tested_on: '2026-04-21'
        '400':
          description: Invalid or missing url parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Website not reachable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/ai_energy/calculate:
    post:
      operationId: calculateAiEnergy
      summary: Calculate the energy, water, and carbon of an AI model
      description: >
        Estimate the electricity (Wh), water (mL), and carbon (gCO2e) of running any AI model at
        your usage. Returns p5/median/p95 bands per query, per month, and per year, plus a
        breakdown, human-scale equivalents, resolved assumptions, and a confidence report. Only
        model_id and scale are required; all other fields fall back to documented defaults from
        GET /v1/ai_energy/options. Requires an API key; each call counts as 1 API call.
      tags:
        - AI Energy
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiEnergyRequest'
            example:
              model_id: claude-fable-5
              workload_id: chat
              region_id: us-average
              scale:
                mode: queries
                queries_per_month: 1000000
      responses:
        '200':
          description: AI energy footprint result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiEnergyResult'
        '400':
          description: Invalid request body or unknown id (see GET /v1/ai_energy/options)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/ai_energy/options:
    get:
      operationId: getAiEnergyOptions
      summary: List AI energy calculator options
      description: >
        Returns the full catalog needed to build a calculate request or render a UI — models,
        providers, hardware, regions, workloads, regimes, boundaries, and the current defaults.
        Read-only; requires an API key and counts as 1 API call. Cache the response and refresh
        when data_version changes.
      tags:
        - AI Energy
      responses:
        '200':
          description: Option catalog
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiEnergyOptions'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

# Outbound webhooks (documented with the x-webhooks vendor extension so this stays a
# valid OpenAPI 3.0 document; see https://docs.1clickimpact.com/webhooks).
x-webhooks:
  impactEvent:
    post:
      operationId: impactWebhookEvent
      summary: Impact lifecycle event
      tags: [Webhooks]
      description: >
        Sent to each of your registered endpoints when a subscribed impact event occurs,
        so you can react in real time instead of polling GET /v1/track. Available on the
        Basic and Pro plans; register up to 10 endpoints in the dashboard under
        Account -> Webhooks (https://1clickimpact.com/account/webhooks). Verify the
        X-1CI-Signature header before trusting a request and deduplicate on the event id.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookEvent'
      responses:
        '2XX':
          description: >
            Return any 2xx status to acknowledge receipt. 429, 5xx, and network errors are
            retried with backoff; other 4xx responses are treated as misconfiguration and
            are not retried.

tags:
  - name: Account
    description: Verify credentials and retrieve account details
  - name: Impact Actions
    description: Create environmental impact — trees, ocean, carbon, donations
  - name: Impact Data
    description: Retrieve aggregated and time-series impact totals
  - name: Records
    description: Access full impact history for your org and customers
  - name: Tracking
    description: Real-time lifecycle tracking for specific impact events
  - name: Projects
    description: Browse and retrieve verified environmental impact projects
  - name: Website Carbon
    description: Calculate carbon emissions for any website using the Sustainable Web Design Model V4
  - name: AI Energy
    description: Estimate the electricity, water, and carbon of AI model inference
  - name: Webhooks
    description: Receive real-time, HMAC-signed impact lifecycle events at your own endpoint
