Skip to content

Zugo: a complete sync app

Zugo is CIQRA’s reference app, and it uses only the public API described on this site — no private back door. It reads a dealer’s used-car feed and publishes each vehicle into the store as a metaobject entry of type ikinci-el-arac, with its photos imported into the store’s media library.

Source: ciqra-saas/apps/Ciqra.Apps.Zugo/ in the CIQRA repository.

A one-shot process: it starts, syncs, and exits. It holds no state between runs — the store is the state, and every write is keyed so a re-run converges instead of duplicating.

Setting (Zugo: section) Purpose
FeedBaseUrl, FeedUsername, FeedPassword The dealer feed.
PlatformBaseUrl Where to reach the CIQRA API.
PlatformHost The store’s domain, sent as Host — this is what selects the store.
ClientId, ClientSecret The app’s credentials.
MetaobjectType Default ikinci-el-arac.
MaxRunDuration Default 6 hours.

Missing secrets are all reported at startup at once, rather than one per failed run.

  1. Token. POST /apps/token with the client credentials. The token is cached and re-requested one minute before expiresIn runs out.
  2. Photos. For each vehicle, POST /apps/media/imports in chunks of up to 100 URLs, with Idempotency-Key: zugo:{runId}:{vehicle}:{chunk}. The key is per run on purpose: within a run a retry replays instead of re-downloading; the next run is a new request and picks up changed photos. Deduplication by URL and by content hash makes unchanged photos cost nothing.
  3. Entry. PUT /custom-data/metaobjects/ikinci-el-arac/entries/{feed id} with the vehicle’s fields and the returned mediaAssetIds in the gallery fields. The feed id is the handle, so the same car always lands on the same entry.

Failures are isolated per vehicle: one car whose photos fail does not stop the others, and the run’s summary reports every one. 401, 403 and 404 each produce a distinct message naming the likely cause (bad credentials, a missing scope, a missing metaobject type).

write_media and write_metaobjects — nothing to do with orders or customers, so the merchant’s consent screen shows exactly what it does.

  • Key every write by something stable from your source (handle = source id).
  • Treat the batch routes’ per-row results as the truth, not the status code.
  • Refresh the token before it expires instead of reacting to 401.
  • Keep idempotency keys per logical operation and reuse them across retries.