How to Automate Catalog Imports and Exports with the Acenda API
Use Acenda’s Import and Export API to keep catalog, inventory, pricing, and other marketplace data in sync automatically. This is ideal for running scheduled updates from an ERP, PIM, warehouse system, vendor feed, or custom script without ever logging into the Acenda UI.
Guide Overview
This article covers the following automation workflows:
Importing data into Acenda
Exporting data from Acenda
Previewing files before import
Monitoring background jobs
Downloading error reports
Using profiles to map column names
Frequently Asked Questions
What can I automate with the Import and Export API?
You can automate two main background workflows. The initial API request kicks off the job, and your automation should poll it until it finishes.
1. Import Data into Acenda
Use this flow to update catalog data, inventory, pricing, promotions, tracking, kit components, or channel mappings.
The Workflow: Upload file for preview → Review parsed headers & sample rows → Adjust/reparse if needed → Finalize preview to start import → Poll until complete → Download error report if rows failed.
2. Export Data from Acenda
Use this flow to download current Acenda data for reporting, reconciliation, backups, templates, or downstream systems.
The Workflow: Create export job → Poll until complete → Download the finished file.
What do I need before using the API?
Before you begin, ensure you have:
A service account with a
client_idandclient_secret.The correct API scopes assigned to that service account.
Your Acenda organization identifier (the org slug).
⚠️ Important: Your organization identifier must be sent on every API request using the following header: X-Astur-Organization: your-org-slug. Additionally, the same service account that creates an import preview must be used to manage, finalize, or cancel it.
How do I authenticate?
Acenda uses OAuth2 client credentials authentication. Send a POST request to the token endpoint:
[https://login.acenda.io/auth/realms/acenda/protocol/openid-connect/token](https://login.acenda.io/auth/realms/acenda/protocol/openid-connect/token)
Example Request:
Bash
TOKEN_RESPONSE="$(curl -sS -X POST \ "https://login.acenda.io/auth/realms/acenda/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=client_credentials" \ --data-urlencode "client_id=$CLIENT_ID" \ --data-urlencode "client_secret=$CLIENT_SECRET" \ --data-urlencode "scope=openid" )" TOKEN="$(printf '%s' "$TOKEN_RESPONSE" | jq -r '.access_token')"
Include the returned access token in the header of your subsequent API requests:
Authorization: Bearer your-access-token
💡 Tip: Tokens are short-lived. For scheduled or long-running jobs, request a fresh token at the start of each major step or whenever the API returns a 401 status code.
What headers are required on API requests?
Most API requests should include:
HTTP
Authorization: Bearer your-access-token X-Astur-Organization: your-org-slug Content-Type: application/json
Note: For file uploads, do not manually set Content-Type. Allow curl -F or your HTTP client to automatically set the multipart boundary.
What is the base API URL?
Use the following base URL: [https://api.acenda.io/v1](https://api.acenda.io/v1)
There is no tenant-specific subdomain. Your organization is automatically routed via the X-Astur-Organization header.
Which file formats are supported?
Imports and exports support: .csv, .csv.gz, .xlsx, and .xlsx.gz.
Size Limit: For imports, the maximum upload size is 500 MB.
XLSX Constraint: Acenda reads only the first sheet. If the workbook contains multiple sheets, the preview response will include a sheet warning.
Supported Data Types
Import Types
Import Type | Use Case |
| Product catalog data (most common) |
| Inventory quantities and warehouse-level inventory |
| Channel listing mappings |
| Channel-specific SKU presentation data |
| Promotional pricing |
| Custom pricing records |
| Shipment tracking updates |
| Kit component relationships |
Export Types
Export Type | Use Case |
| Product catalog data |
| Inventory quantities and warehouse-level inventory |
| Channel listing mappings |
| Channel-specific SKU presentation data |
| Promotional pricing |
| Custom pricing records |
| Kit component relationships |
Note: Tracking currently does not support an export type.
The Import Process Step-by-Step
Step 1: Upload the file for preview
The preview flow helps you validate data before Acenda applies changes.
Bash
PREVIEW="$(curl -sS -X POST \ "$BASE/import_preview/catalog?skip_rows=0" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" \ -F "file=@./catalog.csv" )" TOKEN_ID="$(printf '%s' "$PREVIEW" | jq -r '.result.token')"
Preview Response Breakdown
Field | Meaning |
| Preview token used to manage, finalize, or cancel the preview |
| When the preview expires |
| Header row parsed from the file |
| Sample rows from the file for validation |
| Header validation problems |
| Number of non-empty data rows |
| Number of valid image URLs found for catalog image columns |
| Present only after the preview has been finalized |
⏳ Limits: Preview files expire after 24 hours. Each organization can have a maximum of 50 active, unfinalized previews at one time.
Step 2: Validate the Preview
Before finalizing, verify the following fields in the response:
raw_header: Confirms Acenda found the correct header row.preview_rows: Confirms data maps visually to the right fields.header_errors: Checks for invalid/unmapped columns. Do not finalize if this contains errors unless you are using an import profile to map them.total_lines&image_count: Verifies row count and image URL health.
Handling Shifted Headers
If your header row is not the first row, use the skip_rows parameter to reparse without re-uploading:
Bash
curl -sS -X POST \ "$BASE/import_preview/catalog/$TOKEN_ID/reparse" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" \ -H "Content-Type: application/json" \ -d '{"skip_rows": 2}'Step 3: Finalize the Import
Finalizing creates the actual background processing job.
Bash
FINALIZE="$(curl -sS -X POST \ "$BASE/import_preview/catalog/$TOKEN_ID/finalize" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" \ -H "Content-Type: application/json" \ -d '{ "upsert": true, "skip_unmatched": false, "delete": false, "delay": 0 }' )" IMPORT_ID="$(printf '%s' "$FINALIZE" | jq -r '.result[0].id')"Finalize Configuration Options
profile: Import profile ID for custom column mapping.upsert: Updates matching records and creates missing records where supported.skip_unmatched: Skips rows that do not match an existing record.delete: Type-specific delete mode. (Do not use for catalog automation unless confirmed compatible by Acenda support).delay: Seconds to wait before processing (max 60).
💡 Tip: Finalization is safe to retry. If the import job was already successfully triggered, Acenda returns the existing import details instead of creating a duplicate job.
Step 4: Monitor & Check Status
Poll the import record until done returns true.
Bash
curl -sS "$BASE/catalog/import/$IMPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Monitoring Fields to Watch
done: Becomestruewhen processing finishes completely.progress/total_lines: Tracks row progress.completed_lines/skipped_lines/deleted_lines: Post-import counters.error_report_path: Provided if a downloadable error report is available.
Step 5: Download Error Reports (If Applicable)
If your completed import returns an error_report_path, download the log using:
Bash
curl -L -o "catalog_import_errors.csv" \ "$BASE/download/error_report/catalog/$IMPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Note: If no errors occurred, this endpoint returns a 404 status code.
Canceling a Preview
If you need to reject a file preview and start over, explicitly delete it:
Bash
curl -sS -X DELETE \ "$BASE/import_preview/catalog/$TOKEN_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Returns a 204 No Content response upon success.
Formatting Data Columns
Standard Catalog Columns
Catalog imports use lowercase, case-sensitive column names. The easiest setup template is achieved by exporting your data type first and copying its header row.
Column Name | Description |
| Product or variant unique SKU |
| Product name |
| Product structural type: |
| Product barcodes and unique identifiers |
| Link child variants to parent products |
| Variant option configuration values |
| Product selling price configuration |
| Manufacturer's Suggested Retail Price |
| Minimum Advertised Price mapping |
| Product image asset URLs |
| Custom metadata attributes |
Custom Fields (fields.*)
Custom fields must use keys prefixed with fields.. Only catalog, channel_item_mapping, and custom_pricing import types support these columns.
Example CSV Format:
Code snippet
sku,fields.brand,fields.weight.value,fields.weight.unit SKU-1001,Acme,2.5,lb SKU-1002,Acme,0.8,kg
💡 Tip: For unit-based custom fields (like weight, dimensions, or volume), separate the metrics into fields.<name>.value and fields.<name>.unit. If you omit the .unit column, Acenda falls back to your catalog's default unit settings.
Catalog Images (images.*)
Image fields ingest publicly accessible asset URLs.
Example CSV Format:
Code snippet
sku,images.default.main.url,images.default.swatch.url,images.default.1.alternate.url SKU-1001,https://cdn.example.com/main.jpg,https://cdn.example.com/swatch.jpg,https://cdn.example.com/side.jpg
⚠️ Warning: When importing via upsert, image column values replace the product's live image stack completely. If you omit an existing image from the row, it will be removed. To leave a product's current image assets untouched, completely omit all images.* columns from your import file.
Import and Export Profiles
Profiles map your system’s unique column naming conventions to Acenda's required field nomenclature. Use this if your raw files originate directly from an ERP, PIM, or warehouse vendor feed.
Creating an Import Profile
Bash
curl -sS -X POST "$BASE/import_profile" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" \ -H "Content-Type: application/json" \ -d '{ "name": "Vendor catalog feed", "import_type": "catalog", "mappings": [ {"source": "Item #", "target": "sku"}, {"source": "Title", "target": "name"}, {"source": "Retail Price", "target": "pricing_item.price.amount"} ] }'Applying the Profile to an Import
Reference the profile ID when executing your finalization step. The preview response will show your file's original columns, but the mappings will execute upon processing:
Bash
curl -sS -X POST \ "$BASE/import_preview/catalog/$TOKEN_ID/finalize" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" \ -H "Content-Type: application/json" \ -d '{"profile": 42, "upsert": true}'The Export Process Step-by-Step
Step 1: Create the Export Job
Exports run asynchronously. Start the job by calling the endpoint:
Bash
EXPORT="$(curl -sS -X POST \ "$BASE/catalog/export" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG" )" EXPORT_ID="$(printf '%s' "$EXPORT" | jq -r '.result.id')"
Step 2: Poll Export Job Status
Query the export instance ID until done matches true.
Bash
curl -sS "$BASE/catalog/export/$EXPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Key Export Fields
done:truewhen execution is complete.estimate_count/actual_count: Output record tallies.path: The relative path string required to fetch your file.
Step 3: Download the Export File
Extract the exact path value returned by the status response to pull down your final document. Do not manually format this string yourself.
Bash
DOWNLOAD_PATH="$(printf '%s' "$STATUS" | jq -r '.result.path')" curl -L -o "catalog_export.csv" \ "$BASE/download/$DOWNLOAD_PATH" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Filtering Export Outputs
Filter your data by supplying a URL-encoded MongoDB-style filter to the query parameter.
Example (Filtering inventory for warehouse ID 12):
Bash
curl -sS -X POST \ "$BASE/inventory_detail/export?query=%7B%22warehouse_id%22%3A12%7D" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Astur-Organization: $ORG"
Note: If no matching records are found for your filter, the API returns an error instead of an empty document.
API Scopes and Error Handling
Required Access Scopes
Scope | Intended Use Case |
| Create, reparse, finalize, or cancel file previews |
| Read import logs and download failed rows reports |
| Manage shared Import Profiles |
| Trigger export jobs, monitor progress, and access generated paths |
| Manage shared Export Profiles |
| Standard permission needed to stream down the final export files |
💡 Tip: Creating a raw data data export job requires exports:read, not exports:create. The exports:create scope is explicitly reserved for structural Export Profile creations.
Common API Error Statuses
400Bad Request: Invalid profile syntax, bad payload type mapping, or header structures failed validation.401Unauthorized: Token is missing, incorrectly structured, or expired.403Forbidden: Authenticated user lacks the designated scopes for this action.404Not Found: Target resource doesn't exist (or error logs are clear of failed records).409Conflict: Triggered if a preview state is already transitioning or finalizing.410Gone: The target preview instance has passed its 24-hour expiration window.429Too Many Requests: Hit the systemic limit of 50 active, unfinalized file previews. Clean up stale jobs viaDELETE.
Best Practices & Standard Automation Flows
Developer Recommendations
Safety First: Always use the preview endpoints to validate files before pushing records to live catalog fields.
Fail-Fast Coding: Program automation tasks to halt immediately if
header_errorsis populated (unless verified profiles are explicitly managing translation logic).State Alignment: Ensure a single service account runs the entire lifecycle thread of a single preview-to-import event sequence.
Polite Polling: Implement progressive backoff loops when tracking
done: trueflags; do not bombard endpoints with rapid-fire loops.Robust Logging: Capture and store every unique token ID, file name, import/export ID, and final response status inside your application logs to simplify remote debugging.
Recommended Nightly Catalog Sync Workflow
Authenticate: Request an OAuth2 access token using your service account credentials.
Upload Preview: Push your catalog payload file to the
/import_preview/catalogendpoint.Validate Headers: Inspect the preview response payload for the presence of
header_errors.If errors are present: Cancel the preview (
DELETE) and alert your system administrators via webhook (e.g., Slack/PagerDuty).If headers are clean: Proceed and finalize the preview by sending
{"upsert": true}.
Monitor Job: Poll the
/catalog/import/{id}status endpoint using a progressive backoff interval.Evaluate Completion: Wait until the API returns
done: true, then inspect the final job counters.If row failures are found: Download the error report from the path provided and exit your script with a non-zero status code (
Code 1) to trigger a system alert.If processed cleanly: Log the final success metrics and safely close out the pipeline run.
This pattern maps reliably to standard scheduling utilities like system cron, Kubernetes CronJobs, or continuous integration pipelines.