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
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.
Prefer not to write code? A Recurring Import (under DATA TRANSFERS > Imports > Recurring Imports) pulls a file from your own SFTP on a schedule, and a Scheduled Export (DATA TRANSFERS > Scheduled Exports) pushes one out the same way — both skip this API entirely. If you'd rather point an AI assistant at Acenda instead of scripting requests, see How to connect your AI assistant to Acenda.
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).
Create the service account yourself under ADMINISTRATION > Users > API Keys: click Create New Key and give it a name and description. The client_secret is shown in full only once, right after you create the key (or click Regenerate, which keeps the same Client Id and issues a new secret) — copy it then, because the key list only ever shows <Hidden> afterward.
Scopes like imports:create or exports:read aren’t chosen when you create the key. They come from the built-in Api Client role, whose permissions you can turn on or off per resource under ADMINISTRATION > Users > Roles — this isn’t an Acenda-Support-only step. See How to use the Acenda API for the full walkthrough of keys, roles, and scopes.
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
Example Request:
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:
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
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.
Gzip is API-only: the .csv.gz / .xlsx.gz formats are only accepted here. If you’re uploading through the Acenda UI instead (see Using the Import Feature), send a plain
.csvor.xlsx.
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.
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:
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.
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.
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:
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:
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 — see Using the Export Feature if you want to do that from the UI.
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:
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 entirely, Acenda falls back to your field's default unit (for example lb for weight, in for dimension, l for volume). Don't send a .unit value for a row with no .value — a unit with no accompanying number rejects that row with an "Update failed… invalid value" error, it does not fall back to a default.
Catalog Images (images.*)
Image fields ingest publicly accessible asset URLs.
Example CSV Format:
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
Important: Acenda only touches the image slots named by the columns you actually send — it does not wipe the rest of the image stack. In an upsert, a blank cell in a column you include clears that one slot (for example, blanking images.default.1.alternate.url removes only the first alternate image and leaves the main, swatch, and every other alternate untouched). A column you leave out of the file entirely is never touched. To clear a product's whole image set, send every images.* column blank; to update one slot without disturbing the rest, send only that column.
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
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:
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:
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.
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.
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):
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.
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 an export job requires exports:read, not exports:create. The exports:create scope is reserved for creating Export Profiles.
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.
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.
Troubleshooting & FAQ
401 Unauthorizedpartway through a long job: Your token expired — tokens are short-lived. Request a new one and retry the same step; you don't need to restart the job.403 Forbiddenon an otherwise-correct request: Your service account's Api Client role is missing the scope for that action (see the scopes table above). Add it under ADMINISTRATION > Users > Roles.409 Conflicton a preview action: That preview is already finalizing or being modified by another request. Wait for it to settle and retry rather than creating a new preview.410 Goneon a preview action: The preview passed its 24-hour window. Upload the file again to get a fresh token.429 Too Many Requestswhen creating a preview: You're at the 50-active-preview cap for your organization.DELETEpreviews you no longer need, then retry.Preview response has a non-empty
header_errors: One or more columns aren't recognized. Rename the columns to match the standard names, or map them with an import profile instead.Export request errors instead of returning an empty file: Your
queryfilter matched zero records. Loosen the filter and confirm matching data exists before exporting.
Related articles
Still stuck? Contact Acenda Support and include your organization slug, the endpoint you called, and the token or import/export id involved.
Keywords
Import and Export API, import API, export API, API automation, REST API, automate catalog updates, bulk API, API key, Create New Key, Regenerate, API scopes, service account, Api Client, authentication, headers, base URL, example request, size limit, 500 MB, XLSX constraint, Gzip, csv.gz, catalog sync, programmatic import, developer, how to automate catalog updates, how to use the import API, how to export data with the API, how to automate catalog updates with the import & export api
