> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intentleads.si/llms.txt
> Use this file to discover all available pages before exploring further.

# Quote or start an export

> Quotes or starts an export of new people from one or more lanes.

**Dry run (free, the default).** Unless the body has `"dry_run": false` (the JSON boolean), this only returns a quote: how many new people each lane has right now, `will_export` (the smallest of `max`, the contacts you have left and what's available) and your contacts before and after. Nothing is bought. If you leave `dry_run` out, the quote also says `dry_run_defaulted: true`.

**Export (uses contacts).** With `"dry_run": false` and an `idempotency_key`, up to `will_export` contacts are reserved against your plan straight away and the export is queued (`202`). It starts within seconds; filling it can take several minutes. Poll `GET /api/v1/exports/{id}` until `status` is `completed`, `partial` or `failed`; the same call returns the leads (add `format=csv` for a file). Only people actually exported count against your plan, and each person counts once per billing period: anyone already exported to your organization this period is left out before anything is bought.

**Idempotency.** Sending an `idempotency_key` you've used before returns that earlier export with `200` and `reused: true`, and never buys twice. The rest of the body isn't compared, so use a new key for each new export.

**Good to know**
- Available counts come from each lane's latest check, less people exported from that lane since. An export fills up to `will_export`, or fewer if fewer people are really there (`partial`).
- Intent is a rolling 14-day window: people who aren't exported within about two weeks of researching drop out.
- Lanes are filled in priority order, whatever order you list them in. Within a lane, higher-strength people are taken first.
- Your organization's exports run one at a time; a second one waits until the first finishes.
- Without an active plan the quote still works and shows `will_export: 0`.
- The returned export's `requested` is the reserved number (the quote's `will_export`), not the `max` you sent.



## OpenAPI

````yaml /api-reference/openapi.json post /api/v1/exports
openapi: 3.1.0
info:
  title: Intent Leads API
  version: '1.0'
  description: >-
    The Intent Leads API finds B2B people actively researching the topics you
    sell into, and exports them with contact details into your own tools.


    **Authentication.** Send an API key as a bearer token: `Authorization:
    Bearer il_live_…`. Keys belong to one organization. Standard keys work with
    everything except billing, team and key management, which need an admin key.


    **What costs contacts.** Only `POST /api/v1/exports` with `"dry_run": false`
    uses contacts from your plan. Quotes, counts, checks, samples and
    re-downloads are free.


    **Errors.** Every error is JSON: `{"error": "code", "message":
    "Plain-English explanation"}`. Codes are stable; messages may change.


    **Conventions.** JSON by default. Dates are `YYYY-MM-DD` and timestamps ISO
    8601, all in UTC. Lane codes (`L1`) are case-insensitive.
servers:
  - url: https://intentleads.si
security:
  - bearerAuth: []
tags:
  - name: Exports
    description: Quote (free) and buy new people from your lanes, then download them.
  - name: Leads
    description: Pull and re-download the leads you've exported, and list deliveries.
  - name: Lanes
    description: >-
      Create, inspect and tune lanes: keywords plus the companies and roles you
      want.
  - name: Keywords
    description: Add and remove a lane's keywords; each one is approved as its own topic.
  - name: Checks
    description: >-
      Free lane checks that size every filter step over 14 days, plus quick
      topic signals.
  - name: Company list
    description: >-
      The target-company list your lanes can narrow to or use instead of
      industries.
  - name: Suppressions
    description: People you exported who later asked to be removed.
  - name: Usage
    description: Contacts used and left this billing period.
  - name: Billing
    description: Plan, invoices and plan changes. Admin keys only.
  - name: Team
    description: Members and invite links. Admin keys only.
  - name: API keys
    description: Create, rename, rotate and revoke API keys. Admin keys only.
  - name: Account
    description: Check which organization a key belongs to and its role.
  - name: Reference
    description: Valid values for lane filters.
  - name: Activity
    description: A feed of changes and events in your organization.
paths:
  /api/v1/exports:
    post:
      tags:
        - Exports
      summary: Quote or start an export
      description: >-
        Quotes or starts an export of new people from one or more lanes.


        **Dry run (free, the default).** Unless the body has `"dry_run": false`
        (the JSON boolean), this only returns a quote: how many new people each
        lane has right now, `will_export` (the smallest of `max`, the contacts
        you have left and what's available) and your contacts before and after.
        Nothing is bought. If you leave `dry_run` out, the quote also says
        `dry_run_defaulted: true`.


        **Export (uses contacts).** With `"dry_run": false` and an
        `idempotency_key`, up to `will_export` contacts are reserved against
        your plan straight away and the export is queued (`202`). It starts
        within seconds; filling it can take several minutes. Poll `GET
        /api/v1/exports/{id}` until `status` is `completed`, `partial` or
        `failed`; the same call returns the leads (add `format=csv` for a file).
        Only people actually exported count against your plan, and each person
        counts once per billing period: anyone already exported to your
        organization this period is left out before anything is bought.


        **Idempotency.** Sending an `idempotency_key` you've used before returns
        that earlier export with `200` and `reused: true`, and never buys twice.
        The rest of the body isn't compared, so use a new key for each new
        export.


        **Good to know**

        - Available counts come from each lane's latest check, less people
        exported from that lane since. An export fills up to `will_export`, or
        fewer if fewer people are really there (`partial`).

        - Intent is a rolling 14-day window: people who aren't exported within
        about two weeks of researching drop out.

        - Lanes are filled in priority order, whatever order you list them in.
        Within a lane, higher-strength people are taken first.

        - Your organization's exports run one at a time; a second one waits
        until the first finishes.

        - Without an active plan the quote still works and shows `will_export:
        0`.

        - The returned export's `requested` is the reserved number (the quote's
        `will_export`), not the `max` you sent.
      operationId: createExport
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExportRequest'
            examples:
              quote:
                summary: Free quote
                value:
                  lanes:
                    - L1
                    - L2
                  max: 250
                  dry_run: true
              export:
                summary: Export (uses contacts)
                value:
                  lanes:
                    - L1
                    - L2
                  max: 250
                  dry_run: false
                  idempotency_key: crm-sync-2026-10-14
              all_high:
                summary: Every lane, high strength only
                value:
                  lanes: all
                  max: 500
                  min_strength: high
                  dry_run: true
      responses:
        '200':
          description: >-
            A free quote (any request without `"dry_run": false`), or an earlier
            export returned again for a repeated `idempotency_key` (`reused:
            true`).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ExportQuote'
                  - $ref: '#/components/schemas/ExportStarted'
              examples:
                quote:
                  summary: Dry run
                  value:
                    dry_run: true
                    lanes:
                      - lane: L1
                        name: Medical device distributors
                        strength: medium
                        available:
                          high: 88
                          medium_plus: 412
                          all: 1265
                          at_lane_strength: 412
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                      - lane: L2
                        name: Plastics molders
                        strength: high
                        available:
                          high: 61
                          medium_plus: 230
                          all: 702
                          at_lane_strength: 61
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                    requested: 250
                    available: 473
                    will_export: 250
                    capped_by: max
                    allowance:
                      plan: growth
                      before: 6100
                      after: 5850
                      period_end: '2026-11-01'
                    exports_enabled: true
                    notes:
                      - >-
                        Available counts come from each lane's latest daily
                        check, less people exported since. An export fills the
                        number shown, or fewer if fewer are really there.
                      - >-
                        Intent is a rolling 14-day window: people who aren't
                        exported within about two weeks of researching drop out.
                quote_defaulted:
                  summary: dry_run left out
                  value:
                    dry_run: true
                    lanes:
                      - lane: L1
                        name: Medical device distributors
                        strength: medium
                        available:
                          high: 88
                          medium_plus: 412
                          all: 1265
                          at_lane_strength: 412
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                      - lane: L2
                        name: Plastics molders
                        strength: high
                        available:
                          high: 61
                          medium_plus: 230
                          all: 702
                          at_lane_strength: 61
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                    requested: 250
                    available: 473
                    will_export: 250
                    capped_by: max
                    allowance:
                      plan: growth
                      before: 6100
                      after: 5850
                      period_end: '2026-11-01'
                    exports_enabled: true
                    notes:
                      - >-
                        Available counts come from each lane's latest daily
                        check, less people exported since. An export fills the
                        number shown, or fewer if fewer are really there.
                      - >-
                        Intent is a rolling 14-day window: people who aren't
                        exported within about two weeks of researching drop out.
                    dry_run_defaulted: true
                    note: >-
                      dry_run defaulted to true: nothing was bought. Send
                      "dry_run": false with an idempotency_key to export.
                no_plan_quote:
                  summary: Quote without a plan
                  value:
                    dry_run: true
                    lanes:
                      - lane: L1
                        name: Medical device distributors
                        strength: medium
                        available:
                          high: 88
                          medium_plus: 412
                          all: 1265
                          at_lane_strength: 412
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                      - lane: L2
                        name: Plastics molders
                        strength: high
                        available:
                          high: 61
                          medium_plus: 230
                          all: 702
                          at_lane_strength: 61
                        data_window:
                          start: '2026-09-30'
                          end: '2026-10-13'
                        checked_at: '2026-10-14T06:12:41.528311+00:00'
                        approximate: false
                    requested: 250
                    available: 473
                    will_export: 0
                    capped_by: allowance
                    allowance:
                      plan: null
                      before: 0
                      after: 0
                      period_end: null
                    exports_enabled: true
                    notes:
                      - 'No active plan: pick a plan to export.'
                      - >-
                        Available counts come from each lane's latest daily
                        check, less people exported since. An export fills the
                        number shown, or fewer if fewer are really there.
                      - >-
                        Intent is a rolling 14-day window: people who aren't
                        exported within about two weeks of researching drop out.
                reused:
                  summary: Repeated idempotency_key
                  value:
                    export:
                      id: 0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
                      status: completed
                      lanes:
                        - L1
                        - L2
                      requested: 250
                      will_export: 250
                      exported: 250
                      min_strength: null
                      billing_period: '2026-10-01'
                      via: api
                      created_at: '2026-10-14T09:30:02.114502+00:00'
                      finished_at: '2026-10-14T09:41:55.903117+00:00'
                      error: null
                    reused: true
                    poll: /api/v1/exports/0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
        '202':
          description: >-
            Export started. Contacts are reserved; poll the export for progress
            and leads.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportStarted'
              example:
                export:
                  id: 0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
                  status: queued
                  lanes:
                    - L1
                    - L2
                  requested: 250
                  will_export: 250
                  exported: 0
                  min_strength: null
                  billing_period: '2026-10-01'
                  via: api
                  created_at: '2026-10-14T09:30:02.114502+00:00'
                  finished_at: null
                  error: null
                reused: false
                poll: /api/v1/exports/0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
        '400':
          description: The request isn't valid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalid_body:
                  value:
                    error: invalid_body
                    message: >-
                      Send JSON like {"lanes": ["L1"], "max": 100, "dry_run":
                      true}.
                lanes_required:
                  value:
                    error: lanes_required
                    message: Pass lanes, e.g. ["L1"], or "all".
                invalid_max:
                  value:
                    error: invalid_max
                    message: max must be a whole number from 1 to 100,000.
                invalid_strength:
                  value:
                    error: invalid_strength
                    message: min_strength must be low, medium or high.
                idempotency_key_required:
                  value:
                    error: idempotency_key_required
                    message: >-
                      Pass an idempotency_key (any unique string up to 200
                      characters) so a retry never buys twice.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: >-
            Only for real exports: no active plan, or no contacts left this
            period.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlanError'
              examples:
                no_plan:
                  value:
                    error: no_plan
                    message: >-
                      Pick a plan on the Usage page before exporting. Counts and
                      samples stay free.
                    upgrade: /dash/usage
                allowance_exhausted:
                  value:
                    error: allowance_exhausted
                    message: >-
                      You've used this period's contacts. Upgrade on the Usage
                      page, or wait for the next period.
                    upgrade: /dash/usage
        '403':
          description: >-
            Only for real exports: exports aren't open for your account yet. The
            quote's `exports_enabled` shows this in advance.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                exports_disabled:
                  value:
                    error: exports_disabled
                    message: >-
                      Exports aren't open for this account yet. Dry runs still
                      work.
        '404':
          description: One of the lanes doesn't exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                lane_not_found:
                  value:
                    error: lane_not_found
                    message: No lane L9.
        '409':
          description: >-
            Only for real exports: the lanes have no new people right now
            (`available` is 0).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                nothing_available:
                  value:
                    error: nothing_available
                    message: No new people are available in these lanes right now.
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    ExportRequest:
      type: object
      properties:
        lanes:
          description: >-
            Lane codes to export from, e.g. `["L1", "L6"]`, a single code
            (`"L1"`), or `"all"` for every lane. Codes are case-insensitive.
          oneOf:
            - type: array
              items:
                type: string
              minItems: 1
              example:
                - L1
                - L2
            - type: string
              example: all
        max:
          type: integer
          minimum: 1
          maximum: 100000
          example: 250
          description: >-
            Most new people to export. The export takes fewer if fewer are
            available or you have fewer contacts left.
        min_strength:
          type: string
          enum:
            - low
            - medium
            - high
          description: >-
            Overrides every chosen lane's own minimum strength for this export.
            Leave it out to use each lane's `min_strength`.
        dry_run:
          type: boolean
          default: true
          description: >-
            Leave out or `true` for a free quote. Only the JSON boolean `false`
            exports (and uses contacts). Anything else, including the string
            `"false"`, is a quote.
        idempotency_key:
          type: string
          minLength: 1
          maxLength: 200
          example: crm-sync-2026-10-14
          description: >-
            Required when `dry_run` is `false`. Any unique string up to 200
            characters. Retrying with the same key returns the first export and
            never buys twice.
        via:
          type: string
          enum:
            - api
            - cli
            - mcp
          description: >-
            Label recorded on the export. Defaults to `api` (`cli` for the
            Intent Leads CLI).
      required:
        - lanes
        - max
    ExportQuote:
      type: object
      properties:
        dry_run:
          type: boolean
          const: true
          description: 'Always true: nothing was bought.'
        lanes:
          type: array
          items:
            $ref: '#/components/schemas/LaneAvailability'
        requested:
          type: integer
          description: The `max` you sent.
        available:
          type:
            - integer
            - 'null'
          description: >-
            Sum of `at_lane_strength` over the lanes, or null if any lane hasn't
            been sized yet.
        will_export:
          type: integer
          description: >-
            What an export would reserve now: the smallest of `max`,
            `allowance.before` and `available`. 0 without an active plan.
        capped_by:
          type: string
          enum:
            - max
            - allowance
            - available
          description: Which limit set `will_export`.
        allowance:
          type: object
          properties:
            plan:
              type:
                - string
                - 'null'
              description: Plan id, or null without a plan.
            before:
              type: integer
              description: Contacts left to export now (same as `left_to_export` in Usage).
            after:
              type: integer
              description: Contacts that would be left after this export.
            period_end:
              type:
                - string
                - 'null'
              format: date
              description: End of the billing period.
          required:
            - plan
            - before
            - after
            - period_end
        exports_enabled:
          type: boolean
          description: >-
            False while exports aren't open for your account; a real export
            would then fail with `exports_disabled`.
        notes:
          type: array
          items:
            type: string
          description: Plain-English caveats about this quote.
        dry_run_defaulted:
          type: boolean
          const: true
          description: Only present (true) when you left `dry_run` out.
        note:
          type: string
          description: >-
            Only present when you left `dry_run` out: explains how to export for
            real.
      required:
        - dry_run
        - lanes
        - requested
        - available
        - will_export
        - capped_by
        - allowance
        - exports_enabled
        - notes
      description: A free quote. Nothing is bought.
      example:
        dry_run: true
        lanes:
          - lane: L1
            name: Medical device distributors
            strength: medium
            available:
              high: 88
              medium_plus: 412
              all: 1265
              at_lane_strength: 412
            data_window:
              start: '2026-09-30'
              end: '2026-10-13'
            checked_at: '2026-10-14T06:12:41.528311+00:00'
            approximate: false
          - lane: L2
            name: Plastics molders
            strength: high
            available:
              high: 61
              medium_plus: 230
              all: 702
              at_lane_strength: 61
            data_window:
              start: '2026-09-30'
              end: '2026-10-13'
            checked_at: '2026-10-14T06:12:41.528311+00:00'
            approximate: false
        requested: 250
        available: 473
        will_export: 250
        capped_by: max
        allowance:
          plan: growth
          before: 6100
          after: 5850
          period_end: '2026-11-01'
        exports_enabled: true
        notes:
          - >-
            Available counts come from each lane's latest daily check, less
            people exported since. An export fills the number shown, or fewer if
            fewer are really there.
          - >-
            Intent is a rolling 14-day window: people who aren't exported within
            about two weeks of researching drop out.
    ExportStarted:
      type: object
      properties:
        export:
          $ref: '#/components/schemas/Export'
        reused:
          type: boolean
          description: >-
            True when this `idempotency_key` was used before: this is that
            earlier export and nothing new was bought.
        poll:
          type: string
          example: /api/v1/exports/0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
          description: Path to poll for progress and leads.
      required:
        - export
        - reused
        - poll
    Error:
      type: object
      properties:
        error:
          type: string
          example: lane_not_found
          description: Stable machine-readable code, e.g. `lane_not_found`.
        message:
          type: string
          example: No lane L9.
          description: Plain-English explanation you can show to a person.
      required:
        - error
        - message
      description: Every error has this shape.
    PlanError:
      type: object
      properties:
        error:
          type: string
          enum:
            - no_plan
            - allowance_exhausted
          description: '`no_plan` or `allowance_exhausted`.'
        message:
          type: string
        upgrade:
          type: string
          example: /dash/usage
          description: Dashboard path where an owner can pick or upgrade a plan.
      required:
        - error
        - message
        - upgrade
      description: >-
        Returned by `POST /api/v1/exports` when there's no active plan or no
        contacts left.
    LaneAvailability:
      type: object
      properties:
        lane:
          type: string
          description: Lane code.
        name:
          type: string
          description: Lane name.
        strength:
          type: string
          enum:
            - low
            - medium
            - high
          description: Minimum strength this export would use for the lane.
        available:
          type: object
          properties:
            high:
              type:
                - integer
                - 'null'
              description: High strength only.
            medium_plus:
              type:
                - integer
                - 'null'
              description: Medium and high.
            all:
              type:
                - integer
                - 'null'
              description: Any strength.
            at_lane_strength:
              type:
                - integer
                - 'null'
              description: >-
                At the strength used for this export (the override, or the
                lane's own `min_strength`).
          required:
            - high
            - medium_plus
            - all
            - at_lane_strength
          description: >-
            New people available now: the latest check's final count, less
            people exported from this lane since that check. Null when the lane
            hasn't been sized.
        data_window:
          anyOf:
            - $ref: '#/components/schemas/DataWindow'
            - type: 'null'
          description: >-
            Window of the check behind the counts, or null if the lane hasn't
            been checked.
        checked_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When that check finished.
        approximate:
          type: boolean
          description: >-
            True when the count is summed over parts of a large company list, so
            someone tied to two listed companies can be counted twice. An export
            never buys anyone twice.
      required:
        - lane
        - name
        - strength
        - available
        - data_window
        - checked_at
        - approximate
    Export:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Export id.
        status:
          type: string
          enum:
            - queued
            - running
            - completed
            - partial
            - failed
          description: >-
            `queued` and `running` are in progress. `completed`: everything
            reserved was exported. `partial`: some people were exported, fewer
            than `will_export`. `failed`: nobody was exported. Contacts that
            weren't used go back to your allowance.
        lanes:
          type: array
          items:
            type: string
          description: Lane codes, in the order they're filled.
        requested:
          type: integer
          description: >-
            The number reserved when the export started (the quote's
            `will_export`), not the `max` you sent.
        will_export:
          type: integer
          description: Contacts reserved for this export.
        exported:
          type: integer
          description: People exported so far. Only these count against your plan.
        min_strength:
          type:
            - string
            - 'null'
          enum:
            - low
            - medium
            - high
            - null
          description: >-
            Strength override sent with the export, or null for each lane's own
            `min_strength`.
        billing_period:
          type: string
          format: date
          description: Start date of the billing period the export counts against.
        via:
          type: string
          enum:
            - dashboard
            - api
            - cli
            - mcp
          description: Where the export was started.
        created_at:
          type: string
          format: date-time
        finished_at:
          type:
            - string
            - 'null'
          format: date-time
        error:
          type:
            - string
            - 'null'
          description: >-
            Why a `partial` or `failed` export stopped short, e.g. `No new
            people were available in these lanes.` or `Fewer new people were
            available than estimated.` Always null for other statuses.
      required:
        - id
        - status
        - lanes
        - requested
        - will_export
        - exported
        - min_strength
        - billing_period
        - via
        - created_at
        - finished_at
        - error
      example:
        id: 0199e3a1-2f4b-7c10-8e2d-1a2b3c4d5e6f
        status: completed
        lanes:
          - L1
          - L2
        requested: 250
        will_export: 250
        exported: 250
        min_strength: null
        billing_period: '2026-10-01'
        via: api
        created_at: '2026-10-14T09:30:02.114502+00:00'
        finished_at: '2026-10-14T09:41:55.903117+00:00'
        error: null
    DataWindow:
      type: object
      properties:
        start:
          type: string
          format: date
          description: First data day (inclusive), UTC.
        end:
          type: string
          format: date
          description: Last data day (inclusive), UTC.
      required:
        - start
        - end
      description: >-
        The 14-day data window a count covers. It can be shorter when fewer
        consecutive data days are ready.
      example:
        start: '2026-09-30'
        end: '2026-10-13'
  responses:
    Unauthorized:
      description: Missing, malformed, unknown or revoked API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            unauthorized:
              value:
                error: unauthorized
                message: 'Send a valid API key as: Authorization: Bearer il_live_…'
    InternalError:
      description: >-
        Unexpected server error. Safe to retry reads; retry an export only with
        the same `idempotency_key`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            internal_error:
              value:
                error: internal_error
                message: Something went wrong. Try again.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: il_live_…
      description: >-
        An Intent Leads API key, e.g. `il_live_` followed by 32 letters and
        digits. Create one on the API and CLI page of the dashboard.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.