Skip to main content

How to automate catalog updates with the Import & Export API

Keep catalog, inventory and pricing in sync on a schedule.

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_id and client_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 .csv or .xlsx.

Import Types

Import Type

Use Case

catalog

Product catalog data (most common)

inventory_detail

Inventory quantities and warehouse-level inventory

channel_item_mapping

Channel listing mappings

sku_presentation

Channel-specific SKU presentation data

promotion

Promotional pricing

custom_pricing

Custom pricing records

tracking

Shipment tracking updates

kit_component

Kit component relationships

Export Types

Export Type

Use Case

catalog

Product catalog data

inventory_detail

Inventory quantities and warehouse-level inventory

channel_item_mapping

Channel listing mappings

sku_presentation

Channel-specific SKU presentation data

promotion

Promotional pricing

custom_pricing

Custom pricing records

kit_component

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

token

Preview token used to manage, finalize, or cancel the preview

expires_at

When the preview expires

raw_header

Header row parsed from the file

preview_rows

Sample rows from the file for validation

header_errors

Header validation problems

total_lines

Number of non-empty data rows

image_count

Number of valid image URLs found for catalog image columns

import_id

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: Becomes true when 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

sku

Product or variant unique SKU

name

Product name

group

Product structural type: product, variant, or kit

upc, ean, gtin, mpn, isbn

Product barcodes and unique identifiers

group_ids.N, group_skus.N

Link child variants to parent products

options.N

Variant option configuration values

pricing_item.price.amount / .currency

Product selling price configuration

pricing_item.msrp.amount / .currency

Manufacturer's Suggested Retail Price

pricing_item.mapp.amount / .currency

Minimum Advertised Price mapping

images.*

Product image asset URLs

fields.*

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: true when 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

imports:create

Create, reparse, finalize, or cancel file previews

imports:read

Read import logs and download failed rows reports

imports:update / :delete

Manage shared Import Profiles

exports:read

Trigger export jobs, monitor progress, and access generated paths

exports:create / :update / :delete

Manage shared Export Profiles

general:read

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

  • 400 Bad Request: Invalid profile syntax, bad payload type mapping, or header structures failed validation.

  • 401 Unauthorized: Token is missing, incorrectly structured, or expired.

  • 403 Forbidden: Authenticated user lacks the designated scopes for this action.

  • 404 Not Found: Target resource doesn't exist (or error logs are clear of failed records).

  • 409 Conflict: Triggered if a preview state is already transitioning or finalizing.

  • 410 Gone: The target preview instance has passed its 24-hour expiration window.

  • 429 Too Many Requests: Hit the systemic limit of 50 active, unfinalized file previews. Clean up stale jobs via DELETE.

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_errors is 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: true flags; 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

  1. Authenticate: Request an OAuth2 access token using your service account credentials.

  2. Upload Preview: Push your catalog payload file to the /import_preview/catalog endpoint.

  3. 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}.

  4. Monitor Job: Poll the /catalog/import/{id} status endpoint using a progressive backoff interval.

  5. 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 Unauthorized partway 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 Forbidden on 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 Conflict on 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 Gone on a preview action: The preview passed its 24-hour window. Upload the file again to get a fresh token.

  • 429 Too Many Requests when creating a preview: You're at the 50-active-preview cap for your organization. DELETE previews 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 query filter 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

Did this answer your question?