Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

















# Query argument
carto sql query <connection> "SELECT * FROM dataset.table LIMIT 10"
# Read SQL from a file
carto sql query <connection> --file query.sql
# Pipe via stdin
echo "SELECT COUNT(*) FROM dataset.table" | carto sql query <connection>
# Cached read (GET, 1-year cache, 1-minute timeout)
carto sql query <connection> "SELECT * FROM dataset.table" --cache
# JSON output
carto sql query <connection> "SELECT * FROM dataset.table" --json# CREATE TABLE
carto sql job <connection> "CREATE TABLE dataset.newtable AS SELECT * FROM dataset.oldtable"
# INSERT
carto sql job <connection> "INSERT INTO dataset.table VALUES (1, 'test')"
# Read from a file
carto sql job <connection> --file create_table.sql
npm install -g @carto/carto-clicarto --version
carto --helpnpm install -g @carto/carto-cli@latestcarto auth login # Login to default profile
carto auth login staging # Login to a named profile
carto auth login --organization-name "ACME" # Organization-specific login (SSO or standard)
carto auth login acme-prod --organization-name "ACME Corporation"carto auth logout # Logout from default profile
carto auth logout staging # Logout from named profilecarto auth status
carto auth status productioncarto auth use productioncarto auth whoamicarto transfer --source-connection <n> --dest-connection <n> --source-table <t> --dest-table <t>
carto transfer status <jobId> # Fetch status of an async transfer job# Transfer from BigQuery to Snowflake
carto transfer \
--source-connection bigquery-prod \
--dest-connection snowflake-analytics \
--source-table project.dataset.customers \
--dest-table db.schema.customers
# With geography support, async
carto transfer \
--source-connection bq-prod \
--dest-connection postgres-dev \
--source-table project.dataset.geo_data \
--dest-table public.geo_data \
--geography --async
# Poll an async transfer
carto transfer status <jobId>









workflows_temp dataset in that other region and specify its location in the Advanced options of your BigQuery connection.gemini mcp add carto-pm-org \
https://<region>.api.carto.com/mcp/<account_id> \
-H 'Authorization: Bearer <YOUR_API_TOKEN>' \
-t httpNew features and improvements introduced from April to June 2025






































# Export as GeoParquet (waits, prints download URL)
carto export --connection carto_dw --source project.dataset.my_table --format geoparquet
# Export selected columns with a WHERE predicate and a row limit
carto export \
--connection carto_dw \
--source project.dataset.my_table \
--format csv \
--select name,lon,lat \
--where "year = 2025" \
--limit 10000
# Export directly to cloud storage
carto export \
--connection carto_dw \
--source project.dataset.my_table \
--format geojson \
--dest-url gs://my-bucket/exports/data.geojson
# Kick off async, then poll status separately
carto export --connection carto_dw --source project.dataset.big --format csv --async
carto export status <jobId>SUM(female) / NULLIF(SUM(population), 0)carto connections listcarto connections get conn_xyz789carto connections create '{
"name": "my-snowflake",
"type": "snowflake",
"parameters": {
"account": "myaccount",
"warehouse": "compute_wh"
}
}'carto connections update conn_xyz789 '{ "parameters": { "warehouse": "new_wh" } }'carto connections delete conn_xyz789# Top-level tree for a connection
carto connections browse carto_dw
# Drill into a specific subtree
carto connections browse carto_dw "carto-demo-data"carto connections describe carto_dw "carto-demo-data.demo_tables.nyc_collisions"carto connections search my-conn "customers"
carto connections search my-conn "orders" --scope "mydb.public" --type tablecarto named-sources list # List named sources
carto named-sources get <name> # Get named source details
carto named-sources create --name <n> --source <sql> # Create named source
carto named-sources update <name> --source <sql> # Update named source
carto named-sources delete <name> # Delete named source# List all named sources
carto named-sources list
# Search named sources
carto named-sources list --search "my_source"
# Create a named source
carto named-sources create --name my_source --source "SELECT * FROM project.dataset.table"
# Get details
carto named-sources get my_source
# Update the SQL query
carto named-sources update my_source --source "SELECT id, geom FROM project.dataset.table"
# Delete (with confirmation)
carto named-sources delete my_source
# Delete (skip confirmation for CI/CD)
carto named-sources delete my_source --yesnpm install -g @carto/carto-cli
carto auth login
carto auth status # confirm: ✓ Authenticated/plugin marketplace add CartoDB/agent-skills
/plugin install carto-skills@agent-skillsnpx skills add CartoDB/agent-skillscarto import --file <path> --connection <name> --destination <table>
carto import --url <url> --connection <name> --destination <table>
carto import status <jobId> # Fetch status of an async import job# Import local CSV
carto import --file ./data.csv --connection carto_dw --destination project.dataset.my_table
# Import from URL with overwrite
carto import \
--url https://example.com/data.geojson \
--connection carto_dw \
--destination project.dataset.table \
--overwrite
# Kick off async, then poll status separately
carto import --file ./big.csv --connection carto_dw --destination my.table --async
carto import status <jobId>
# JSON output (for scripts)
carto import --file ./data.geojson --connection carto_dw --destination project.dataset.table --json
https://<region>.api.carto.com/mcp/<account_id>




SUM(female) / NULLIF(SUM(population), 0)


SUM(female) / NULLIF(SUM(population), 0)carto [global-options] <command> <subcommand> [args...]# Read
carto projects list [options] # Top-level projects
carto projects get <id|name> # Project details + full contents tree
# Top-level CRUD
carto projects create --name <name> # New top-level project
carto projects rename <path> --to <name> # Rename a folder
carto projects delete <path> # Delete a folder or shortcut
# Asset placement
carto projects add <path> --folder <name> # Create a subfolder inside a project
carto projects add <path> --map <map-id> # Add an existing map (creates a shortcut)
carto projects add <path> --workflow <wf-id> # Add an existing workflow (creates a shortcut)
carto projects move <path> --to <path> # Move a folder or shortcut to a new parent
# Local-sync workflow
carto projects init <name> # New project + scaffold a local working dir
carto projects clone <id|name> # Materialize an existing project to disk
carto projects status # Show local-vs-clone diff (run inside a checkout)carto admin list <resource-type>carto admin list maps
carto admin list workflows
carto admin list connections
# With pagination and search
carto admin list maps --page-size 50
carto admin list connections --search snowflake
# Fetch every page
carto admin list maps --all
carto admin list workflows --allLearn everything you need to know about your Workspace and how to make the most out of it.

















.gitignore — meta, untracked.



















# Start a brand-new project — creates server-side and scaffolds a local dir
carto projects init "Q2 Analytics" --color "#3478f6"
cd q2-analytics
$EDITOR AGENTS.md # capture project context for an agent
# Or check out an existing project
carto projects clone "Q2 Analytics"
cd q2-analytics
ls -R # AGENTS.md, README.md, *.map.json, *.workflow.json
# See what's changed locally vs the clone
carto projects status
# Optionally check whether anything moved on the server since you cloned
carto projects status --server$EDITOR my-map.map.json
carto maps update <map-id> < my-map.map.json# Browse
carto projects list --mine
carto projects list --search analytics
carto projects get "Q2 Analytics"
carto projects get "Q2 Analytics/Maps"
# Build out a project
carto projects create --name "Q2 Analytics" --color "#3478f6"
carto projects add "Q2 Analytics" --folder "Maps"
carto projects add "Q2 Analytics/Maps" --map 62c90ed4-eeec-46d0-bda9-c7ea173e26f0
carto projects add "Q2 Analytics" --workflow b32f9fff-4303-4f75-bf7a-1f661c60b53a
# Reorganize
carto projects rename "Q2 Analytics/Maps" --to "Production maps"
carto projects move "Q2 Analytics/Production maps" --to "Q1 Archive"
# Clean up
carto projects delete "Q2 Analytics" --yescarto admin batch-delete '{"resource_ids":["map1","map2","workflow1"]}'carto admin transfer '{
"from_user": "[email protected]",
"to_user": "[email protected]",
"resource_ids": ["map1", "workflow1"]
}'# Dump the current org settings to stdout
carto admin settings get
# Or write them to a file
carto admin settings get --out settings.json
# Preview what would change without writing
carto admin settings diff settings.json
cat settings.json | carto admin settings diff -
# Apply a bundle (per-section PATCH — only the sections present in the file are touched)
carto admin settings apply settings.json
carto admin settings apply --file settings.json
cat settings.json | carto admin settings apply -carto users get google-oauth2|123456789
carto users get [email protected]
carto users get <user-id> --json# Single user
carto users invite [email protected] --role Builder
# Default role is Viewer
carto users invite [email protected]
# Comma-separated
carto users invite [email protected],[email protected],[email protected] --role Builder
# Multiple arguments
carto users invite [email protected] [email protected] --role Viewercarto users invitations
carto users invitations --jsonSUM(female) / NULLIF(SUM(population), 0)SUM(female) / NULLIF(SUM(population), 0)
profiles — every saved profile keyed by name. Each entry holds:{
"current_profile": "production",
"profiles": {
"production": {
"token": "your-bearer-token",
"tenant_id": "gcp-us-east1",
"tenant_domain": "carto.acme.com",
"organization_id": "ac_yv1im1y2",
"organization_name": "carto-prod",
"user_email": "[email protected]"
},
"staging": {
"token": "staging-bearer-token",
"tenant_id": "gcp-us-east1",
"tenant_domain": "carto-dev.acme.com",
"organization_id": "ac_7p1sk0gs",
"organization_name": "Carto-Dev",
"user_email": "[email protected]"
}
}
}# Show full request details for any command
carto --debug maps list
# Combine with --json for clean output + visible request internals
carto --debug --json auth status# Authenticate via env var (useful in CI/CD)
export CARTO_API_TOKEN="eyJhbGc..."
carto maps list
# Override with CLI flags
carto --token "different-token" --base-url "https://eu-west1.api.carto.com" maps listcarto credentials list # All credentials
carto credentials list tokens # Only API tokens
carto credentials list spa # Only SPA OAuth clients
carto credentials list m2m # Only M2M OAuth clients# Single fully-qualified source
carto credentials create token \
--connection carto_dw \
--source "carto.shared.demo_table" \
--apis sql,maps
# Wildcard pattern (note: minimum two dot-separated segments before the wildcard)
carto credentials create token \
--connection carto_dw \
--source "carto.shared.CARTO_*" \
--apis sql,maps
# All sources on a connection, with expiry and a label
carto credentials create token \
--connection carto_dw \
--source "*" \
--apis sql,maps \
--name "demo-day-token" \
--expiration-date 7dcarto credentials create spa \
--title "My Web App" \
--callback "https://myapp.com/callback" \
--logout-url "https://myapp.com/logout" \
--web-origin "https://myapp.com" \
--allowed-origin "https://myapp.com"carto credentials create m2m --title "Backend Service"carto credentials get token <token-id>
carto credentials get spa <client-id>
carto credentials get m2m <client-id>carto credentials update token <token-id> --apis sql,maps
carto credentials update spa <client-id> --title "Updated Title"carto credentials delete token <token-id>
carto credentials delete spa <client-id>
carto credentials revoke m2m <client-id># Discover available filters (countries, categories, providers, licenses, etc.)
carto do filters # All filter values with dataset counts
carto do filters --json | jq '.categories' # Just categories (programmatic)
# Browse and search
carto do list --category demographics # Browse datasets by category
carto do list --country usa --limit 10 # Browse by country
carto do list --provider experian # Browse by provider
carto do list --license public # Filter by license type
carto do search "demographics united states" # Full-text search
carto do search "flood risk" --license public # Search with filters
# AI-powered semantic variable search (requires embeddings)
carto do search-variables "purchasing power" --country deu
carto do search-variables "population density" --limit 10
# Dataset details
carto do details <dataset-id> # Full dataset metadata
carto do sample <dataset-id> # Data sample + data dictionary
# Subscriptions (public datasets only — premium requires contacting sales)
carto do subscriptions # List your subscriptions
carto do subscribe <dataset-id> # Subscribe using catalog slug
carto do subscribe wp_population_29d72d59 # Resolves slug → creates BQ view
carto do subscribe <id> --filter "WHERE country_iso = 'US'" # Partial subscription
carto do subscribe <id> --columns "geoid, population, geom" # Specific columns only
carto do subscribe <id> --connection my-sf --destination db.tbl # Subscribe + transfer
carto do unsubscribe <dataset-id> # Remove a subscription
carto do unsubscribe <dataset-id> --yes # Skip confirmation









carto aifeature aiagent <map-id># Interactive multi-turn conversation
carto aifeature aiagent <map-id>
# Example session:
# You: What are the traffic patterns in this area?
# Assistant: Based on the data, I can see...
# You: Show me the collision hotspots
# Assistant: Here are the areas with highest collisions...
# You: exit
# One-shot mode
carto aifeature aiagent <map-id> "What are the traffic patterns?"
# Continue a previous conversation
carto aifeature aiagent <map-id> "Tell me more" --conversation-id abc123
# Read message from a file
carto aifeature aiagent <map-id> --file test-query.txt
# Pipe via stdin
echo "Analyze the collision data" | carto aifeature aiagent <map-id>
# JSON output
carto aifeature aiagent <map-id> "Summarize the data" --jsoncarto activity query# Simple count
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 \
--sql "SELECT COUNT(*) as total_events FROM activity"
# Maps created per user with email
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 --sql "
SELECT
CAST(a.ts AS DATE) as date,
u.email,
COUNT(*) AS created_maps
FROM activity a
JOIN userList u ON json_extract_string(a.data, '$.userId') = u.user_id
WHERE a.type = 'MapCreated'
GROUP BY date, u.email
ORDER BY created_maps DESC
LIMIT 10
"
# Force fresh download
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 --no-cache \
--sql "SELECT type, COUNT(*) FROM activity GROUP BY type ORDER BY COUNT(*) DESC"
# JSON output
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 --json \
--sql "SELECT COUNT(*) FROM activity"New features and improvements introduced from July to September 2025



































carto aiproxy infoCARTO LiteLLM Proxy Configuration
API Mode: OpenAI Compatible
API Host: https://litellm-gcp-us-east1.api.carto.com
API Base URL: https://litellm-gcp-us-east1.api.carto.com/v1
API Key: eyJhbGciOiJSUzI1NiIs...
Endpoints:
Chat completions: /v1/chat/completions
Completions: /v1/completions
Embeddings: /v1/embeddings
Models: /v1/modelscarto aiproxy models# Simple chat
carto aiproxy chat "What is 2+2?" --model gpt-4
# With a system prompt
carto aiproxy chat "Analyze this data pattern" \
--model gemini-2.5-flash \
--system "You are a geospatial data analyst"
# Control generation parameters
carto aiproxy chat "Write a haiku about maps" \
--model gpt-4 \
--temperature 1.5 \
--max-tokens 100
# Read message from a file
carto aiproxy chat --file prompt.txt --model gpt-4
# Pipe via stdin
echo "Explain quantum physics simply" | carto aiproxy chat --model gpt-4
# JSON output
carto aiproxy chat "Hello" --model gpt-4 --jsonSUM(female) / NULLIF(SUM(population), 0)# Export all categories
carto activity export --start-date 2025-10-01 --end-date 2025-10-07
# Export as Parquet (smaller files, faster queries)
carto activity export --start-date 2025-10-01 --end-date 2025-10-07 --format parquet
# Export only the activity category
carto activity export --start-date 2025-10-01 --end-date 2025-10-07 --category activity
# Custom output directory
carto activity export --start-date 2025-10-01 --end-date 2025-10-07 --output-dir ~/exports# Interactive browser-based login (recommended)
carto auth login
# Login to a named profile
carto auth login staging# Standard organization name
carto auth login --organization-name production
# Organization name with spaces (requires quotes)
carto auth login --organization-name "ACME Corporation"
# Save to a specific profile
carto auth login acme-prod --organization-name "ACME Corporation"carto auth status # Status of the current profile
carto auth status production # Status of a named profile$ carto auth status
✓ Authenticated
Current profile: my-org/[email protected] (default)
Token source: credentials
Token: eyJhbGciOiJSUzI1NiIs...
Expiration: 23/10/2025, 12:42:45
Time remaining: (in 18 hours)
Status: 🟢 Valid
Tenant: clausa.app.carto.com (gcp-us-east1)
Organization: my-org (ac_abc123)
User: [email protected]⚠️ Warning: Token is expiring soon
Less than 10% of token lifetime remaining
Consider re-authenticating to avoid interruptions:
carto auth login my-profilecarto auth logout # Logout from the current profile
carto auth logout staging # Logout from a named profile# Login to multiple profiles
carto auth login # Auto-suggests: tenant_id/org_name/[email protected]
carto auth login staging
carto auth login production
# Switch the current default profile
carto auth use production
carto auth use staging
# Use a specific profile for a single command (overrides default)
carto --profile staging maps list
carto --profile production workflows list
# List all profiles and the current default
carto auth status
# Logout removes only that profile
carto auth logout stagingNew features and improvements introduced from July to September 2023






















ordergroupSELECT "myColumn", "Revenue_2024" FROM "MySchema"."SalesData"SELECT "MyColumn", "Revenue_2024" FROM "public"."SalesData"SELECT myColumn, Revenue_2024 FROM `project.dataset.SalesData`SELECT myColumn FROM `my-catalog`.schema.sales_dataSELECT "myColumn", "Revenue_2024" FROM SCHEMA_NAME."SalesData"async_workflow_job_get_status_v1_0_0({
jobId: "abc-123",
connectionName: "carto_dw"
})async_workflow_job_get_results_v1_0_0({
jobId: "abc-123",
providerId: "bigquery",
connectionName: "carto_dw",
workflowOutputTableName: "my_project.results.trade_areas"
}){
"status": 200,
"data": {
"jobId": "abc-123",
"connectionName": "carto_dw",
"providerId": "bigquery",
"status": "running",
"error": null,
"createdAt": "2024-06-20T14:30:00.000Z"
}
}{
"status": 200,
"data": {
"rows": [
{
"store_id": 1,
"name": "Madrid Centro",
"trade_area_geom": "POLYGON((-3.71 40.41, ...))",
"drive_time_min": 10
},
{
"store_id": 2,
"name": "Madrid Norte",
"trade_area_geom": "POLYGON((-3.69 40.48, ...))",
"drive_time_min": 10
}
],
"schema": [
{ "name": "store_id", "type": "INT64" },
{ "name": "name", "type": "STRING" },
{ "name": "trade_area_geom", "type": "GEOGRAPHY" },
{ "name": "drive_time_min", "type": "INT64" }
]
}
}



































New features and improvements introduced from April to June 2026










































quadbin module provides the equivalent set of functions for the Quadbin grid.SUM(female) / NULLIF(SUM(population), 0)pickable and a getTooltip expression is provided). The legend is not part of the map widget itself. When the MCP client supports inline UI artifacts, the agent renders the legend as a separate artifact directly underneath the map.list_maps({ search: "retail stores" })
// → returns a map with id "a1b2c3d4-e5f6-..."
load_builder_map({ mapId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" })















Frequently Asked Questions about the CARTO platform and its components.
New features and improvements introduced from July to September 2022

@@function@@=

view_map({
deckglProps: {
initialViewState: { latitude: 20, longitude: 0, zoom: 2 },
mapStyle: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
layers: [{
"@@type": "VectorTileLayer",
id: "places",
pickable: true,
data: {
"@@function": "vectorTableSource",
connectionName: "carto_dw",
tableName: "carto-demo-data.demo_tables.populated_places"
},
getFillColor: [255, 100, 50],
pointRadiusMinPixels: 3
}],
getTooltip: "@@=object && '<b>' + object.properties.name + '</b>'"
}
})view_map({
deckglProps: {
initialViewState: { latitude: 54, longitude: -2.5, zoom: 5.5 },
mapStyle: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
layers: [{
"@@type": "HeatmapTileLayer",
id: "uk-solar",
data: {
"@@function": "h3QuerySource",
connectionName: "carto_dw",
sqlQuery: "SELECT `carto-un`.carto.H3_FROMGEOGPOINT(geom, 9) AS h3, COUNT(*) AS n FROM `dataset.uk_solar_panels` WHERE geom IS NOT NULL GROUP BY 1",
aggregationExp: "SUM(n) AS n"
},
getWeight: "@@=properties.n",
radiusPixels: 25,
colorRange: [[255,255,178,0], [254,217,118,160], [254,178,76,200], [253,141,60,220], [240,59,32,240], [189,0,38,255]]
}]
}
}){
"content": [
{
"type": "text",
"text": "Displaying ad-hoc deck.gl visualization on an interactive map."
}
]
}carto workflows list [options] # List workflows
carto workflows get <id> # Pretty details; --json = round-trippable bundle
carto workflows create [--file <bundle.json>] # Create from a bundle
carto workflows update <id> [--file <bundle.json>] # Update (partial bundles OK)
carto workflows delete <id> # Delete workflow
carto workflows copy <id> --dest-profile <name> # Duplicate (cross-tenant or same-tenant)
carto workflows schema [section] # JSON Schema reference for agents
carto workflows validate [--file <bundle.json>] # Tier-0 offline (Zod-only) bundle check
carto workflows verify-remote <id|--file …> --connection <c> # Tier-0 + Tier-2 deep validation against a warehouse
carto workflows to-sql [--file <bundle.json>] # Compile bundle → SQL preview (what `run` would submit)
carto workflows components list # Agent-facing component catalog
carto workflows components get <names> # Full input/output signature for components
carto workflows run <id> # Execute workflow; returns per-node outputs
carto workflows run output <id> <node-id> # Fetch a node's output rows
carto workflows run status <job-id> # Poll an async-submitted run
carto workflows share <id> [--org | --with <email>] # Share workflow
carto workflows unshare <id> # Revert to private
carto workflows mcp publish|unpublish|describe|list # MCP tool lifecycle
carto workflows schedule add|update|remove <id> # Warehouse cron lifecycle
carto workflows extensions install --file <ext.zip> --connection <name> # Install an extension zipcarto workflows get abc123 --json > /tmp/wf.json
jq '.title = "New title"' /tmp/wf.json | carto workflows update abc123 --file -# Create from a bundle
carto workflows create --file my-pipeline.json
# Update + verify post-write
carto workflows update abc123 --file pipeline.json --verify# Offline structural check
carto workflows validate --file bundle.json
# Full warehouse-side check
carto workflows verify-remote --file bundle.json --connection carto_dw
# Same, but fail on advisory warnings (CI gates)
carto workflows verify-remote --file bundle.json --connection carto_dw --strictcarto workflows to-sql --file bundle.json# Browse native components
carto workflows components list --connection carto_dw --group Joins
# Full signatures (for agent composition)
carto workflows components get native.customsql,native.joinv2 --connection carto_dw --json
# Include input-format reference entries
carto workflows components get native.customsql --connection carto_dw --input-formatscarto workflows run <id> # Run synchronously; returns per-node outputs
carto workflows run <id> --async # Return immediately with a job ID
carto workflows run status <job-id> # Poll the async job
carto workflows run output <id> <node-id> # Fetch a specific node's output rows# Share with the whole organization
carto workflows share <id> --org
# Share with a specific user (email → user-id lookup is automatic)
carto workflows share <id> --with [email protected]
# Revert to private
carto workflows unshare <id>carto workflows mcp publish <id> [options] # Expose this workflow as an MCP tool
carto workflows mcp unpublish <id> # Remove from MCP catalog
carto workflows mcp describe <id> # Show current MCP tool registration
carto workflows mcp list # List all workflows published as MCP toolscarto workflows schedule add <id> --cron "0 6 * * *"
carto workflows schedule update <id> --cron "0 6 * * 1-5"
carto workflows schedule remove <id># Auto-map by name
carto workflows copy abc123 --dest-profile production
# Explicit connection
carto workflows copy abc123 \
--source-profile staging \
--dest-profile production \
--connection prod-bigquerycarto workflows extensions install --file my-extension.zip --connection carto_dw# List ETL workflows, recently updated first
carto workflows list --search "ETL" --order-by updated_at
# Round-trip get → edit → update
carto workflows get abc123 --json > /tmp/w.json
jq '.title = "New title"' /tmp/w.json | carto workflows update abc123 --file -
# Local validation before write
carto workflows validate --file bundle.json
# Full warehouse-side verification before merging a bundle PR
carto workflows verify-remote --file bundle.json --connection carto_dw
# Preview the SQL `run` would submit
carto workflows to-sql --file bundle.json
# Publish as MCP tool so agents can call it
carto workflows mcp publish abc123











carto maps list [options] # List maps
carto maps get <map-id> # Pretty details; --json emits round-trippable JSON
carto maps create [json] # Create from JSON (positional, path, or stdin)
carto maps update <map-id> [json] # Update (partial JSON OK)
carto maps validate [json] # Tier-1 preflight (offline, no API calls)
carto maps verify-remote [json] # Tier-0 + Tier-2 (validate + warehouse dry-runs)
carto maps publish <map-id> # Freeze a snapshot so viewers see current state
carto maps schema [section] # JSON Schema reference for agents
carto maps agents <subcommand> # AI agent introspection (see below)
carto maps datasets update <map-id> <dataset-id> # PATCH a single dataset on an existing map
carto maps screenshot <map-id> [options] # Save a PNG screenshot (opt-in Chromium)
carto maps copy <map-id> --dest-profile <name> # Duplicate (cross-org or same org)
carto maps delete <map-id> # Delete mapcarto maps get abc123 --json > map.json
jq '.title = "New title"' map.json | carto maps update abc123carto maps create '{"title":"…", "connectionId":"…"}' # Inline JSON
carto maps create ./map.json # Path
carto maps create < map.json # Stdinagentenumsmapstatemapstylemapsettingsuistatelegendsettingscarto maps publish abc123
# Or chain it onto an update:
carto maps update abc123 < map.json --publishcarto maps schema layer.h3
carto maps schema uistatecarto maps agents status # Is CARTO AI enabled? What's the default model?
carto maps agents models # AI models you can put in agent.config.model (formatted "{source}::{provider}::{model}")
carto maps agents mcp-tools # MCP tools (workflow-backed) available for agent.config.tools[]
carto maps agents core-tools # Hardcoded core Builder tools and their activation rulescarto maps datasets update <map-id> <dataset-id> '{"source":"SELECT … FROM new_table"}'# Auto-map connections by name (default)
carto maps copy <map-id> --dest-profile production
# Manual mapping for renamed connections
carto maps copy <map-id> --dest-profile prod \
--connection-mapping "dev-bq=prod-bq,dev-sf=prod-sf"
# Override source profile and title
carto maps copy <map-id> --source-profile staging --dest-profile prod \
--title "Production Map"carto maps screenshot abc123 -o map.png
carto maps screenshot abc123 --lat 40.42 --lng -3.70 --zoom 12 --hide-overlays
carto maps screenshot abc123 --render-engine fullcarto maps delete <map-id>
carto maps delete <map-id> --yes # Skip confirmation# Create from a bundle file
carto maps create < map.json
# Round-trip: get → edit → update
carto maps get abc123 --json > /tmp/map.json
jq '.title = "Q3 Dashboard"' /tmp/map.json | carto maps update abc123
# Validate locally (no network), then create
carto maps validate < map.json && carto maps create < map.json
# Update + publish in one go
carto maps update abc123 < shared.json --publish
# Agent introspection
carto maps agents status
carto maps schema layer.h3npm install playwright-core
npx playwright install chromium # ~300 MB
























# Interactive browser-based login using OAuth 2.0 + PKCE
carto auth login
# This will:
# 1. Display an authorization URL
# 2. Open your browser (you may need to copy/paste the URL)
# 3. Wait for you to complete the login process
# 4. Capture your access token and user information
# 5. Store credentials in ~/.carto_credentials.json
# 6. Configure the API URL based on your tenant
# Check authentication status
carto auth status
# Show current user information
carto auth whoami
# Returns: user_id, name, email, account info, roles
# Switch between profiles
carto auth use production
carto auth use staging# List all credentials
carto credentials list
carto credentials list tokens
# Create an API Access Token for your application
carto credentials create token \
--connection carto_dw \
--source "demo_tables.*" \
--apis sql,maps
# Create SPA OAuth Client for web applications
carto credentials create spa \
--title "My Dashboard" \
--callback "https://mydash.com/callback"
# Create M2M OAuth Client for backend services
carto credentials create m2m \
--title "ETL Service"
# Get token details
carto credentials get token <token-id>
# Delete a credential
carto credentials delete token <token-id># List maps with filters (enhanced display shows owner, privacy, views, tags)
carto maps list --search sales --page-size 20
# List only your maps
carto maps list --mine
# Pagination
carto maps list --page 1 --page-size 10
carto maps list --page 2 --page-size 10
# Fetch all pages automatically with --all
carto maps list --all
carto maps list --mine --all
carto workflows list --all --search "project"
# Get detailed info for a specific map
carto maps get 69b0e7cc-026a-4feb-87bb-a82cc6ac5189
# Output shows:
# - Map metadata (title, owner, privacy, views, collaborative, agent enabled)
# - Datasets and their connections
# - Map URL
# JSON output for scripting (or AI agents)
carto maps list --json | jq '.data[].id'
# Delete a map
carto maps delete map_abc123# Minimal bundle — title, connection, and one dataset rendered as a tileset layer
cat > stores.map.json <<'JSON'
{
"title": "Retail stores",
"connectionId": "12345678-1234-1234-1234-123456789abc",
"privacy": "private",
"datasets": [
{
"id": "stores-ds",
"type": "table",
"source": "carto-demo-data.demo_tables.retail_stores",
"connectionId": "12345678-1234-1234-1234-123456789abc"
}
],
"keplerMapConfig": {
"config": {
"visState": {
"layers": [
{
"id": "stores-layer",
"type": "tileset",
"config": {
"dataId": "stores-ds",
"label": "Stores",
"color": [255, 100, 50],
"visConfig": { "radius": 10 }
}
}
]
},
"mapStyle": { "styleType": "positron" }
}
}
}
JSON
# Validate locally (no network), then create
carto maps validate < stores.map.json
carto maps create < stores.map.json
# Or chain in one go
carto maps create ./stores.map.json --json | jq '.builderUrl'# Get the map as a round-trippable bundle, edit, and update
carto maps get abc123 --json > /tmp/map.json
jq '.title = "Q3 Dashboard"' /tmp/map.json | carto maps update abc123
# Update + publish in one call so shared/public viewers see the changes
carto maps update abc123 < /tmp/map.json --publish# Default light engine — layers + basemap, no widgets
carto maps screenshot abc123 -o map.png
# Recenter and hide chrome
carto maps screenshot abc123 --lat 40.42 --lng -3.70 --zoom 12 --hide-overlays
# Full CARTO Builder viewer (widgets, legends, popups) — heavier
carto maps screenshot abc123 --render-engine full# Minimal — pipeline that reads a table, filters it, and writes back
cat > cycle-pipeline.workflow.json <<'JSON'
{
"title": "Cycle network — existing routes only",
"connectionId": "12345678-1234-1234-1234-123456789abc",
"config": {
"schemaVersion": "1.0.0",
"connectionProvider": "bigquery",
"useCache": false,
"nodes": [
{
"id": "src",
"type": "source",
"data": {
"name": "ReadTable",
"inputs": [
{ "name": "source", "value": "demo_tables.bristol_cycle_network" }
]
},
"position": { "x": 100, "y": 100 }
},
{
"id": "filter",
"type": "generic",
"data": {
"name": "native.where",
"inputs": [
{ "name": "expression", "value": "r_status = 'Existing'" }
]
},
"position": { "x": 300, "y": 100 }
}
],
"edges": [
{
"id": "e1",
"source": "src",
"target": "filter",
"sourceHandle": "out",
"targetHandle": "source"
}
]
},
"tags": ["analytics", "cycle-data"]
}
JSON
# Validate offline (Zod-only, no warehouse calls), then create
carto workflows validate --file cycle-pipeline.workflow.json
carto workflows create --file cycle-pipeline.workflow.json
# Full warehouse-side check before merging the bundle to a repo
carto workflows verify --file cycle-pipeline.workflow.json --connection carto_dw--skip-source-validation# All Joins components for a BigQuery connection
carto workflows components list --connection carto_dw --group Joins
# Full input/output signatures for the components you'll use
carto workflows components get native.customsql,native.joinv2 --connection carto_dw --json# Execute the workflow
carto workflows run abc123
# Make it callable from the CARTO MCP Server (agents will see it as a tool)
carto workflows mcp publish abc123# Auto-map connections by name (default, recommended)
carto maps copy <map-id> --dest-profile <profile-name>
carto workflows copy <workflow-id> --dest-profile <profile-name>carto maps copy <map-id> --dest-profile <profile-name> \
--connection-mapping "dev-bq=prod-bq,dev-postgres=prod-postgres"carto workflows copy <workflow-id> --dest-profile <profile-name> \
--connection <connection-name># Auto-map (recommended)
carto maps copy abc123 --dest-profile production
# → Automatically maps: bigquery-dev → bigquery-dev, snowflake → snowflake
# Manual mapping for renamed connections
carto maps copy map456 \
--source-profile staging \
--dest-profile production \
--connection-mapping "bigquery-dev=bigquery-prod,snowflake-staging=snowflake-prod"
# Legacy: single connection for all datasets
carto maps copy xyz789 --dest-profile prod --connection prod-bigquery
# Combine options
carto maps copy map456 \
--dest-profile production \
--connection-mapping "dev-bq=prod-bq" \
--title "Production Sales Dashboard" \
--keep-privacycarto maps copy abc123 --dest-profile prod
# Source has: bigquery-dev, snowflake-analytics
# Destination has: bigquery-dev, snowflake-analytics
# ✅ Success — both auto-mapped by namecarto maps copy abc123 --dest-profile prod \
--connection-mapping "bigquery-dev=bigquery-prod,snowflake-analytics=snowflake-prod"
# ✅ Success — both manually mappedcarto maps copy abc123 --dest-profile prod --connection-mapping "old-conn=new-conn"
# Source has: old-conn, shared-connection
# Destination has: new-conn, shared-connection
# ✅ Success — old-conn mapped manually, shared-connection auto-mappedcarto maps copy abc123 --dest-profile prod
# Source has: bigquery-dev, snowflake-analytics
# Destination has: bigquery-dev only
# ❌ Fails with clear error:
# Missing connections in destination organization:
# • "snowflake-analytics" (used by 3 datasets)
# Solutions:
# 1. Create missing connections in destination
# 2. Use --connection-mapping to map to different namescarto maps copy abc123 --dest-profile prod --connection-mapping "dev-bq=prod-bq"
# Connections mapped successfully, but...
# ❌ Source validation failed - datasets cannot access their data sources:
# • "NYC Traffic" → my-project.dataset.traffic_table
# Error: Permission bigquery.tables.get denied on table (or it may not exist)
# Solutions:
# 1. Grant access to these tables in the destination connection
# 2. Ensure tables/views exist in the destination data warehouse
# 3. Use --skip-source-validation to create the map anywaycarto maps copy abc123 --dest-profile prod \
--connection-mapping "dev-bq=prod-bq" \
--skip-source-validation
# ✅ Success — map created but datasets won't load data until access is fixed# View organization statistics and quotas
carto org stats
# Example output:
# === Organization Statistics ===
#
# Users
# Total users: 184
# Editor users: 179
# Viewer users: 1
# Superadmin users: 2
# API Access Tokens: 2,374
#
# Resources
# Maps: 3,792 (2,897 public)
# All users maps: 13,624
# Workflows: 872
# Connections: 569
# Applications: 201
#
# Usage & Quotas
# Usage quota: 7,702,490
# LDS credits: 1,069,663 of 15,000,000 (7%)
# Map loads: 53,194
#
# AI Quotas
# Builder Gen AI: 0 of 250 threads
# AI Agents tokens: 292,187 available
# JSON output for scripting
carto org stats --json# List all users
carto users list
# Filter by role
carto users list --role Builder
carto users list --role Viewer --all
# Search for specific users
carto users list --search "john"
carto users list --search "@company.com"
# Get detailed info (by user ID or email)
carto users get google-oauth2|123456789
carto users get [email protected]
# Invite a single user
carto users invite [email protected] --role Builder
# Invite multiple users at once
carto users invite [email protected],[email protected] --role Viewer
# Check pending invitations
carto users invitations
# JSON output for automation
carto users list --json | jq '.[] | {email, roles: .app_metadata.roles}'# Simple count
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 \
--sql "SELECT COUNT(*) as total_events FROM activity"
# Maps created per user, joined with userList for emails
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 --sql "
SELECT
CAST(a.ts AS DATE) as date,
u.email,
COUNT(*) AS created_maps
FROM activity a
JOIN userList u ON json_extract_string(a.data, '$.userId') = u.user_id
WHERE a.type = 'MapCreated'
GROUP BY date, u.email
ORDER BY created_maps DESC
LIMIT 10
"
# User activity by role
carto activity query --start-date 2025-10-01 --end-date 2025-10-07 --sql "
SELECT u.email, u.role, COUNT(*) as events
FROM activity a
JOIN userList u ON json_extract_string(a.data, '$.userId') = u.user_id
GROUP BY u.email, u.role
ORDER BY events DESC
"
# Export raw files for loading into your warehouse
carto activity export --start-date 2025-10-01 --end-date 2025-10-07 --format parquet# Interactive multi-turn conversation
carto aifeature aiagent <map-id>
# One-shot
carto aifeature aiagent <map-id> "What are the traffic patterns?"
# Continue a previous conversation
carto aifeature aiagent <map-id> "Tell me more" --conversation-id abc123
# Pipe a message
echo "Analyze the collision data" | carto aifeature aiagent <map-id>
# JSON for automation / CI agent quality tests
carto aifeature aiagent <map-id> "Summarize the data" --jsoncolorCategories: use the returned categories.list_connections()// First call: list top-level projects
list_resources({ connection_name: "carto_dw" })
// Second call: drill into a dataset and expand tables
list_resources({
connection_name: "carto_dw",
fqn: "my_project.retail_data",
maxDepth: 2
})search_resources({
connection_name: "carto_dw",
query: "stores",
scopeFqn: "my_project.retail_data"
}){
"source": { "type": "table", "fqn": "..." }, // or { "type": "query", "sql": "..." }
"schema": [{ "name": "pop_max", "type": "Number" }, ...],
"geomField": "geom", // optional — present when the source has a geometry column
"geometryType": "Point", // optional — "Point" | "LineString" | "Polygon"
"rowCount": 12345 // optional
}describe({
connection_name: "carto_dw",
table_fqn: "carto-demo-data.demo_tables.populated_places"
})
// → { source, schema: [...], geomField: "geom", geometryType: "Point", rowCount: 7322 }describe({
connection_name: "carto_dw",
table_fqn: "carto-demo-data.demo_tables.populated_places",
column: "pop_max"
})
// → { type: "Number", min: 0, max: 30000000, quantiles: { 4: [0, 5000, 50000, 250000, 30000000] } }
// Drop the first and last (natural extremes); use the inner three as colorBins domain.describe({
connection_name: "carto_dw",
query: "SELECT name, COUNT(*) AS n FROM carto-demo-data.demo_tables.populated_places GROUP BY name"
})
// → { source: { type: "query", sql: "..." }, schema: [{ name: "name", type: "String" }, { name: "n", type: "Number" }] }list_maps({ mine_only: true, page_size: 5 })














SUM(female) / NULLIF(SUM(population), 0)



























































































