Index Export/Import API
Export and import index metadata for backup, migration, audit, and index forking.
Architecture
Both export and import live in admin_lambda:
admin_lambda/
├── routes/
│ ├── export_routes.py # GET endpoints for each category + /all
│ └── import_routes.py # POST /all to apply exported data
└── models/
└── export_models.py # Pydantic response models shared by export and import
Export routes serialize canonical persistence records (IndexSettings, QuerySearchConfigRecord, merchandising models, etc.) directly into JSON. There is no separate collector or orchestrator layer — each route fetches data via FastAPI dependency injection and wraps it in a response envelope.
Import accepts the output of GET /export/all and applies it to a target index.
Export Endpoints
All export routes are mounted at:
GET /api/v1/admin/accounts/{system_account_id}/indexes/{index_name}/export/<category>
| Endpoint | Description |
|---|---|
/configs |
Serialized IndexSettings record (search, collections, add docs, agentic config) |
/aliases |
Serialized IndexSettings record (alias configuration) |
/infra |
Control-plane index record |
/queries |
Query config records + redirect records |
/merchandising |
Merchandising config, view records, and global rules records |
/feature-flags |
IndexSettings record + static feature flags |
/pixel |
IndexSettings record (pixel configuration) |
/all |
All categories above, fetched in parallel via ThreadPoolExecutor |
Each single-category endpoint returns { metadata, data } where data is category-specific.
The /all endpoint returns { metadata, data: { configs, aliases, infra, queries, merchandising, feature_flags, pixel } }.
Categories
| Category | Data Source | Importable? |
|---|---|---|
configs |
IndexSettings record | Yes — imports create_index_config, search_config, collections_config, add_docs_config, agentic_config |
aliases |
IndexSettings record | Yes — imports index_aliases |
infra |
Control-plane index record | No (export-only, informational) |
queries |
QuerySearchConfigRecord list |
Yes — re-keys to target index |
merchandising |
Config + views + global rules | Yes — re-keys to target index |
feature-flags |
IndexSettings + static flags file | Yes — imports feature_flags |
pixel |
IndexSettings record | Yes — imports pixel_id |
Examples
Full export:
curl -X GET \
"https://admin.example.com/api/v1/admin/accounts/acc-123/indexes/products/export/all"
Single category:
curl -X GET \
"https://admin.example.com/api/v1/admin/accounts/acc-123/indexes/products/export/queries"
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 404 | Index not found |
| 500 | Internal server error (infra fetch failure reported in metadata.warnings) |
Import Endpoint
POST /api/v1/admin/accounts/{system_account_id}/indexes/{index_name}/import/all
Accepts a FullExportResponse body (the output of GET /export/all) and applies it to the target index.
Requires SuperAdmin authorization.
What gets imported
| Source | Imported fields |
|---|---|
configs |
create_index_config, search_config, collections_config, add_docs_config, agentic_config |
aliases |
index_aliases |
feature-flags |
feature_flags |
pixel |
pixel_id |
queries |
All QuerySearchConfigRecord entries, re-keyed with target pk/sk and kv_key |
merchandising |
Config record, view records, and global rules records, re-keyed with target system_account_id/index_name |
What does NOT get imported
infra— control-plane records are informational only- Static feature flags — derived from the flags file, not from the export
Preflight conflict checks
Before applying any changes, the import checks the target index for existing resources:
| Resource | Conflict condition |
|---|---|
query_configs |
Target has any query config records |
redirects |
Target has any redirect records |
merchandising_config |
Target has a merchandising config |
merchandising_rules |
Target has any views or global rules |
aliases |
Target has any alias configuration (including legacy read_alias / index_write_aliases) |
If any conflicts exist, import returns 409 with existing_resources and resource_counts.
Apply and rollback behavior
Import applies changes in this order:
- Query configs — inserted with
attribute_not_existscondition to prevent races, then artifact sync triggered - Index settings — bulk update of all importable fields
- Merchandising — config, views, and global rules written individually
If any step fails, previously imported query configs are rolled back (deleted via QueryConfigsService.delete_query_configs). Index settings and merchandising changes are not rolled back — a failure at those stages returns 500 with both the error and any rollback error.
Imported query configs are tagged with updated_by: "admin_import" and change_reason: "Imported from {source_account}/{source_index}".
Response
{
"status": "ok",
"imported_categories": ["configs", "aliases", "queries", "merchandising", "feature-flags", "pixel"],
"skipped_categories": ["infra"]
}
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Import succeeded |
| 400 | Invalid record in payload (with record_index and error) |
| 404 | Target index not found |
| 409 | Target has existing resources (with resource_counts) |
| 500 | Import failed (may include rollback_error) |
Contract rules
Export and import are a paired contract. Key rules (from admin_lambda/routes/AGENTS.md):
- Changes to export models must be reviewed against import handling (and vice versa)
- The round-trip E2E test must stay in sync:
components/shopify/e2e_tests/e2e_tests/tests/ecom_import_export_test.py - Infra is intentionally export-only — never add import handling for it
- All export data is serialized canonical persistence records, not custom projections
Adding a new export category
- Add
*ExportDataand*ExportResponsemodels toadmin_lambda/models/export_models.py(useConfigDict(frozen=True)) - Add the field to
FullExportData - Add a
GET /<category>route inexport_routes.pyusing FastAPIDepends()for data access - Add the category to the
/allroute (useThreadPoolExecutorfor IO-bound fetches) - If importable: add preflight conflict check, apply logic, and rollback handling in
import_routes.py - Update the round-trip E2E test
- Update these docs
See Export/Import Schema for response model details.