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

# Execute an import

> Approve the final column mappings and start the import. The import runs asynchronously in chunks — this endpoint returns `202` with an `import_run_id`; poll `GET /v1/contacts/imports/{importRunId}` until `status` is `completed` or `failed`.

Every mapping's `header` must be a column from the session's CSV. Map a column to `null` (`target_field: null`, `target_kind: null`) to skip it. At least one column must map to the `email` or `phone` standard field — contacts are matched (deduplicated) by normalized email or phone.

Each session can be executed once: re-executing a session whose latest run is `queued`, `running`, or `completed` returns `400`. A session whose only runs `failed` can be executed again.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/contacts/imports/{sessionId}/execute
openapi: 3.1.0
info:
  title: Tented API
  version: 1.0.0
  description: >-
    The Tented public API: generate, publish, and manage AI-built web pages
    (tents), and run the email platform — contacts, reusable emails, one-time
    blasts, and triggered flows.


    ## Authentication

    Authenticate every request with a workspace API key: `Authorization: Bearer
    <api-key>`. Keys are created in **Workspace Settings → API Keys** and are
    scoped to a single workspace.


    ## Asynchronous work

    Tent generation, bulk creation, and email AI generation return `202
    Accepted` immediately. Poll the corresponding status endpoint (`GET
    /v1/tents/{tentId}`, `GET /v1/bulk-jobs/{bulkJobId}`, `GET
    /v1/emails/{emailId}/generations/{generationId}`) — no more than every 10
    seconds.


    ## Pagination

    Email listings use cursor pagination (`cursor`/`next_cursor`). Blast, flow,
    and member listings use page pagination (`page`/`limit` with a `pagination`
    object in the response).


    ## Conventions

    Request and response fields are snake_case, with two exceptions: analytics
    query parameters (`tentIdOrAlias`, `daysBack`) and segment rule trees
    (camelCase keys such as `listId` and `timeWindow`).
  contact:
    name: Tented Support
    email: support@tented.ai
servers:
  - url: https://api.tented.ai
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Tents
    description: >-
      Create, edit, publish, and manage AI-generated pages, including asset
      uploads and bulk creation.
  - name: Analytics
    description: Traffic analytics for single tents and the whole workspace.
  - name: Contacts
    description: >-
      Batch create, update, and delete contacts. Up to 25 items per request with
      per-item results.
  - name: Emails
    description: >-
      Reusable email content: AI generation, direct HTML edits, plain-text
      control, and approval.
  - name: Email Blasts
    description: >-
      One-time sends to an audience: compose, schedule, track engagement, export
      recipients.
  - name: Triggered Flows
    description: >-
      Multi-step automations that enroll contacts on triggers and move them
      through a step graph.
  - name: Contact Imports
  - name: Contact Fields
  - name: Contact Lists
  - name: Email Templates
  - name: Tent Templates
    description: >-
      Reusable, AI-editable tent layouts. Create from HTML or an existing tent,
      iterate with AI, approve, and clone. Approved tent templates seed new
      tents.
paths:
  /v1/contacts/imports/{sessionId}/execute:
    post:
      tags:
        - Contact Imports
      summary: Execute an import
      description: >-
        Approve the final column mappings and start the import. The import runs
        asynchronously in chunks — this endpoint returns `202` with an
        `import_run_id`; poll `GET /v1/contacts/imports/{importRunId}` until
        `status` is `completed` or `failed`.


        Every mapping's `header` must be a column from the session's CSV. Map a
        column to `null` (`target_field: null`, `target_kind: null`) to skip it.
        At least one column must map to the `email` or `phone` standard field —
        contacts are matched (deduplicated) by normalized email or phone.


        Each session can be executed once: re-executing a session whose latest
        run is `queued`, `running`, or `completed` returns `400`. A session
        whose only runs `failed` can be executed again.
      operationId: execute-contact-import
      parameters:
        - name: sessionId
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Import session ID from `POST /v1/contacts/imports`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    $ref: '#/components/schemas/ContactImportExecuteMapping'
                  minItems: 1
                  description: >-
                    Approved column mappings. Start from the preview's
                    `proposed_mappings` and adjust as needed.
                duplicate_strategy:
                  type: string
                  enum:
                    - update
                    - skip
                  default: update
                  description: >-
                    What to do when a row matches an existing contact (by
                    normalized email or phone): `update` merges the mapped
                    values into the existing contact; `skip` leaves the existing
                    contact untouched and counts the row as skipped.
                overwrite_blank_only:
                  type: boolean
                  default: false
                  description: >-
                    When `true`, imported values only fill fields that are
                    currently empty on the matched contact (the default
                    `overwrite_behavior` for every mapping becomes
                    `skip_if_filled`). Per-mapping `overwrite_behavior`
                    overrides this default.
                list_ids:
                  type: array
                  items:
                    type: string
                    format: uuid
                  maxItems: 500
                  description: >-
                    Static contact list IDs every imported contact is added to
                    (max 500).
                created_field_definition_ids:
                  type: array
                  items:
                    type: string
                    format: uuid
                  description: >-
                    IDs of custom fields you bulk-created for this import (from
                    the preview's `field_creation_candidates`). Each ID must
                    reference a field created via `POST /v1/contact-fields`
                    against this same import session — unrelated fields are
                    rejected with `400`.
              required:
                - mappings
      responses:
        '202':
          description: >-
            Import accepted and queued. Poll `GET
            /v1/contacts/imports/{importRunId}` for progress.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactImportRunAccepted'
        '400':
          description: >-
            Bad request — invalid mappings, no `email`/`phone` identity column
            mapped, the session was already executed, a run is already in
            progress for the session, or `created_field_definition_ids`
            references fields not created against this session. Validation
            failures include `details.issues` with per-field messages.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing, malformed, revoked, or expired API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            Not found — the import session does not exist in the workspace tied
            to your API key, or has expired (sessions are retained for 7 days).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ContactImportExecuteMapping:
      type: object
      properties:
        header:
          type: string
          minLength: 1
          description: CSV column header. Must be one of the session's detected headers.
        target_field:
          type:
            - string
            - 'null'
          description: >-
            Target field `api_name` (standard or custom) or `listIds` for a
            membership column. Set to `null` to skip this column.
        target_kind:
          type:
            - string
            - 'null'
          enum:
            - standard
            - custom
            - membership
            - null
          description: >-
            Kind of target: `standard`, `custom`, or `membership`. Set to `null`
            to skip this column.
        overwrite_behavior:
          type: string
          enum:
            - overwrite
            - skip_if_filled
          description: >-
            When updating an existing contact: `overwrite` replaces the current
            value; `skip_if_filled` only writes if the field is currently empty.
            Defaults to `overwrite`, or to `skip_if_filled` when
            `overwrite_blank_only` is `true`.
      required:
        - header
        - target_field
        - target_kind
      description: An approved column-to-field mapping.
    ContactImportRunAccepted:
      type: object
      properties:
        import_run_id:
          type: string
          format: uuid
          description: >-
            ID of the queued import run. Poll `GET
            /v1/contacts/imports/{importRunId}` with it.
        import_session_id:
          type: string
          format: uuid
          description: The import session the run was created from.
        status:
          type: string
          enum:
            - queued
          description: Initial run status — always `queued`.
        duplicate_strategy:
          type: string
          enum:
            - update
            - skip
          description: The duplicate strategy the run will use.
        list_ids:
          type: array
          items:
            type: string
            format: uuid
          description: Static list IDs every imported contact will be added to.
        total_rows:
          type:
            - integer
            - 'null'
          description: >-
            Total data rows to process, or `null` if not yet counted (counted
            during preprocessing for upload-mode imports).
        correlation_id:
          type: string
          description: >-
            Correlation ID of the queued background job (useful when contacting
            support).
      required:
        - import_run_id
        - import_session_id
        - status
        - duplicate_strategy
        - list_ids
        - total_rows
        - correlation_id
      description: Acknowledgement that an import run was queued.
    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message.
        error_code:
          type: string
          description: >-
            Stable machine-readable error code (present on email, blast, flow,
            and related endpoints, e.g. `campaign_not_ready`,
            `generation_in_progress`).
        message:
          type: string
          description: Additional human-readable context (present on some tent endpoints).
        code:
          type: string
          description: >-
            Machine-readable code used by tent creation errors (e.g.
            `INVALID_PROMPT_INTENT`).
        details:
          type: object
          additionalProperties: true
          description: >-
            Additional error context. Validation errors include `issues`: an
            array of `{ path, message }` objects.
        limit:
          type: integer
          description: Plan limit that was hit (present on `429` publish-limit errors).
        current:
          type: integer
          description: >-
            Current usage against the limit (present on `429` publish-limit
            errors).
      required:
        - error
      description: >-
        Error response. All errors include `error`; the other fields vary by
        endpoint group.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Workspace API key, e.g. `Authorization: Bearer tented_...`. Create keys
        in Workspace Settings → API Keys.

````