Arceto Developer Get API keys

Arceto Marketplace API

Programmatic access to your Arceto seller account. Sync inventory, manage prices, fetch orders and submit shipments — all from your existing OMS or ERP.

Introduction

The Arceto Marketplace API is a JSON-over-HTTPS interface scoped to a single seller account. Every request is authenticated against your Client ID / Client Secret pair, and authorized via a short-lived bearer token. All endpoints return application/json.

Base URL:

https://api.arceto.com

Every endpoint is https://api.arceto.com/<name>.php. The old https://www.arceto.com/api/… address still works. Please read Rate limits before you go live.

Quick start

  1. Generate a Client ID and Client Secret in Seller Central → Settings → API Keys.
  2. Exchange them for an access token via POST /token.php.
  3. Send your token in the AccessToken header to any other endpoint.

Authentication

Every API call (other than token.php) requires three request headers:

HeaderRequiredDescription
SellerIDYESYour numeric seller ID (vendor ID).
AuthorizationYESBasic + base64(clientId:clientSecret).
AccessTokenYESThe token returned by POST /token.php.
Content-Typewith a bodyapplication/json for JSON bodies, or application/x-www-form-urlencoded for legacy form bodies (Data=<json>). Not needed on GET or /token.php.
POST /token.php

Exchange Basic credentials for an access token. Tokens are tied to a single seller and are valid for 15 minutes (expires_in: 900). Reuse one token for every call in that window; get a new one when it expires or when a call returns AUTHENTICATION.

curl -X POST https://api.arceto.com/token.php \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $(echo -n 'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET' | base64)" \
  -H "Content-Type: application/x-www-form-urlencoded"

Response

{
  "access_token": "xWlZz*zEsi3HWg9t3Rz1u5CelAMGvPf7GE85qLWVAhrBRB&...",
  "token_type": "Bearer",
  "expires_in": 900
}
Heads up: each call to token.php replaces your active token — the previous one stops working immediately — and token.php is limited to 20 calls a minute. Cache the token for its 15 minutes instead of requesting one per call.

Errors

All errors are returned as JSON with the same shape:

{
  "status": "Error",
  "error_reason": "INVALID_REQUEST_PARAM",
  "error_description": "SellerID is missing or invalid."
}
error_reasonWhen it happens
METHOD_NOT_ALLOWEDWrong HTTP verb (e.g. GET on a write endpoint).
INVALID_REQUEST_HEADERMissing or wrong Content-Type.
INVALID_REQUEST_PARAMRequired parameter missing or malformed.
UNAUTHORIZEDBad Client ID / Client Secret pair.
AUTHENTICATIONAccessToken missing, wrong, replaced by a newer one, or older than 15 minutes.
RATE_LIMITEDHTTP 429 — too many requests. Wait for Retry-After seconds. See Rate limits.
CONTENT_NOT_FOUNDResource doesn't exist or isn't owned by this seller.

Bulk endpoints (price, qty, shipping) return per-item results — you'll get HTTP 200 with a mixed summary + items array, not a top-level error.

Rate limits

Limits keep the API fast for every seller. They are counted per one-minute window and reset at the start of each minute.

What is countedLimitApplies to
Requests per seller120 / minuteEvery authenticated call (after your token is accepted).
Requests per IP address300 / minuteEvery call to the API, signed in or not.
Token requests per seller20 / minutePOST /token.php
Items per request500/listings, /price, /qty — a batch counts as one request.
Orders per page100 (default 20)GET /orders.php with limit / page
Products per page200 (default 50)GET /products.php
Feed "run now"once per 5 minutes per importPOST /feeds.php

Headers on every response

HeaderMeaning
X-RateLimit-LimitThe limit for the window this request was counted in.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetUnix time (seconds) when the window resets.
Retry-AfterOnly on a 429: seconds to wait before retrying.

When you go over

HTTP/2 429
Retry-After: 37
X-RateLimit-Remaining: 0

{
  "status": "Error",
  "error_reason": "RATE_LIMITED",
  "error_description": "Too many requests: limit is 120 per minute. Retry after 37 seconds. Batch up to 500 items per call to stay well under it."
}
Staying well under the limits:
  • Send up to 500 items per call to /listings, /price or /qty — 10,000 price changes is 20 requests, not 10,000.
  • Reuse your token for its 15 minutes; don't call /token.php before every request.
  • Poll orders every few minutes with createdAfter = your last check, not in a tight loop.
  • For a whole catalogue, use a feed file: Arceto pulls it on your schedule and it doesn't count against your API limit.
  • On a 429, wait Retry-After seconds and retry — don't retry immediately.

Condition IDs

Several endpoints take a conditionId field. Each (BSIN, conditionId) pair on your account is a distinct row — the same product in New and Open Box conditions are listed separately.

conditionIdDisplay name
1New
2Open Box
3Refurbished
4Seller Refurbished
5Used

List products v1

GET /products.php

Return your seller-scoped product feed. Supports search, filtering and pagination. Use this to bootstrap your local mirror of BSINs, then call /price and /qty to push updates.

Query parameters

ParamTypeDescription
skustringFilter by your own SKU. Each product in the response carries its sku.
bsinstringFilter by exact Arceto BSIN.
itemIdintFilter by Arceto numeric item id.
upcstringFilter by GTIN / UPC.
conditionIdintRestrict to one condition (1–5, see above).
qstringSubstring match on title or manufacturer part #.
changedSincedatetimeOnly return rows updated after YYYY-MM-DD HH:MM:SS (UTC).
pageint1-indexed page number. Default 1.
limitintItems per page. Default 50, max 200.
curl "https://api.arceto.com/products.php?changedSince=2026-04-26+00:00:00&limit=100" \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded"

Response

{
  "meta": { "page": 1, "limit": 50, "total": 1, "pages": 1 },
  "products": [
    {
      "bsin": "ZUGKSHHKHO",
      "itemId": 238724478,
      "title": "YAMAHA YVC-330 USB MICROPHONE & SPEAKER SYSTEM",
      "mfg": "Yamaha",
      "mfgPart": "10-YVC330",
      "productId": "889025128698",
      "productIdType": "UPC",
      "conditionId": 1,
      "condition": "New",
      "cost": 367.72,
      "mapEnabled": true,
      "mapPrice": 410.29,
      "qty": 2,
      "markup": 9,
      "discount": 0,
      "imageUrl": "https://img.arceto.com/product_images/2026/04/4/08/ZUGKSHHKHO-0.webp",
      "active": true,
      "lastUpdated": "2026-04-26 23:24:44"
    }
  ]
}

Update price v1

POST /price.php

Bulk-update cost (your selling price in USD) and optional mapPrice (Minimum Advertised Price floor) for one or more (BSIN, conditionId) pairs you own. Up to 500 items per request.

Request body

Send either raw JSON with Content-Type: application/json, or form-encoded with Data=<json-string> and Content-Type: application/x-www-form-urlencoded.

FieldTypeDescription
items[].skustringYour SKU — use this or bsin + conditionId.
items[].bsinstringArceto BSIN (if you don't send sku).
items[].conditionIdint1–5 (see Condition IDs). Required with bsin.
items[].costnumber · requiredSelling price in USD. Must be ≥ 0.
items[].mapPricenumber · optionalMAP floor. Set to 0 to disable MAP.
curl -X POST https://api.arceto.com/price.php \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {"bsin": "ZUGKSHHKHO", "conditionId": 1, "cost": 367.72, "mapPrice": 410.29},
      {"bsin": "ZYNTWY7P9R", "conditionId": 1, "cost": 27.73}
    ]
  }'

Response

{
  "summary": { "accepted": 2, "rejected": 0, "total": 2 },
  "items": [
    { "bsin": "ZUGKSHHKHO", "conditionId": 1, "status": "Success", "description": "Price updated.", "cost": 367.72, "mapPrice": 410.29 },
    { "bsin": "ZYNTWY7P9R", "conditionId": 1, "status": "Success", "description": "Price updated.", "cost": 27.73,  "mapPrice": null  }
  ]
}
Per-item failures don't fail the batch — inspect summary.rejected and the per-row status field. Common reasons: BSIN doesn't belong to your seller account, missing conditionId, or negative cost.

Update quantity v1

POST /qty.php

Bulk-update on-hand quantity for (BSIN, conditionId) pairs. Same shape, same 500-item cap as /price. Set qty: 0 to deactivate a listing without retiring it.

Request body

FieldTypeDescription
items[].skustringYour SKU — use this or bsin + conditionId.
items[].bsinstringArceto BSIN (if you don't send sku).
items[].conditionIdint1–5. Required with bsin.
items[].qtyint · requiredOn-hand units, ≥ 0.
curl -X POST https://api.arceto.com/qty.php \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {"bsin": "ZUGKSHHKHO", "conditionId": 1, "qty": 5},
      {"bsin": "ZYNTWY7P9R", "conditionId": 1, "qty": 0}
    ]
  }'

Response

{
  "summary": { "accepted": 2, "rejected": 0, "total": 2 },
  "items": [
    { "bsin": "ZUGKSHHKHO", "conditionId": 1, "status": "Success", "description": "Quantity updated.", "qty": 5 },
    { "bsin": "ZYNTWY7P9R", "conditionId": 1, "status": "Success", "description": "Quantity updated.", "qty": 0 }
  ]
}

Create or update listings v1

POST /listings.php

Send your catalogue by your own SKU — no Arceto ids needed. For each item:

Other verbs: PATCH /listings.php takes the same body but only updates SKUs you already list (unknown SKUs are rejected, nothing is created). GET /listings.php?sku=SKU1,SKU2 looks up to 100 of your SKUs (price, qty, BSIN, status; "found": false for unknown ones).

New listings need price > 0 and qty > 0. Up to 500 items per request. Set "validateOnly": true to check a batch without changing anything. Prefer a file? The same fields work as a CSV feed in Seller Central → Feed Sync (match on SKU, "create listings" on), pulled on a schedule from a URL, FTP or SFTP.

Request body

FieldTypeDescription
items[].skustring · requiredYour SKU, up to 64 characters. One SKU = one product + condition.
items[].conditionIdint1–5, default 1 (New). See Condition IDs.
items[].pricenumberSelling price in USD.
items[].qtyintUnits available, ≥ 0. 0 pauses the listing.
items[].titlestringRequired only when the product has to be created.
items[].brand, items[].mfgPartstringBrand and manufacturer part number — used to find the product.
items[].upcstringUPC/EAN — used to find the product.
items[].bsinstringArceto BSIN, if you already know the product.
items[].descriptionstringHTML or plain text.
items[].imagesarray of URLsUp to 8 JPG/PNG/WEBP/GIF images, 5MB each; we download them.
items[].weight, length, width, heightnumberlb / inches.
items[].categoryIdintCategory id, if known.
validateOnlyboolCheck only, change nothing.
curl -X POST https://api.arceto.com/listings.php \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {"sku": "WIDGET-001", "conditionId": 1, "price": 24.99, "qty": 12,
       "title": "Acme USB-C Hub 7-in-1", "brand": "Acme", "mfgPart": "HUB-7C",
       "upc": "012345678905", "images": ["https://example.com/hub.jpg"]},
      {"sku": "WIDGET-002", "price": 9.50, "qty": 0}
    ]
  }'

Response

{
  "validateOnly": false,
  "summary": { "accepted": 2, "rejected": 0, "total": 2, "created": 1, "attached": 0, "updated": 1 },
  "items": [
    { "sku": "WIDGET-001", "conditionId": 1, "status": "Success", "action": "created", "bsin": "AR7K2Q9XM4", "description": "New product created." },
    { "sku": "WIDGET-002", "conditionId": 1, "status": "Success", "action": "updated", "bsin": "AR3MZP81QD", "description": "Price/qty updated." }
  ]
}

action is one of updated, attached (offer added to an existing product), created, skipped or failed; skipped and failed items carry the reason in description.

Feed status v1.1

Prefer files to API calls? Set up a feed import in Seller Central → Feed Sync: a CSV/TSV at a URL, FTP or SFTP that Arceto pulls on your schedule. Match on SKU and turn on create listings to add new products from the file — same rules as /listings. A full feed import also sets anything missing from the file to qty 0 (with a safety stop if the file is under half its usual size). These endpoints report on your imports.

GET/feeds.php

Your imports and each one's last result.

GET/feeds.php?importId=12&limit=10

One import plus its recent runs: rows total / updated / added / zeroed / skipped / failed, and up to 10 error lines per run.

POST/feeds.php

Body {"importId": 12} — queue a run now (it starts within a minute; poll GET for the result). Once per 5 minutes per import. URL / FTP / SFTP imports only — upload manual files in Seller Central.

Response (GET with importId)

{
  "importId": 12, "name": "Nightly catalogue", "sourceType": "url", "matchField": "sku",
  "createsListings": true, "fullFeed": true, "schedule": "Hourly at :45", "status": "active",
  "lastRunAt": "2026-10-04 11:45:01", "lastStatus": "success",
  "runs": [
    { "runId": 41, "trigger": "cron", "status": "success",
      "startedAt": "2026-10-04 11:45:01", "finishedAt": "2026-10-04 11:47:58",
      "rows": { "total": 82550, "updated": 82136, "added": 0, "zeroed": 0, "skipped": 414, "failed": 0 },
      "errors": [] }
  ]
}

Google Shopping feeds — no mapping

Already list on Google Shopping? In Seller Central → Feed Sync, paste the feed URL you give Google Merchant Center (tab-separated, CSV, or XML/RSS/Atom with the g: namespace) and click Preview, then Connect & import. Arceto reads it exactly as Google does:

Google attributeOn Arceto
idyour SKU
title, description, brand, mpn, gtinproduct details; gtin / brand+mpn find products already on Arceto
price, sale_priceyour price (the sale price when it is lower)
availabilityin stock / preorder / backorder → the quantity you choose (default 5); out of stock → 0. A quantity or sell_on_google_quantity column overrides it.
conditionnew → New, refurbished → Refurbished, used → Used
image_link, additional_image_linkup to 8 images, downloaded by Arceto
shipping_weight, shipping_length/width/heightweight (lb) and size (in); kg, g, oz, cm and mm are converted

Choose daily or hourly checks, and tick whole catalogue if items missing from the feed should go to qty 0. The feed URL must be public (http/https on port 80 or 443).

Feed file columns (match on SKU)

Header row, comma-separated: sku, condition, price, qty, bsin, upc, brand, mfg_part, title, description, image, wt, length, width, height, category. Only sku and price or qty are needed to update; title is needed to create a product. Separate several image URLs with |.

List orders

GET /orders.php?createdAfter=YYYY-MM-DD+HH:MM:SS

Return orders created after the given timestamp, oldest first. By default only unshipped orders, 20 per page. Each order includes its lines (with your sku and whether you acknowledged it), shipping/billing address and totals.

Query parameters

ParamTypeDescription
createdAfterdatetime · requiredSQL datetime, e.g. 2026-04-26 00:00:00.
statusstringComma list: unshipped (default), shipped, cancelled, return_requested, cancel_requested, refunded, pending, or all.
acknowledgedboolfalse = only orders you haven't acknowledged yet (the usual "new orders" poll); true = only acknowledged.
limit, pageintPage size (default 20, max 100) and page number (from 1).
curl "https://api.arceto.com/orders.php?createdAfter=2026-04-26+00:00:00" \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded"

Get a single order

GET /getOrder.php?orderId=<ORDER_ID>

Fetch one order by its orderId (the value returned by /orders). Same response shape as a single entry in the orders list.

Acknowledge an order v1.1

POST/acknowledge.php

Tell Arceto you've received an order and will fulfil it. Body {"orderId": "4Q8W2E-1329"} (the orderId from /orders). Then poll GET /orders.php?acknowledged=false to see only new orders.

{ "status": "Success", "orderId": "4Q8W2E-1329", "linesAcknowledged": 2 }

Cancel order lines v1.1

POST/cancel.php

Cancel lines you can't fulfil — only lines that haven't shipped (unshipped, pending payment, or a buyer cancel request). Arceto refunds the buyer. Body: {"orderId": "4Q8W2E-1329", "itemIds": [154349], "reason": "Out of stock", "comment": "optional"}.

{
  "orderId": "4Q8W2E-1329",
  "items": [ { "itemId": 154349, "status": "Success", "description": "Line cancelled. Arceto refunds the buyer." } ]
}

Submit shipment

POST /shipping.php

Mark order lines as shipped and submit carrier + tracking. Carriers accepted include UPS, USPS, FedEx, DHL, OnTrac, Lasership, plus most LTL freight providers.

Request body

FieldTypeDescription
orderShipment.orderIdstring · requiredThe orderId from /orders.
orderLines.orderLine[].item.idint · requiredThe line's item id.
orderLines.orderLine[].item.qtyint · requiredQuantity shipped.
orderLines.orderLine[].item.statusstring · requiredSet to "1" for shipped.
orderLines.orderLine[].item.carrierstring · requirede.g. UPS, FedEx, USPS.
orderLines.orderLine[].item.servicestringService level, e.g. Ground.
orderLines.orderLine[].item.trackingNumberstring · requiredCarrier tracking number.
orderLines.orderLine[].item.shipDatedate · requiredYYYY-MM-DD.
DATA='{"orderShipment":{"orderId":"a1b2c3-91234","orderLines":{"orderLine":[
  {"item":{"id":12345,"qty":1,"status":"1","carrier":"UPS","service":"Ground","trackingNumber":"1Z999AA10123456784","shipDate":"2026-04-26"}}
]}}}'
curl -X POST https://api.arceto.com/shipping.php \
  -H "SellerID: 12345" \
  -H "Authorization: Basic $BASIC" \
  -H "AccessToken: $TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "Data=$DATA"

Changelog

DateChange
2026-10-04v1.1 orders: status / acknowledged / limit / page on /orders, sku + acknowledged on each line, new /acknowledge and /cancel. /shipping now saves tracking (it previously returned success without saving).
2026-10-04Google Shopping (Merchant Center) feeds accepted as-is in Feed Sync — details.
2026-10-04v1.1: base URL https://api.arceto.com; rate limits with X-RateLimit-* headers and HTTP 429; tokens now expire after 15 minutes; sku on /products, /price, /qty; PATCH and GET on /listings; new /feeds.
2026-10-04Added /listings: create or update listings by your own SKU. Feed files can now create listings too.
2026-04-26Added /products, /price, /qty. Modernized the developer portal.
2024-12-07Initial launch: /token, /orders, /getOrder, /shipping.

Support

Hit a snag? Email developer@arceto.com with your SellerID, the request URL and the response body. We typically respond within one business day.

For account / payout / catalog questions, head to Seller Central instead.