openapi: 3.1.0

info:
  title: CARTO API
  version: "3.0"
  description: |
    The CARTO API lets you work with data in your data warehouse through an existing
    connection in your CARTO organization.

    ## Authorization

    All requests need a bearer token in the `Authorization` header:

    ```
    Authorization: Bearer <YOUR_TOKEN>
    ```

    There are two kinds of token:

    - **API Access Token** — grants access to specific sources through a specific
      connection. Use it in public applications. Works with the Maps, SQL, Imports
      and LDS APIs. [Create one in the Workspace](https://docs.carto.com/carto-user-manual/developers/managing-credentials/api-access-tokens).
    - **OAuth Access Token** — represents a user. Works with every API, and is the
      *only* option for the Tokens, Named Sources, Resources and Activity Data APIs.

    To get an OAuth token, create an OAuth Client in the Developers section of your
    Workspace and exchange its credentials:

    ```bash
    curl --request POST \
      --url 'https://auth.carto.com/oauth/token' \
      --header 'content-type: application/x-www-form-urlencoded' \
      --data 'grant_type=client_credentials' \
      --data 'client_id=<YOUR_CLIENT_ID>' \
      --data 'client_secret=<YOUR_CLIENT_SECRET>' \
      --data 'audience=carto-cloud-native-api'
    ```

    ## API Base URL

    Every CARTO deployment has its own base URL. Pick the server matching your
    organization's region, or use your own domain for Self-Hosted. You can copy your
    API Base URL from the Developers section of the Workspace.

    ## Rate limits

    CARTO Cloud is protected by a web application firewall that temporarily blocks
    any IP going over these per-IP limits:

    | API | Requests per minute |
    | --- | --- |
    | Maps | 3500 |
    | LDS | 3000 |
    | SQL | 2500 |
    | Imports | 500 |
    | Tokens & Accounts | 300 |
    | Connections, Workflows & Organization Maps | 300 |
    | AI (LLM completions) | 300 |
    | All other endpoints | 1000 |

    Requests answered by the CDN cache don't count. Going over the limit returns `429`.
    The "All other endpoints" row covers any API not listed above, including the Activity Data API.
  contact:
    name: CARTO Support
    url: https://carto.com/contact
  license:
    name: Proprietary
    url: https://carto.com/legal

servers:
  - url: https://gcp-us-east1.api.carto.com
    description: CARTO Cloud - United States East
  - url: https://gcp-europe-west1.api.carto.com
    description: CARTO Cloud - Europe West
  - url: https://gcp-asia-northeast1.api.carto.com
    description: CARTO Cloud - Asia Northeast
  - url: https://gcp-australia-southeast1.api.carto.com
    description: CARTO Cloud - Australia Southeast
  - url: https://{tenant}/api
    description: CARTO Self-Hosted
    variables:
      tenant:
        default: your-carto-tenant-domain.com
        description: The domain of your Self-Hosted deployment.

security:
  - accessToken: []

tags:
  - name: Maps
    x-page-title: Maps API
    x-page-icon: map
    description: |
      Create map layers from queries, tables and tilesets in your data warehouse.

      The Maps API is designed to be consumed by
      [@deck.gl/carto](https://deck.gl/docs/api-reference/carto/overview). If you are
      building a deck.gl application you normally don't call it directly.

      **Timeouts.** Requests time out after 1 minute.

      **Caching.** Responses are cached in CARTO's CDN. Use the `Cache-Control`
      request header to lower the maximum age — `Cache-Control: max-age=300` returns
      results at most 5 minutes old. The minimum accepted `max-age` is 10 seconds.
  - name: SQL
    x-page-title: SQL API
    x-page-icon: database
    description: |
      Run SQL queries in your data warehouse through an existing connection,
      synchronously or as asynchronous jobs.
  - name: Tokens
    x-page-title: Tokens API
    x-page-icon: key
    description: |
      Create and manage API Access Tokens that grant access to specific sources
      through a specific connection.

      Requires an **OAuth Access Token**.
  - name: Imports
    x-page-title: Imports API
    x-page-icon: file-import
    description: |
      Import geospatial files into your data warehouse from a URL.
  - name: LDS
    x-page-title: Location Data Services API
    x-page-icon: location-dot
    description: |
      Geocoding, reverse geocoding, isolines and routing.
  - name: Named Sources
    x-page-title: Named Sources API
    x-page-icon: bookmark
    description: |
      Manage named sources — server-side aliases for SQL queries that let you keep
      query text out of client applications.

      Requires an **OAuth Access Token**.
  - name: Resources
    x-page-title: Resources API
    x-page-icon: folder
    description: |
      List and manage the maps, workflows and connections in your organization.

      Requires an **OAuth Access Token**.
  - name: Exports
    x-page-title: Exports API
    x-page-icon: file-export
    description: |
      Export a table or a query from your data warehouse to a file.
  - name: Activity Data
    x-page-title: Activity Data API
    x-page-icon: chart-line
    description: |
      Export your organization's activity and API usage data.

      Requires an **OAuth Access Token**.

paths:
  /v3/maps/{connectionName}/query:
    get:
      tags: [Maps]
      summary: Get a map layer from a query
      operationId: mapsQuery
      description: |
        Returns metadata and URLs to fetch a map layer built from a SQL query.

        Omit `format` to get the full response with a URL per available format.
        Pass `format` to get that single format directly.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - name: q
          in: query
          required: true
          description: The SQL query, or the name of a named source.
          schema:
            type: string
          example: SELECT * FROM carto-demo-data.demo_tables.airports
        - $ref: '#/components/parameters/QueryParameters'
        - $ref: '#/components/parameters/SpatialDataColumn'
        - $ref: '#/components/parameters/SpatialDataType'
        - $ref: '#/components/parameters/GeoColumn'
        - $ref: '#/components/parameters/Columns'
        - name: format
          in: query
          description: |
            Return a single format instead of the full response. Omit to get URLs
            for every available format.
          schema:
            type: string
            enum: [ndjson, geojson, json, binary, tilejson]
        - $ref: '#/components/parameters/TileResolution'
        - $ref: '#/components/parameters/AggregationExp'
        - $ref: '#/components/parameters/AggregationResLevel'
        - $ref: '#/components/parameters/ApiVersion'
      responses:
        '200':
          description: Map layer metadata and download URLs.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MapResponse'
              example:
                ndjson:
                  url:
                    - https://gcp-us-east1.api.carto.com/v3/maps/carto_dw/query?format=ndjson&q=SELECT%20*%20FROM%20carto-demo-data.demo_tables.airports&v=3.0
                geojson:
                  url:
                    - https://gcp-us-east1.api.carto.com/v3/maps/carto_dw/query?format=geojson&q=SELECT%20*%20FROM%20carto-demo-data.demo_tables.airports&v=3.0
                tilejson:
                  url:
                    - https://gcp-us-east1.api.carto.com/v3/maps/carto_dw/query?format=tilejson&q=SELECT%20*%20FROM%20carto-demo-data.demo_tables.airports&v=3.0
                schema:
                  - name: geom
                    type: geometry
                  - name: name
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: |
            The query can't be served for this connection — for example a Databricks
            connection with `spatialDataType=geo`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/maps/{connectionName}/table:
    get:
      tags: [Maps]
      summary: Get a map layer from a table
      operationId: mapsTable
      description: |
        Returns metadata and URLs to fetch a map layer built from a table.

        A `tilejson` URL is always included. Other formats are included depending on
        the size of the table — large tables only offer tiles.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - name: name
          in: query
          required: true
          description: Fully qualified table name.
          schema:
            type: string
          example: carto-demo-data.demo_tables.airports
        - $ref: '#/components/parameters/SpatialDataColumn'
        - $ref: '#/components/parameters/SpatialDataType'
        - $ref: '#/components/parameters/GeoColumn'
        - $ref: '#/components/parameters/Columns'
        - name: format
          in: query
          description: Return a single format instead of the full response.
          schema:
            type: string
            enum: [ndjson, geojson, json, binary, tilejson]
        - $ref: '#/components/parameters/TileResolution'
        - $ref: '#/components/parameters/ApiVersion'
      responses:
        '200':
          description: Map layer metadata and download URLs.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MapResponse'
              example:
                size: 70307
                nrows: 1000
                ndjson:
                  url:
                    - https://gcp-us-east1.api.carto.com/v3/maps/carto_dw/table?format=ndjson&name=carto-demo-data.demo_tables.airports&v=3.0
                tilejson:
                  url:
                    - https://gcp-us-east1.api.carto.com/v3/maps/carto_dw/table?format=tilejson&name=carto-demo-data.demo_tables.airports&v=3.0
                schema:
                  - name: geom
                    type: geometry
                  - name: name
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '406':
          description: |
            No column matches the expected spatial data type. The response body
            includes the table `schema` so you can pick the right column.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: We couldn't find a column that matches the expected spatial data type
                status: 406
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/maps/{connectionName}/tileset:
    get:
      tags: [Maps]
      summary: Get a TileJSON from a tileset
      operationId: mapsTileset
      description: |
        Returns the TileJSON for a tileset in your data warehouse. Learn more about
        [tileset generation](https://docs.carto.com/data-and-analysis/analytics-toolbox-for-bigquery/main-concepts/tilesets).
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - name: name
          in: query
          required: true
          description: Fully qualified tileset name.
          schema:
            type: string
          example: carto-demo-data.demo_tilesets.nasadem_glo_quadgrid15
        - name: format
          in: query
          description: |
            The only supported value is `tilejson`. Omit it to get the full response
            with tileset metadata.
          schema:
            type: string
            enum: [tilejson]
        - $ref: '#/components/parameters/ApiVersion'
      responses:
        '200':
          description: Tileset metadata, or the TileJSON when `format=tilejson`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MapResponse'
        '204':
          description: The tileset returned no result.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/sql/{connectionName}/query:
    get:
      tags: [SQL]
      summary: Run a query
      operationId: sqlQuery
      description: |
        Runs a SQL query and returns the result.

        Times out after 1 minute. For longer queries, create a job instead.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - name: q
          in: query
          required: true
          description: The SQL query, or the name of a named source.
          schema:
            type: string
          example: SELECT * FROM carto-demo-data.demo_tables.airports
        - $ref: '#/components/parameters/QueryParameters'
        - $ref: '#/components/parameters/ApiVersion'
      responses:
        '200':
          $ref: '#/components/responses/SqlResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '408':
          description: The query took longer than the 1 minute timeout.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    post:
      tags: [SQL]
      summary: Run a query (POST)
      operationId: sqlQueryPost
      description: |
        Same as the `GET` variant, for queries too long to fit in a URL.

        This endpoint is **not cached** in CARTO's CDN, so every request reaches the
        data warehouse. Keep that in mind to avoid unnecessary compute cost.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                q:
                  type: string
                  description: The SQL query, or the name of a named source.
                queryParameters:
                  $ref: '#/components/schemas/QueryParametersValue'
              required: [q]
            example:
              q: SELECT * FROM carto-demo-data.demo_tables.airports
              queryParameters: {}
      responses:
        '200':
          $ref: '#/components/responses/SqlResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '408':
          description: The query took longer than the 1 minute timeout.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/sql/{connectionName}/job:
    post:
      tags: [SQL]
      summary: Create a job
      operationId: sqlCreateJob
      description: |
        Runs a query asynchronously. Use this for queries that would exceed the
        1 minute timeout of the synchronous endpoints.

        Available for BigQuery, Snowflake, Redshift, PostgreSQL and CARTO Data
        Warehouse connections.

        Poll `GET /v3/sql/{connectionName}/job/{jobId}` with the
        returned `externalId` to follow the execution.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                query:
                  type: string
                  description: |
                    The SQL query, or the name of a named source. Note this field is
                    `query`, not `q`.
                queryParameters:
                  $ref: '#/components/schemas/QueryParametersValue'
                metadata:
                  type: object
                  description: Arbitrary metadata stored with the job.
                  additionalProperties: true
              required: [query]
            example:
              query: CREATE TABLE your-project.your_dataset.airports_copy AS (SELECT * FROM carto-demo-data.demo_tables.airports)
              queryParameters: {}
              metadata:
                source: nightly-etl
      responses:
        '200':
          description: The job was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobCreated'
              example:
                externalId: job_h8UWzpdzX0s2XAAXQd3rdWCdPUT9
                accountId: ac_jfakef5m
                userId: auth0|61164b7xxx77c006a259f53
                connectionId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                connectionName: carto_dw
                providerId: bigquery
                metadata:
                  source: nightly-etl
                createdAt: '2026-07-30T16:10:35.732Z'
                query: CREATE TABLE your-project.your_dataset.airports_copy AS (SELECT * FROM carto-demo-data.demo_tables.airports)
                jobMetadata:
                  location: US
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/sql/{connectionName}/job/{jobId}:
    get:
      tags: [SQL]
      summary: Get a job
      operationId: sqlGetJob
      description: Returns the current state of an asynchronous job.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: The job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
              example:
                jobId: job_h8UWzpdzX0s2XAAXQd3rdWCdPUT9
                connectionName: carto_dw
                providerId: bigquery
                query: SELECT * FROM carto-demo-data.demo_tables.airports
                status: success
                error: null
                createdAt: '2026-07-30T16:10:35.732Z'
                jobMetadata:
                  location: US
                metadata: {}
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    delete:
      tags: [SQL]
      summary: Cancel a job
      operationId: sqlCancelJob
      description: Cancels a running job. Returns no content on success.
      parameters:
        - $ref: '#/components/parameters/ConnectionName'
        - $ref: '#/components/parameters/JobId'
      responses:
        '204':
          description: The job was cancelled.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/sql/jobs:
    get:
      tags: [SQL]
      summary: List jobs
      operationId: sqlListJobs
      description: |
        Lists the asynchronous jobs in your account.

        Only `userId`, `createdSince` and `client` are accepted — any other query
        parameter returns `400`.
      parameters:
        - name: user_id
          in: query
          description: |
            Filter by user. Ignored when authenticating with an API Access Token,
            which is always scoped to its own user.
          schema:
            type: string
        - name: created_since
          in: query
          description: Only return jobs created after this date.
          schema:
            type: string
            format: date-time
          example: '2026-07-01T00:00:00.000Z'
      responses:
        '200':
          description: The jobs.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/JobListItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/imports:
    post:
      tags: [Imports]
      summary: Create an import job
      operationId: createImport
      description: |
        Imports a geospatial file from a URL into a table in your data warehouse.

        The job runs asynchronously — poll
        `GET /v3/imports/{jobId}` with the returned
        `jobId`.

        By default CARTO guesses the schema of the file. To set it yourself, call
        `POST /v3/imports/preview` first, then pass
        `autoguessing: false` together with the `schema` you want.

        Each account can run 5 import jobs concurrently.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ImportRequest'
            example:
              connection: carto_dw
              url: https://libs.cartocdn.com/data/airports.geojson
              destination: carto-dw-project.my_dataset.airports
              overwrite: false
      responses:
        '201':
          description: The import job was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobId:
                    type: string
                    format: uuid
                  status:
                    $ref: '#/components/schemas/ImportJobStatus'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                status: pending
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The connection doesn't exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: |
            You already have 5 import jobs running. Wait for one to finish.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Rate limit error
                status: 429
    get:
      tags: [Imports]
      summary: List import jobs
      operationId: listImports
      description: |
        Lists import jobs. By default only `pending` and `running` jobs are
        returned — pass `status` to widen the search.
      parameters:
        - name: status
          in: query
          description: |
            Comma-separated list of statuses to return. Defaults to
            `pending,running`.
          schema:
            type: string
          example: success,failure
        - name: created_since
          in: query
          description: Only return jobs created after this date.
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: The import jobs.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ImportJob'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/imports/preview:
    post:
      tags: [Imports]
      summary: Preview an import
      operationId: previewImport
      description: |
        Inspects a file and returns the schema CARTO would use to import it,
        without importing anything.

        Use the returned `columns` as a starting point for the `schema` of a
        manual import.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                connection:
                  type: string
                  description: Name of the connection to import through.
                url:
                  type: string
                  format: uri
                  description: Public URL of the file to inspect.
              required: [connection, url]
            example:
              connection: carto_dw
              url: https://libs.cartocdn.com/data/airports.geojson
      responses:
        '201':
          description: The detected schema.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportPreview'
              example:
                columns:
                  - name: geom
                    type: GEOGRAPHY
                    nullable: true
                  - name: name
                    type: STRING
                    nullable: true
                options:
                  - name: STRING
                  - name: INT64
                  - name: FLOAT64
                  - name: GEOGRAPHY
                source:
                  driver: GeoJSON
                  ogrSource: airports.geojson
                  schema:
                    - name: name
                      type: STRING
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The connection doesn't exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/imports/{jobId}:
    get:
      tags: [Imports]
      summary: Get an import job
      operationId: getImport
      description: |
        Returns the current state of an import job. Poll this until `status` is
        `success`, `failure` or `cancelled`.
      parameters:
        - name: jobId
          in: path
          required: true
          description: The job identifier returned when the job was created.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: The import job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportJob'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                createdAt: '2026-07-30T16:10:35.732Z'
                connection: carto_dw
                resource: https://libs.cartocdn.com/data/airports.geojson
                destination: carto-dw-project.my_dataset.airports
                status: success
                error: ''
                metadata: {}
        '401':
          description: The job belongs to another user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/imports/{jobId}/cancel:
    post:
      tags: [Imports]
      summary: Cancel an import job
      operationId: cancelImport
      description: |
        Cancels an import job that is still `pending` or `running`. Cancelling a
        job that already finished returns `400`.
      parameters:
        - name: jobId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: The cancelled job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportJob'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                createdAt: '2026-07-30T16:10:35.732Z'
                connection: carto_dw
                resource: https://libs.cartocdn.com/data/airports.geojson
                destination: carto-dw-project.my_dataset.airports
                status: cancelled
                error: ''
        '400':
          description: The job already finished and can't be cancelled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: The job has finished and it can not be cancelled
                status: 400
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: The job belongs to another user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/geocoding/geocode:
    get:
      tags: [LDS]
      summary: Geocode an address
      operationId: geocode
      description: |
        Returns coordinates for a street address.

        The geocoding provider is configured per organization, so the fields of each
        result depend on which provider your organization uses.
      parameters:
        - name: address
          in: query
          required: true
          description: The address to geocode.
          schema:
            type: string
          example: Plaza Mayor, Madrid
        - name: country
          in: query
          description: |
            Restrict results to a country. Accepts ISO alpha-2, alpha-3, numeric
            codes or the English country name.
          schema:
            type: string
          example: ES
        - name: limit
          in: query
          description: Maximum number of results.
          schema:
            type: integer
            default: 1
        - name: options
          in: query
          description: |
            Provider options as a JSON string, for example `{"language":"es-ES"}`.
            Supported keys depend on the provider.
          schema:
            type: string
      responses:
        '200':
          description: The geocoding results.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    error:
                      type: [string, 'null']
                    value:
                      type: array
                      items:
                        $ref: '#/components/schemas/GeocodingResult'
              example:
                - error: null
                  value:
                    - formattedAddress: Plaza Mayor, 28012 Madrid, España
                      latitude: 40.41556
                      longitude: -3.70739
                      country: España
                      countryCode: ESP
                      city: Madrid
                      zipcode: '28012'
                      provider: here
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/geocoding/reverse:
    get:
      tags: [LDS]
      summary: Reverse geocode coordinates
      operationId: reverseGeocode
      description: |
        Returns the street address closest to a pair of coordinates.

        Unlike `GET /v3/lds/geocoding/geocode`, this endpoint
        returns the results directly, without the `{ error, value }` wrapper.
      parameters:
        - name: lat
          in: query
          required: true
          description: Latitude.
          schema:
            type: number
          example: 40.40168788033523
        - name: lon
          in: query
          required: true
          description: Longitude.
          schema:
            type: number
          example: -3.6925478219155212
        - name: lang
          in: query
          description: |
            Language for the result, passed through to the provider — for example
            `es-ES`. Accepted values depend on the provider.
          schema:
            type: string
        - name: options
          in: query
          description: Provider options as a JSON string.
          schema:
            type: string
      responses:
        '200':
          description: The addresses found.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/GeocodingResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/geocoding/batch:
    post:
      tags: [LDS]
      summary: Geocode a list of addresses
      operationId: batchGeocode
      description: |
        Geocodes up to 10,000 addresses in one request.

        Results come back in the same order as the input. Individual addresses can
        fail without failing the request — check the `error` field of each entry.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                addresses:
                  type: array
                  maxItems: 10000
                  items:
                    type: string
                  description: The addresses to geocode.
                country:
                  type: string
                  description: Restrict results to a country.
                limit:
                  type: integer
                  default: 1
                  description: |
                    Maximum results per address. Has no effect when the provider is
                    Google Maps.
              required: [addresses]
            example:
              addresses:
                - Lucero, Madrid
                - Guadalajara
              country: ES
              limit: 1
      responses:
        '200':
          description: |
            One entry per input address, in the same order. An entry with a non-null
            `error` means that address failed.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    error:
                      type: [string, 'null']
                    value:
                      type: array
                      items:
                        $ref: '#/components/schemas/GeocodingResult'
                    status:
                      type: integer
                      description: Present only when the address failed.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/isolines:
    get:
      tags: [LDS]
      summary: Get an isoline
      operationId: isolines
      description: |
        Returns the area reachable from a point within a time or distance budget,
        as GeoJSON.

        Isolines are not available when your organization's provider is Google.
      parameters:
        - name: origin
          in: query
          required: true
          description: Origin point as `longitude,latitude`.
          schema:
            type: string
          example: -3.70739,40.41556
        - name: mode
          in: query
          required: true
          description: |
            Mode of transport — `car`, `walk` or `bike`. CARTO maps these to the
            equivalent mode for your provider. Other values are passed through.
          schema:
            type: string
          example: car
        - name: range
          in: query
          required: true
          description: |
            Budget, in seconds when `range_type=time` and in meters when
            `range_type=distance`. HERE and Mapbox accept several comma-separated
            values; TomTom and TravelTime accept only one.
          schema:
            type: string
          example: '300'
        - name: range_type
          in: query
          required: true
          schema:
            type: string
            enum: [time, distance]
        - name: options
          in: query
          description: Provider options as a JSON string.
          schema:
            type: string
      responses:
        '200':
          description: The isoline, as a GeoJSON FeatureCollection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoJsonFeatureCollection'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/isolines/h3:
    get:
      tags: [LDS]
      summary: Get an isoline as H3 cells
      operationId: isolinesH3
      description: |
        Returns the area reachable from a point as a list of H3 cells, each with
        the travel time to reach it.

        Use this instead of `/v3/lds/isolines` when you want to join the result to
        other H3 data, or render it as a spatial index layer rather than a polygon.

        Only available when your organization's provider is **TravelTime**. Each
        request consumes 5 units of your LDS quota.
      parameters:
        - name: origin
          in: query
          required: true
          description: Origin point as `longitude,latitude`.
          schema:
            type: string
          example: -3.70739,40.41556
        - name: mode
          in: query
          required: true
          description: |
            Mode of transport. `car`, `walk` and `bike` are accepted as aliases for
            `driving`, `walking` and `cycling`.
          schema:
            type: string
            enum:
              - cycling
              - driving
              - driving+train
              - driving+public_transport
              - public_transport
              - walking
              - coach
              - bus
              - train
              - ferry
              - driving+ferry
              - cycling+ferry
              - cycling+public_transport
          example: driving
        - name: travelTime
          in: query
          required: true
          description: |
            Maximum travel time in seconds, between 60 and 36000. The usable
            maximum drops as `resolution` rises — 36000 at resolution 6 and 7,
            28800 at 8, 14400 at 9.
          schema:
            type: integer
            minimum: 60
            maximum: 36000
          example: 900
        - name: resolution
          in: query
          required: true
          description: H3 resolution of the returned cells.
          schema:
            type: integer
            minimum: 6
            maximum: 12
          example: 8
        - name: options
          in: query
          description: |
            TravelTime `departure_searches` options as a JSON string. Defaults to
            the current time and the transportation type from `mode`.
          schema:
            type: string
      responses:
        '200':
          description: The H3 cells covering the reachable area.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      description: The H3 cell index.
                    min:
                      type: number
                      description: Shortest travel time to the cell, in seconds.
                    max:
                      type: number
                      description: Longest travel time to the cell, in seconds.
                    mean:
                      type: number
                      description: Mean travel time to the cell, in seconds.
              example:
                - id: '881f1d4887fffff'
                  min: 121
                  max: 486
                  mean: 303
                - id: '881f1d4881fffff'
                  min: 204
                  max: 592
                  mean: 398
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/lds/routing:
    get:
      tags: [LDS]
      summary: Get a route
      operationId: routing
      description: |
        Returns a route between two points.

        Routing is only available when your organization's provider is HERE, TomTom
        or TravelTime.
      parameters:
        - name: origin
          in: query
          required: true
          description: Origin as `longitude,latitude`.
          schema:
            type: string
          example: -1.633492,42.811801
        - name: destination
          in: query
          required: true
          description: Destination as `longitude,latitude`.
          schema:
            type: string
          example: -1.660946,42.824662
        - name: mode
          in: query
          required: true
          description: |
            Mode of transport. Accepted values depend on the provider — HERE accepts
            `car`, `truck`, `pedestrian`, `bicycle`, `scooter`, `taxi`, `bus` and
            `privateBus`; TomTom accepts `car`, `pedestrian`, `bicycle`,
            `motorcycle`, `truck`, `taxi`, `bus` and `van`.
          schema:
            type: string
          example: car
        - name: waypoints
          in: query
          description: |
            Intermediate points, as colon-separated `latitude,longitude` pairs.
            Note the order is the reverse of `origin` and `destination`.
            TravelTime supports at most 9.
          schema:
            type: string
          example: -1.648453,42.813442:-1.657621,42.814813
        - name: options
          in: query
          description: Provider options as a JSON string.
          schema:
            type: string
      responses:
        '200':
          description: The route.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: [string, 'null']
                  value:
                    type: object
                    properties:
                      origin:
                        type: array
                        items:
                          type: number
                      destination:
                        type: array
                        items:
                          type: number
                      route:
                        description: The route geometry, as GeoJSON.
                        type: [object, 'null']
                      provider:
                        type: string
                      metadata:
                        type: object
                        description: The raw response from the provider.
                        additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/tokens:
    post:
      tags: [Tokens]
      summary: Create a token
      operationId: createToken
      description: |
        Creates an API Access Token.

        Each grant ties a connection to a source — a fully qualified table name, a
        SQL query, or `*` for everything reachable through that connection. Keep
        grants as narrow as your application allows.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
            example:
              grants:
                - connection_name: carto_dw
                  source: carto-demo-data.demo_tables.airports
              referers: []
              allowed_apis: [sql, maps]
      responses:
        '201':
          description: The token was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
              example:
                token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                grants:
                  - connection_name: carto_dw
                    source: carto-demo-data.demo_tables.airports
                referers: []
                allowed_apis: [sql, maps]
                name: tk_1a2b3c
                account_id: ac_jfakef5m
                created_at: '2026-07-30T16:10:35.732Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    get:
      tags: [Tokens]
      summary: List tokens
      operationId: listTokens
      description: Lists the API Access Tokens you can see.
      security:
        - accessToken: []
      responses:
        '200':
          description: The tokens.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Token'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/tokens/{token}:
    get:
      tags: [Tokens]
      summary: Get a token
      operationId: getToken
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/TokenPath'
      responses:
        '200':
          description: The token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags: [Tokens]
      summary: Update a token
      operationId: updateToken
      description: |
        Replaces the grants, referers, allowed APIs and name of a token. The
        expiration date can't be changed — create a new token instead.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/TokenPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
            example:
              grants:
                - connection_name: carto_dw
                  source: carto-demo-data.demo_tables.airports
              referers:
                - https://example.domain.com
              allowed_apis: [sql, maps, imports]
      responses:
        '200':
          description: The updated token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      tags: [Tokens]
      summary: Delete a token
      operationId: deleteToken
      description: Deletes a token and returns the deleted object.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/TokenPath'
      responses:
        '200':
          description: The deleted token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: |
            You can't delete this token — either it isn't yours, or a map is still
            using it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'

  /v3/named-sources:
    post:
      tags: [Named Sources]
      summary: Create a named source
      operationId: createNamedSource
      description: |
        Creates a named source — an alias for a SQL query that you can reference
        from the Maps and SQL APIs without exposing the query itself.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: |
                    Lowercase alphanumerics, hyphens and underscores. Must start
                    with a letter or digit, must not end with a hyphen or
                    underscore, and must be 3 to 51 characters long.
                  pattern: '^[a-z0-9][a-z0-9\-_]{2,50}(?<![-_])$'
                source:
                  type: string
                  description: The SQL query this name resolves to.
              required: [name, source]
            example:
              name: my_named_source_1
              source: SELECT * FROM carto-demo-data.demo_tables.populated_places LIMIT 100
      responses:
        '200':
          description: The named source was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NamedSource'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      tags: [Named Sources]
      summary: List named sources
      operationId: listNamedSources
      security:
        - accessToken: []
      parameters:
        - name: search
          in: query
          description: Filter by name.
          schema:
            type: string
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: pageSize
          in: query
          schema:
            type: integer
            default: 10
        - name: orderBy
          in: query
          schema:
            type: string
            enum: [name, createdAt, updatedAt]
            default: createdAt
        - name: orderDirection
          in: query
          schema:
            type: string
            enum: [ASC, DESC]
            default: DESC
      responses:
        '200':
          description: The named sources.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/NamedSource'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /v3/named-sources/{name}:
    get:
      tags: [Named Sources]
      summary: Get a named source
      operationId: getNamedSource
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/NamedSourceName'
      responses:
        '200':
          description: The named source.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NamedSource'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: The named source doesn't exist.
    patch:
      tags: [Named Sources]
      summary: Update a named source
      operationId: updateNamedSource
      description: Changes the query a named source points to. The name can't change.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/NamedSourceName'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                source:
                  type: string
              required: [source]
            example:
              source: SELECT geom, pop_max FROM carto-demo-data.demo_tables.populated_places LIMIT 500
      responses:
        '200':
          description: The updated named source.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NamedSource'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      tags: [Named Sources]
      summary: Delete a named source
      operationId: deleteNamedSource
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/NamedSourceName'
      responses:
        '204':
          description: The named source was deleted.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /v3/connections:
    get:
      tags: [Resources]
      summary: List connections
      operationId: listConnections
      security:
        - accessToken: []
      parameters:
        - name: search
          in: query
          schema:
            type: string
        - name: starred
          in: query
          schema:
            type: string
            enum: ['true', 'false']
        - name: order_by
          in: query
          schema:
            type: string
        - name: order_direction
          in: query
          schema:
            type: string
            enum: [ASC, DESC]
      responses:
        '200':
          description: The connections. Credentials are never returned.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Connection'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      tags: [Resources]
      summary: Create a connection
      operationId: createConnection
      description: |
        Creates a connection to a data warehouse.

        The `config` object depends on `provider_id` and on the authentication
        method — see the examples below. Secrets you send here are stored encrypted
        and never returned by any endpoint.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConnectionRequest'
            examples:
              bigquery:
                summary: BigQuery with a service account
                value:
                  name: example_bigquery_connection
                  provider_id: bigquery
                  config:
                    billing_project: your-billing-project
                    type: service_account
                    credentials:
                      type: service_account
                      project_id: your-project
                      private_key_id: ba0c1bdfcea5ca687ea2dfb136b6dd0b4c32a1c0
                      private_key: '-----BEGIN PRIVATE KEY-----\n...'
                      client_email: user@your-project.iam.gserviceaccount.com
                      client_id: '123456789'
                      auth_uri: https://accounts.google.com/o/oauth2/auth
                      token_uri: https://oauth2.googleapis.com/token
                      auth_provider_x509_cert_url: https://www.googleapis.com/oauth2/v1/certs
                      client_x509_cert_url: https://www.googleapis.com/robot/v1/metadata/x509/user%40your-project.iam.gserviceaccount.com
              snowflake:
                summary: Snowflake with a key pair
                value:
                  name: example_snowflake_connection
                  provider_id: snowflake
                  config:
                    type: key_pair
                    credentials:
                      username: YOUR_SNOWFLAKE_USERNAME
                      privateKey: YOUR_PRIVATE_KEY
                      passphrase: YOUR_PRIVATE_KEY_PASSPHRASE
                      account: YOUR_SNOWFLAKE_ACCOUNT_IDENTIFIER
                      database: YOUR_SNOWFLAKE_DATABASE
                      warehouse: YOUR_SNOWFLAKE_WAREHOUSE
                      role: YOUR_SNOWFLAKE_ROLE
              postgres:
                summary: PostgreSQL
                value:
                  name: example_postgresql_connection
                  provider_id: postgres
                  config:
                    type: user_password
                    credentials:
                      user: your_postgresql_user
                      password: your_password
                      host: host.domain.net
                      port: '5432'
                      database: your_database_name
              redshift:
                summary: Amazon Redshift
                value:
                  name: example-redshift-connection
                  provider_id: redshift
                  config:
                    type: user_password
                    credentials:
                      user: your-redshift-user
                      password: your_password
                      host: redshift-cluster-1.xxx.us-east-2.redshift.amazonaws.com
                      port: '5439'
                      database: your-redshift-database
              databricks:
                summary: Databricks with OAuth M2M
                value:
                  name: databricks-oauth-m2m
                  provider_id: databricksRest
                  config:
                    type: oauth_m2m
                    credentials:
                      host: your-databricks-host.com
                      servicePrincipalClientId: your_client_id
                      servicePrincipalSecret: your_client_secret
                      catalog: databricks_catalog_name
                      warehouseId: databricks_warehouse_id
      responses:
        '200':
          description: The connection was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Connection'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /v3/connections/{connectionId}:
    get:
      tags: [Resources]
      summary: Get a connection
      operationId: getConnection
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/ConnectionId'
      responses:
        '200':
          description: The connection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Connection'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      tags: [Resources]
      summary: Update a connection
      operationId: updateConnection
      description: |
        Updates a connection. You can't change `provider_id` or the authentication
        method. Secrets can be omitted to keep the stored values.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/ConnectionId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                privacy:
                  $ref: '#/components/schemas/ConnectionPrivacy'
                sharingScope:
                  type: string
                  enum: [organization, specific]
                  description: |
                    Required when `privacy` is `shared`, and must be omitted
                    otherwise.
                groupIds:
                  type: array
                  items:
                    type: string
                  description: Required when `privacy` is `shared`.
                config:
                  type: object
                  additionalProperties: true
              additionalProperties: true
            example:
              privacy: shared
              sharingScope: organization
              groupIds: ['1']
      responses:
        '200':
          description: The updated connection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Connection'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      tags: [Resources]
      summary: Delete a connection
      operationId: deleteConnection
      description: |
        Deletes a connection. Pass `targetConnectionId` to move its maps and
        workflows to another connection of the same provider first.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/ConnectionId'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                targetConnectionId:
                  type: string
                  format: uuid
      responses:
        '204':
          description: The connection was deleted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: |
            The connection is in use by other users in your organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v3/organization-maps:
    get:
      tags: [Resources]
      summary: List maps
      operationId: listMaps
      description: Lists the maps you have access to in your organization.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - name: order_by
          in: query
          schema:
            type: string
          example: title
        - $ref: '#/components/parameters/OrderDirection'
        - $ref: '#/components/parameters/Search'
        - name: privacy
          in: query
          schema:
            type: string
            enum: [private, shared, public]
        - $ref: '#/components/parameters/Tags'
      responses:
        '200':
          description: The maps.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/MapItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /v3/organization-maps/{mapId}:
    delete:
      tags: [Resources]
      summary: Delete a map
      operationId: deleteMap
      security:
        - accessToken: []
      parameters:
        - name: mapId
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: The map was deleted.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: You don't own this map, or it is locked by someone else.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'

  /v3/organization-workflows:
    get:
      tags: [Resources]
      summary: List workflows
      operationId: listWorkflows
      description: Lists the workflows you have access to in your organization.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - name: order_by
          in: query
          schema:
            type: string
          example: title
        - $ref: '#/components/parameters/OrderDirection'
        - $ref: '#/components/parameters/Search'
        - name: privacy
          in: query
          schema:
            type: string
            enum: [private, shared]
        - $ref: '#/components/parameters/Tags'
      responses:
        '200':
          description: The workflows.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/WorkflowItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /v3/organization-workflows/{workflowId}:
    delete:
      tags: [Resources]
      summary: Delete a workflow
      operationId: deleteWorkflow
      security:
        - accessToken: []
      parameters:
        - name: workflowId
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: The workflow was deleted.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: You don't own this workflow, or it is locked by someone else.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'

  /v3/accounts/resources:
    get:
      tags: [Resources]
      summary: List all resources in the organization
      operationId: listAllResources
      description: |
        Lists every map, workflow, connection or access token in the organization,
        regardless of owner.

        Requires the **Superadmin** role.
      security:
        - accessToken: []
      parameters:
        - name: resourceType
          in: query
          required: true
          schema:
            type: string
            enum: [map, workflow, connection, accessToken]
        - name: q
          in: query
          description: Free-text search.
          schema:
            type: string
            minLength: 1
        - name: orderBy
          in: query
          schema:
            type: string
            enum: [updatedAt, name]
            default: updatedAt
        - name: orderDirection
          in: query
          schema:
            type: string
            enum: [ASC, DESC]
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: pageSize
          in: query
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: |
            The resources. Access tokens are masked to their last 5 characters.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          type: object
                          additionalProperties: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /v3/accounts/resources/delete-batch:
    post:
      tags: [Resources]
      summary: Delete resources in batch
      operationId: deleteResourcesBatch
      description: |
        Deletes several resources at once.

        Individual failures are reported per item — the request still returns
        `200`. Check `success` on each entry.

        Requires the **Superadmin** role.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              minItems: 1
              items:
                $ref: '#/components/schemas/ResourceRef'
            example:
              - id: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                resourceType: map
      responses:
        '200':
          description: The result for each resource.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BatchResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /v3/accounts/resources/transfer:
    post:
      tags: [Resources]
      summary: Transfer resources to another user
      operationId: transferResources
      description: |
        Moves ownership of several resources to another user.

        Individual failures are reported per item — the request still returns
        `200`. Check `success` on each entry.

        Requires the **Superadmin** role.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                receiverUserId:
                  type: string
                  minLength: 1
                  description: The user who will own the resources.
                resources:
                  type: array
                  minItems: 1
                  items:
                    $ref: '#/components/schemas/ResourceRef'
              required: [receiverUserId, resources]
            example:
              receiverUserId: auth0|61164b7xxx77c006a259f53
              resources:
                - id: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                  resourceType: map
      responses:
        '200':
          description: The result for each resource.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BatchResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /v3/lds/stats:
    get:
      tags: [LDS]
      summary: Get LDS quota usage
      operationId: ldsStats
      description: |
        Returns your organization's Location Data Services quota, how much of it has
        been consumed in the current billing period, and which provider serves each
        operation.
      responses:
        '200':
          description: The quota usage.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    annual_quota:
                      type: number
                    used_quota:
                      type: number
                    providers:
                      type: object
                      properties:
                        geocoding:
                          type: string
                        isolines:
                          type: string
                        routing:
                          type: string
              example:
                - annual_quota: 100000
                  used_quota: 1234
                  providers:
                    geocoding: here
                    isolines: here
                    routing: tomtom
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/exports:
    post:
      tags: [Exports]
      summary: Create an export job
      operationId: createExport
      description: |
        Exports a table or a query to a file.

        The job runs asynchronously — poll it until `status` is `success`, then
        download the file from `result.downloadUrl`.

        By default the file lands in CARTO's storage and the job returns a signed
        download URL valid for 24 hours. Pass `destUrl` to write to your own bucket
        instead, in which case no download URL is returned.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExportRequest'
            examples:
              table:
                summary: Export a table as GeoParquet
                value:
                  connection: carto_dw
                  source: carto-demo-data.demo_tables.airports
                  format: geoparquet
              query:
                summary: Export the result of a query as CSV
                value:
                  connection: carto_dw
                  type: query
                  source: SELECT name, geom FROM carto-demo-data.demo_tables.airports WHERE country = 'Spain'
                  format: csv
                  name: spanish_airports
              ownBucket:
                summary: Export to your own bucket
                value:
                  connection: carto_dw
                  source: carto-demo-data.demo_tables.airports
                  format: geojson
                  destUrl: gs://your-bucket/exports/airports.geojson
      responses:
        '201':
          description: The export job was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobId:
                    type: string
                    format: uuid
                  status:
                    $ref: '#/components/schemas/ExportJobStatus'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                status: pending
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The connection doesn't exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    get:
      tags: [Exports]
      summary: List export jobs
      operationId: listExports
      description: Lists your organization's export jobs, newest first.
      parameters:
        - name: limit
          in: query
          description: How many jobs to return.
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          description: How many jobs to skip.
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: The export jobs.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ExportJob'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/exports/{jobId}:
    get:
      tags: [Exports]
      summary: Get an export job
      operationId: getExport
      description: |
        Returns the current state of an export job. Poll this until `status` is
        `success`, `failure` or `cancelled`.
      parameters:
        - $ref: '#/components/parameters/ExportJobId'
      responses:
        '200':
          description: The export job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportJob'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                createdAt: '2026-07-31T16:10:35.732Z'
                connection: carto_dw
                source: carto-demo-data.demo_tables.airports
                format: geoparquet
                status: success
                error: ''
                result:
                  rowCount: 1000
                  format: geoparquet
                  outputUrl: gs://carto-exports/exports/5a32a0ea-555a-48dd-aeb1-8768aae8ef1c/airports.parquet
                  downloadUrl: https://storage.googleapis.com/carto-exports/exports/5a32a0ea-555a-48dd-aeb1-8768aae8ef1c/airports.parquet?X-Goog-Signature=...
                  fileSize: 70307
                  expirationDate: '2026-08-01T16:10:35.732Z'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: |
            The job doesn't exist, or belongs to another organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /v3/exports/{jobId}/cancel:
    post:
      tags: [Exports]
      summary: Cancel an export job
      operationId: cancelExport
      description: |
        Cancels an export job that is still `pending` or `running`.

        A `200` doesn't guarantee the job was cancelled — if it finished while the
        request was in flight, the response carries its actual final status. Always
        read `status` rather than relying on the status code.
      parameters:
        - $ref: '#/components/parameters/ExportJobId'
      responses:
        '200':
          description: |
            The job's status after the attempt — `cancelled`, or the state it
            reached first.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobId:
                    type: string
                    format: uuid
                  status:
                    $ref: '#/components/schemas/ExportJobStatus'
              example:
                jobId: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
                status: cancelled
        '400':
          description: The job already finished and can't be cancelled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: The job has finished and it cannot be cancelled
                status: 400
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /activity-data-jobs:
    servers:
      - url: https://{accountsHost}
        description: CARTO accounts host
        variables:
          accountsHost:
            default: accounts.app.carto.com
    post:
      tags: [Activity Data]
      summary: Create an activity data job
      operationId: createActivityDataJob
      description: |
        Exports your organization's activity data for a time range.

        The job runs asynchronously — poll
        `GET /activity-data-jobs/{jobId}`
        until `status` is `success`, then use the returned download URLs.

        Note this endpoint lives on the **accounts host**, not on your regional API
        base URL, and there is no `/v3` in the path.

        Requires the **Admin** or **Superadmin** role.
      security:
        - accessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                categories:
                  type: array
                  minItems: 1
                  items:
                    type: string
                    enum: [activity, apiUsage, userList, groupList]
                  description: Which data to export. No duplicates.
                format:
                  type: string
                  enum: [csv, parquet]
                startTime:
                  type: string
                  description: |
                    Start of the range. Must be after your account was created.
                endTime:
                  type: string
                  description: |
                    End of the range. Must be after `startTime`, and can't be in the
                    future or cover data that isn't ready yet. The range must be
                    under 60 days.
              required: [categories, format, startTime, endTime]
            example:
              categories: [activity, apiUsage]
              format: csv
              startTime: '2026-06-27 00:00:00 UTC'
              endTime: '2026-06-29 00:00:00 UTC'
      responses:
        '201':
          description: The job was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
              example:
                id: e38163e9-37f3-4269-b400-c7b160325bce
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: |
            You aren't an admin, or activity data isn't available for your account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /activity-data-jobs/{jobId}:
    servers:
      - url: https://{accountsHost}
        description: CARTO accounts host
        variables:
          accountsHost:
            default: accounts.app.carto.com
    get:
      tags: [Activity Data]
      summary: Get an activity data job
      operationId: getActivityDataJob
      description: |
        Returns the state of an activity data job. When `status` is `success` the
        response includes the download URLs and their expiry.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/ActivityJobId'
      responses:
        '200':
          description: The job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivityDataJob'
              examples:
                success:
                  summary: Finished job
                  value:
                    id: e38163e9-37f3-4269-b400-c7b160325bce
                    status: success
                    downloadUrls:
                      activity:
                        - https://storage.googleapis.com/carto-acc-us-east1-1-export-storage/activity-0.csv
                      apiUsage:
                        - https://storage.googleapis.com/carto-acc-us-east1-1-export-storage/api-usage-0.csv
                    downloadUrlsExpirationDate: '2026-08-02T11:26:14.125Z'
                    categories: [activity, apiUsage]
                    startTime: '2026-07-23T00:00:00.000Z'
                    endTime: '2026-07-24T00:00:00.000Z'
                    format: csv
                    createdAt: '2026-07-26T11:26:03.121Z'
                failure:
                  summary: Failed job
                  value:
                    id: e38163e9-37f3-4269-b400-c7b160325bc1
                    status: failure
                    errorMessage: Error executing the activity data job, please try again or contact support if the problem persists
                    categories: [activity, apiUsage]
                    startTime: '2026-07-23T00:00:00.000Z'
                    endTime: '2026-07-24T00:00:00.000Z'
                    format: csv
                    createdAt: '2026-07-26T11:26:03.121Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /activity-data-jobs/{jobId}/cancel:
    servers:
      - url: https://{accountsHost}
        description: CARTO accounts host
        variables:
          accountsHost:
            default: accounts.app.carto.com
    delete:
      tags: [Activity Data]
      summary: Cancel an activity data job
      operationId: cancelActivityDataJob
      description: |
        Cancels a job that is still `pending` or `running`. Cancelling a finished
        job returns `400`.
      security:
        - accessToken: []
      parameters:
        - $ref: '#/components/parameters/ActivityJobId'
      responses:
        '200':
          description: The cancelled job.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivityDataJob'
        '400':
          description: The job already finished and can't be cancelled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  securitySchemes:
    accessToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An API Access Token or an OAuth Access Token, sent as
        `Authorization: Bearer <token>`.

  parameters:
    ConnectionName:
      name: connectionName
      in: path
      required: true
      description: Name of the connection to use.
      schema:
        type: string
      example: carto_dw
    QueryParameters:
      name: queryParameters
      in: query
      description: |
        Values for the parameters in the query, as a JSON string. Named object on
        BigQuery, positional array on Snowflake, Redshift and PostgreSQL.
      schema:
        type: string
      example: '{"minRevenue": 100000, "type": "Supermarket"}'
    SpatialDataColumn:
      name: spatialDataColumn
      in: query
      description: |
        Column holding the geometry or spatial index. Defaults to `geom`.
        Required from `v=3.3` onwards.
      schema:
        type: string
    SpatialDataType:
      name: spatialDataType
      in: query
      description: |
        Type of the spatial column. Defaults to `geo`. Required from `v=3.3`
        onwards.
      schema:
        type: string
        enum: [geo, h3, h3int, quadbin]
    GeoColumn:
      name: geo_column
      in: query
      deprecated: true
      description: |
        Legacy way to select the geometry column, in the form
        `[spatialIndexType:]columnName`. Use `spatialDataColumn` and
        `spatialDataType` instead — from `v=3.3` this parameter returns `400`.
      schema:
        type: string
    Columns:
      name: columns
      in: query
      description: Comma-separated list of columns to return.
      schema:
        type: string
      example: name,geom
    TileResolution:
      name: tileResolution
      in: query
      description: Resolution of the generated tiles.
      schema:
        type: number
        enum: [0.25, 0.5, 1, 2, 4]
    AggregationExp:
      name: aggregationExp
      in: query
      description: |
        Aggregation expression applied when building spatial index tiles, for
        example `SUM(population) as population`.
      schema:
        type: string
    AggregationResLevel:
      name: aggregationResLevel
      in: query
      description: |
        Resolution level for spatial index aggregation. Requires
        `aggregationExp`. Defaults to 6 for quadbin and 4 for H3.
      schema:
        type: integer
    ApiVersion:
      name: v
      in: query
      description: |
        API version. From `3.3`, `spatialDataColumn` and `spatialDataType` replace
        `geo_column`.
      schema:
        type: string
        enum: ['3.0', '3.1', '3.2', '3.3', '3.4']
        default: '3.0'
    JobId:
      name: jobId
      in: path
      required: true
      description: The job identifier.
      schema:
        type: string
      example: job_h8UWzpdzX0s2XAAXQd3rdWCdPUT9
    ExportJobId:
      name: jobId
      in: path
      required: true
      description: The export job identifier.
      schema:
        type: string
        format: uuid
      example: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
    ActivityJobId:
      name: jobId
      in: path
      required: true
      description: The job identifier.
      schema:
        type: string
      example: e38163e9-37f3-4269-b400-c7b160325bce
    TokenPath:
      name: token
      in: path
      required: true
      description: The token string.
      schema:
        type: string
    NamedSourceName:
      name: name
      in: path
      required: true
      description: The name of the named source.
      schema:
        type: string
      example: my_named_source_1
    ConnectionId:
      name: connectionId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      example: 5a32a0ea-555a-48dd-aeb1-8768aae8ef1c
    Page:
      name: page
      in: query
      schema:
        type: integer
        minimum: 1
        default: 1
    PageSize:
      name: page_size
      in: query
      schema:
        type: integer
        default: 12
    OrderDirection:
      name: order_direction
      in: query
      schema:
        type: string
        enum: [ASC, DESC]
    Search:
      name: search
      in: query
      description: Free-text search over the title.
      schema:
        type: string
      example: sales
    Tags:
      name: tags
      in: query
      description: A JSON-encoded array of tags to filter by.
      schema:
        type: string
      example: '["new", "biz"]'

  responses:
    SqlResult:
      description: The query result.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SqlResponse'
          example:
            rows:
              - name: Madrid Barajas
                geom:
                  type: Point
                  coordinates: [-3.56676, 40.47225]
            schema:
              - name: name
                type: string
              - name: geom
                type: geometry
    BadRequest:
      description: The request is malformed or a parameter failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: "Missing or invalid 'q' parameter"
            status: 400
    Unauthorized:
      description: The token is missing, malformed or expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Account not found
            status: 401
    Forbidden:
      description: The token doesn't grant access to this resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Token not found
            status: 403
    NotFound:
      description: The resource doesn't exist.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Job not found
            status: 404
    TooManyRequests:
      description: |
        You went over the [rate limit](#rate-limits) for this API.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Rate limit exceeded
            status: 429

  schemas:
    Error:
      type: object
      description: |
        Most errors return `error` and `status`. Some return a richer object from
        CARTO's error catalog, which adds `code`, `title`, `detail` and `severity`.
      properties:
        error:
          type: string
          description: A human-readable description of what went wrong.
        status:
          type: integer
          description: The HTTP status code.
        code:
          type: integer
          description: CARTO error catalog code. Only on catalog errors.
        title:
          type: string
          description: Short error title. Only on catalog errors.
        detail:
          type: string
          description: Additional detail. Only on catalog errors.
        severity:
          type: string
          description: Error severity. Only on catalog errors.
      required:
        - error
        - status

    SchemaField:
      type: object
      description: A column in the result set.
      properties:
        name:
          type: string
        type:
          type: string
          enum:
            - number
            - bigint
            - string
            - geometry
            - timestamp
            - object
            - boolean
            - variant
            - unknown
            - array
      required:
        - name
        - type

    QueryParametersValue:
      description: |
        Values for the parameters in the query. A named object on BigQuery, a
        positional array on Snowflake, Redshift and PostgreSQL.
      oneOf:
        - type: object
          additionalProperties: true
        - type: array
          items: {}

    MapResponse:
      type: object
      description: |
        Metadata and download URLs for a map layer. Which format keys are present
        depends on the size of the source — large sources only offer `tilejson`.
      properties:
        size:
          type: integer
          description: Size of the source in bytes.
        nrows:
          type: integer
          description: Number of rows in the source.
        ndjson:
          $ref: '#/components/schemas/MapResponseItem'
        geojson:
          $ref: '#/components/schemas/MapResponseItem'
        json:
          $ref: '#/components/schemas/MapResponseItem'
        binary:
          $ref: '#/components/schemas/MapResponseItem'
        tilejson:
          $ref: '#/components/schemas/MapResponseItem'
        schema:
          type: array
          items:
            $ref: '#/components/schemas/SchemaField'

    MapResponseItem:
      type: object
      properties:
        url:
          type: array
          items:
            type: string
            format: uri
        error:
          type: string

    SqlResponse:
      type: object
      description: |
        The rows returned by the query, plus the schema of the result set.
        Responses are capped at 200,000 rows.
      properties:
        rows:
          type: array
          description: |
            The result rows. Geometry columns are returned as GeoJSON.
          items:
            type: object
            additionalProperties: true
        schema:
          type: array
          items:
            $ref: '#/components/schemas/SchemaField'
        meta:
          type: object
          description: Provider-specific metadata.
          additionalProperties: true

    JobStatus:
      type: string
      description: |
        `success`, `failure` and `cancelled` are final states.
      enum:
        - pending
        - running
        - success
        - failure
        - cancelled
        - blocked
        - resuming_warehouse

    JobCreated:
      type: object
      description: An asynchronous SQL job, as returned when it is created.
      properties:
        externalId:
          type: string
          description: Use this to poll the job.
        accountId:
          type: string
        userId:
          type: [string, 'null']
        connectionId:
          type: string
        connectionName:
          type: string
        providerId:
          type: string
        metadata:
          type: object
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
        query:
          type: string
        jobMetadata:
          type: object
          description: |
            Provider metadata. For workflows executed via API this holds
            `workflowOutputTableName`.
          additionalProperties: true
        token:
          type: [string, 'null']

    Job:
      type: object
      description: The state of an asynchronous SQL job.
      properties:
        jobId:
          type: string
        connectionName:
          type: string
        providerId:
          type: string
        query:
          type: [string, 'null']
        status:
          $ref: '#/components/schemas/JobStatus'
        error:
          type: [object, 'null']
          properties:
            msg:
              type: string
            code:
              type: [string, 'null']
        createdAt:
          type: string
          format: date-time
        provider:
          type: object
          description: |
            Provider-specific execution detail. Omitted for jobs created from a
            named source.
          additionalProperties: true
        jobMetadata:
          type: object
          additionalProperties: true
        metadata:
          type: object
          additionalProperties: true
        token:
          type: [string, 'null']

    JobListItem:
      type: object
      description: |
        A job as returned by the list endpoint. Note this shape uses `state` where
        `GET /v3/sql/{connectionName}/job/{jobId}` uses `status`.
      properties:
        externalId:
          type: string
        accountId:
          type: string
        userId:
          type: [string, 'null']
        connectionId:
          type: string
        metadata:
          type: object
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        query:
          type: [string, 'null']
        state:
          $ref: '#/components/schemas/JobStatus'
        jobMetadata:
          type: object
          additionalProperties: true
        token:
          type: [string, 'null']

    ExportJobStatus:
      type: string
      description: |
        `success`, `failure` and `cancelled` are final states.
      enum:
        - pending
        - running
        - success
        - failure
        - cancelled

    ExportFormat:
      type: string
      enum:
        - geoparquet
        - geojson
        - shapefile
        - geopackage
        - csv
        - tab
        - kml
        - kmz

    ExportRequest:
      type: object
      properties:
        connection:
          type: string
          description: Name of the connection to export through.
        source:
          type: string
          description: |
            A fully qualified table name, or a SQL query when `type` is `query`.
            A named source is also accepted for queries.
        format:
          $ref: '#/components/schemas/ExportFormat'
        type:
          type: string
          enum: [table, query]
          default: table
          description: Whether `source` is a table name or a query.
        name:
          type: string
          description: |
            Filename for the exported file, without extension. Defaults to the
            table name. Unsupported characters are replaced with `_`.
        destUrl:
          type: string
          description: |
            Write the export to your own bucket instead of CARTO's storage.
            Accepts `gs://`, `s3://` and `https://`. When set, the job returns no
            download URL.
        config:
          type: object
          description: |
            Shape the exported rows with raw SQL fragments. Can't be combined with
            the structured fields below.
          properties:
            select:
              type: array
              items:
                type: string
              description: Columns to export.
            where:
              type: string
              description: A SQL predicate, without the leading `WHERE`.
            limit:
              type: integer
              minimum: 1
              description: Maximum rows to export.
        columns:
          type: array
          items:
            type: string
          description: Columns to export. Can't be combined with `config.select`.
        filters:
          type: object
          additionalProperties: true
          description: Attribute filters to apply.
        spatialFilter:
          type: object
          additionalProperties: true
          description: |
            Viewport geometry to clip to, keyed by the spatial index column.
        spatialDataColumn:
          type: string
          description: The geometry or spatial index column.
        spatialDataType:
          type: string
          description: '`geo`, `h3`, `h3int` or `quadbin`.'
        featureIds:
          type: array
          items:
            type: string
          description: |
            Export only these features. Requires `geometryType` and
            `spatialDataColumn` — without both, the filter is ignored.
        geometryType:
          type: string
          description: Required alongside `featureIds`.
        queryParameters:
          $ref: '#/components/schemas/QueryParametersValue'
      required:
        - connection
        - source
        - format

    ExportJob:
      type: object
      properties:
        jobId:
          type: string
          format: uuid
        createdAt:
          type: string
          format: date-time
        connection:
          type: string
          description: |
            Name of the connection. Falls back to its identifier if the connection
            has since been deleted.
        source:
          type: string
        format:
          $ref: '#/components/schemas/ExportFormat'
        status:
          $ref: '#/components/schemas/ExportJobStatus'
        error:
          type: string
          description: Empty string when the job hasn't failed.
        result:
          type: object
          description: |
            Empty until the job succeeds.
          properties:
            rowCount:
              type: integer
              description: |
                Rows exported. `-1` when the data warehouse doesn't report a count.
            format:
              type: string
            outputUrl:
              type: string
              description: Where the file was written.
            downloadUrl:
              type: string
              description: |
                Signed URL to download the file. Only present when the export went
                to CARTO's storage — not when you passed `destUrl`.
            fileSize:
              type: integer
              description: Size of the exported file in bytes.
            expirationDate:
              type: string
              format: date-time
              description: When `downloadUrl` stops working, 24 hours after minting.

    ImportJobStatus:
      type: string
      description: |
        `success`, `failure` and `cancelled` are final states.
      enum:
        - pending
        - running
        - success
        - failure
        - cancelled

    ImportRequest:
      type: object
      properties:
        connection:
          type: string
          description: Name of the connection to import through.
        url:
          type: string
          format: uri
          description: Public URL of the file to import.
        destination:
          type: string
          description: Fully qualified name of the table to create.
        overwrite:
          type: boolean
          default: false
          description: Replace the destination table if it already exists.
        autoguessing:
          type: boolean
          default: true
          description: |
            Let CARTO detect the schema. Set to `false` to import with the `schema`
            you provide.
        schema:
          type: object
          description: |
            The schema to use when `autoguessing` is `false`. Get a starting point
            from `POST /v3/imports/preview`.
          properties:
            columns:
              type: array
              items:
                $ref: '#/components/schemas/ImportColumn'
        dryRun:
          type: boolean
          default: false
          description: |
            Validate the import without writing anything. Can't be combined with
            `overwrite`.
        ignoreErrors:
          type: boolean
          description: |
            Skip rows that fail to parse. Defaults to the value of `autoguessing`.
        maxErrors:
          type: integer
          description: |
            How many bad rows to tolerate. Defaults to 1000 when `autoguessing` is
            on, 0 otherwise.
        wrapDateLine:
          type: boolean
          default: false
          description: Wrap geometries that cross the antimeridian.
        preserveSourceCrs:
          type: boolean
          default: false
          description: |
            Keep the source coordinate reference system instead of reprojecting to
            EPSG:4326.
        metadata:
          type: object
          description: Arbitrary metadata stored with the job.
          additionalProperties: true
      required:
        - connection
        - url
        - destination

    ImportColumn:
      type: object
      properties:
        name:
          type: string
        type:
          type: string
          description: A data type supported by the destination data warehouse.
        nullable:
          type: boolean
        width:
          type: integer
        precision:
          type: integer
        scale:
          type: integer
      required:
        - name
        - type

    ImportJob:
      type: object
      properties:
        jobId:
          type: string
          format: uuid
        createdAt:
          type: string
          format: date-time
        connection:
          type: string
        resource:
          type: string
          description: The URL the data was imported from.
        destination:
          type: string
        overwrite:
          type: boolean
          description: Only returned by the list endpoint.
        status:
          $ref: '#/components/schemas/ImportJobStatus'
        error:
          description: |
            Empty string when the job hasn't failed. Otherwise a message or a
            structured error object.
        metadata:
          type: object
          additionalProperties: true

    ImportPreview:
      type: object
      properties:
        columns:
          type: array
          description: The columns CARTO detected.
          items:
            $ref: '#/components/schemas/ImportColumn'
        options:
          type: array
          description: Data types available in the destination data warehouse.
          items:
            type: object
            properties:
              name:
                type: string
        raster:
          type: boolean
        source:
          type: object
          description: Details about the source file.
          additionalProperties: true

    GeocodingResult:
      type: object
      description: |
        A geocoding result. Fields depend on the provider configured for your
        organization — the ones below are the most common.
      additionalProperties: true
      properties:
        formattedAddress:
          type: string
        latitude:
          type: number
        longitude:
          type: number
        country:
          type: string
        countryCode:
          type: string
        state:
          type: string
        county:
          type: string
        city:
          type: string
        zipcode:
          type: string
        streetName:
          type: string
        streetNumber:
          type: string
        provider:
          type: string

    PaginatedResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            page:
              type: object
              properties:
                current:
                  type: integer
                pageSize:
                  type: integer
                total:
                  type: [integer, 'null']
                totalPages:
                  type: [integer, 'null']
        links:
          type: object
          properties:
            prev:
              type: [string, 'null']
            next:
              type: [string, 'null']

    TokenAllowedApi:
      type: string
      enum:
        - maps
        - sql
        - imports
        - exports
        - lds
        - httpRequest
        - resources
        - workflows
        - batch
        - ai
        - mcp
        - aiProxy
        - workspaceMaps

    Grant:
      type: object
      description: |
        Grants access to a source through a connection. Use `source` for a table
        name or a SQL query, or `resource` for a fully qualified name that may
        contain wildcards. `*` grants access to everything reachable through the
        connection.
      properties:
        connection_name:
          type: string
        source:
          type: string
        resource:
          type: string
      required:
        - connection_name

    TokenRequest:
      type: object
      properties:
        grants:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/Grant'
        allowed_apis:
          type: array
          minItems: 1
          description: Which APIs this token can call.
          items:
            $ref: '#/components/schemas/TokenAllowedApi'
        referers:
          type: array
          description: |
            Restrict use of the token to these HTTP referers. Empty means any.
          items:
            type: string
        name:
          type: string
          description: A name for the token. Generated if omitted.
        expiration_date:
          type: string
          format: date-time
          description: |
            When the token stops working. Must be in the future. Omit for a token
            that never expires. Can only be set at creation.
      required:
        - grants
        - allowed_apis

    Token:
      type: object
      properties:
        token:
          type: string
          description: The token to send in the `Authorization` header.
        grants:
          type: array
          items:
            $ref: '#/components/schemas/Grant'
        allowed_apis:
          type: array
          items:
            $ref: '#/components/schemas/TokenAllowedApi'
        referers:
          type: [array, 'null']
          items:
            type: string
        name:
          type: string
        user_id:
          type: [string, 'null']
        account_id:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        expiration_date:
          type: [string, 'null']
          format: date-time

    NamedSource:
      type: object
      properties:
        name:
          type: string
        source:
          type: string
        accountId:
          type: string
        userId:
          type: string
        createdAt:
          type: string
        updatedAt:
          type: string

    ConnectionPrivacy:
      type: string
      enum: [private, shared]

    ConnectionRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
        provider_id:
          type: string
          enum:
            - bigquery
            - snowflake
            - redshift
            - postgres
            - databricksRest
            - databricksWarehouse
            - oracle
        config:
          type: object
          description: |
            Provider-specific configuration. `type` selects the authentication
            method and `credentials` holds the secrets — see the examples.
          additionalProperties: true
        privacy:
          $ref: '#/components/schemas/ConnectionPrivacy'
        groupIds:
          type: array
          description: Required when `privacy` is `shared`.
          items:
            type: string
      required:
        - name
        - provider_id
        - config

    Connection:
      type: object
      description: |
        A data warehouse connection. Credentials are never returned — secret fields
        are stripped from `config`.
      additionalProperties: true
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        provider_id:
          type: string
        user_id:
          type: string
        account_id:
          type: string
        privacy:
          $ref: '#/components/schemas/ConnectionPrivacy'
        config:
          type: object
          additionalProperties: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    MapItem:
      type: object
      properties:
        id:
          type: string
        title:
          type: [string, 'null']
        description:
          type: [string, 'null']
        thumbnailUrl:
          type: string
        tags:
          type: array
          items:
            type: string
        views:
          type: integer
        userId:
          type: string
        privacy:
          type: string
          enum: [private, shared, public]
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    WorkflowItem:
      type: object
      properties:
        id:
          type: string
        title:
          type: [string, 'null']
        description:
          type: [string, 'null']
        thumbnailUrl:
          type: string
        tags:
          type: array
          items:
            type: string
        userId:
          type: string
        privacy:
          type: string
          enum: [private, shared]
        providerId:
          type: string
        connectionId:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    ResourceRef:
      type: object
      properties:
        id:
          type: string
        resourceType:
          type: string
          enum: [map, workflow, connection, accessToken]
      required:
        - id
        - resourceType

    BatchResult:
      type: object
      properties:
        id:
          type: string
        resourceType:
          type: string
          enum: [map, workflow, connection, accessToken]
        success:
          type: boolean
        failureReason:
          type: string
          description: Only present when `success` is `false`.

    ActivityDataJob:
      type: object
      description: |
        An activity data export job. `downloadUrls` and
        `downloadUrlsExpirationDate` are only present when `status` is `success`;
        `errorMessage` only when it is `failure`.
      properties:
        id:
          type: string
        status:
          type: string
          enum: [pending, running, success, failure, cancelled]
        categories:
          type: array
          items:
            type: string
            enum: [activity, apiUsage, userList, groupList]
        format:
          type: string
          enum: [csv, parquet]
        startTime:
          type: string
          format: date-time
        endTime:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        downloadUrls:
          type: object
          description: Download URLs per category.
          additionalProperties:
            type: array
            items:
              type: string
              format: uri
        downloadUrlsExpirationDate:
          type: string
          format: date-time
        errorMessage:
          type: string

    GeoJsonFeatureCollection:
      type: object
      properties:
        type:
          type: string
          enum: [FeatureCollection]
        features:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum: [Feature]
              properties:
                type: object
                additionalProperties: true
              geometry:
                type: object
                additionalProperties: true
