States and events
The lifecycle of each resource, what changes each state and the webhook for each change.
This page shows how each resource changes state. In each diagram, a box is a state and an arrow says what causes the change. The webhook that tells you comes in parentheses. The full list of events is in Receiving webhooks.
Link session
- The three final states never change again. To connect again, create another session.
- Only a
pendingsession can be revoked. In the other states,DELETEreturns409. - The session lasts up to 5 minutes (
expiresAt). A Connection granted before that keeps working after the session expires.
Connection
active: working. The API renews the access on its own before it expires.error: renewing failed, and we do not know whether the access ended. Ask the Seller to grant access again in a link session.revoked: the access ended.revokedReasonsays who cut it:client(you) ormarketplace. The credential is deleted.- Granting access again reuses the Connection. The
idis the same, andconnection.updatedbrings the previous state inpreviousStatus.
Listing: publicationState
The offer's publicationState answers: "has what changed here gone out to the marketplace yet?" The content has its own, right below.
never_published: the listing only exists here.dirty: there is a local change that has not been published yet.pending: a publish or removal job is running. When removal on the marketplace finishes well, the Listing is deleted and you getlisting.deleted.clean: what is here is what was published or imported.failed: the last publish or removal job failed. You getlisting.updatedwithbehavior: "publication_failed"and thejobId; the error is on the Job item. Fix it and publish again.dirtywins over the end of a job. If you edit the listing while the job runs, it endsdirty, because the edit has not been published yet.- Reconciling a listing that already exists keeps
dirtyandpending; in the other states, it becomesclean.
marketplaceStatus (active, paused, closed, scheduled, suppressed, frozen…) is something else: it comes from the marketplace and changes on publishing, import, reconciliation and notifications. With it come the layers buyable, discoverable, pendingRevision and statusReasons, on the Listing and on each binding. When one changes, you receive listing.status_changed with the before and after of the Listing and only of the lines that changed; source tells where it came from (imported, inbound, reconciled, published, or inventory_published). The first import does not emit this event: listing.created already covers it.
linkState is linked when the listing has at least one binding, and unlinked when it has none. It is ambiguous when an import found more than one Variant for some variation and linked none of them; fix it with the bindings PUT.
MarketplaceProduct: publicationState and events
The content has the same states as the offer, but it moves on its own:
never_published: the content only exists here. This is how it is born, when you create or clone a Listing.dirty: aPATCHor a replacement of the variations changed the content and it has not been published yet.clean: the content was published or imported.- Publishing the Listing publishes the content with it, if it was never published. The content becomes
clean. If it had been published and you changed it afterwards, it staysdirtyeven after you publish the Listing: publishing only the content takes the content publication route. - The MarketplaceProduct has no
DELETE. Only the publish route talks to the marketplace; it keeps the contentpendinguntil the Job ends.
Each change becomes a webhook, marketplace_product.created or marketplace_product.updated. The behavior of updated says what happened:
behavior | When |
|---|---|
local_update | you changed the content with PATCH |
variants_changed | the variations changed: PUT …/variants, or a bindings PUT that created one |
published | publishing a Listing confirmed the content on the marketplace |
imported | an import brought the content in again |
publication_requested | you asked for the content publication; the content becomes pending (carries the jobId) |
publication_failed | the content publication failed for good (carries the jobId) |
external_changed | the marketplace changed the content and the change reached observed |
Job
Each Job has items, one per resource, which go from pending to succeeded or failed only once. The Job types and who creates each one:
type | Who creates it | One item per |
|---|---|---|
connection.sync | the API, when a Connection is born or access is granted again | Connection |
listing.publish | POST /v1/listings/{listingId}/publish | Listing |
listing.remove | a DELETE /v1/listings/{listingId} that removes it on the marketplace | Listing |
listing.import | POST /v1/connections/{id}/listing-imports | Connection |
listing.reconcile | POST /v1/connections/{id}/listing-reconciliations | Connection |
order.import | POST /v1/connections/{id}/order-imports | Connection |
order.reconcile | POST /v1/connections/{id}/order-reconciliations | Connection |
inventory.publish | an inventory movement, automatic sync or POST …/inventory-publications | binding |
marketplace_product.publish | POST /v1/marketplace-products/{marketplaceProductId}/publish | MarketplaceProduct |
Webhook delivery
- Retries come after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h. Each attempt waits up to 10 seconds for the answer.
- Redeliver creates a new delivery of the same event. The original delivery does not change.
- The same event can arrive more than once. Use the event
idto skip repeats.
A publication, from the request to the webhook
The path from POST /v1/listings/{listingId}/publish to the published listing:
On the first publication, the content (the MarketplaceProduct) goes in the same Job as the offer. On later ones, only the offer and its lines change, but the marketplace_product.updated with published is sent just the same.
If the marketplace refuses, the Job ends failed and the listing becomes failed. You get listing.updated (publication_failed) and job.failed, and the error is on the Job item (GET /v1/jobs/{id}/items).
An inventory movement with automatic sending
The path from a recorded sale to the new quantity on the marketplace:
With no automatic sending and no publishTargets, the movement only changes the balance: publicationJobId comes back null, and nothing goes to the marketplace. See From the balance to the marketplace.
The inventory.movement_created webhook is sent once per ledger row, with the warehouseId and the Variant balance after the command. A transfer between warehouses writes two rows and sends two events, with the same transferId. Because the Variant total does not change, it does not trigger automatic sending.