Productsup
Developer guides

Publishing changes

Export template changes stay in a draft until you publish them. How to publish with the ETM API, avoid overwriting other people's changes, and check when a change is live.

11 min read

Writing to an export template does not make the change live. Every write updates the template's draft, and only a publish makes the draft available in the Productsup platform.

This covers everything on an export template: template settings, tags, attributes, attribute tags, analyzer tests, marketing data, custom form fields, and metadata. A successful response from a write endpoint means the change is stored in the draft, not that platform users can see it.

Prerequisites

You need a valid access token. See Authentication for how to obtain one with the Client Credentials flow. You can only publish export templates you own.

Drafts, revisions, and draftVersion

TermWhat it means
DraftThe current, editable state of the export template. Every write changes the draft.
stateDRAFT while the draft has unpublished changes, ACTIVE after a successful publish.
draftVersionA number that identifies the current draft. Send it when you replace, update, or publish the export template. If the draft changed since you read it, the request fails instead of overwriting the change.
RevisionAn immutable copy of the whole export template, created by each publish and numbered from 1.
Active revisionThe revision the platform and the analyzer use. Exactly one revision per export template is active.

Nothing moves a draft into a revision except an explicit publish. There is no auto-publish and no timeout: a draft stays a draft until you publish it.

Analyzer tests are published with the template

Changes to analyzer tests follow the same rule as every other change. Adding, updating, or removing an analyzer test changes the draft and sets state to DRAFT. The analyzer in the platform keeps using the analyzer tests of the active revision until you publish.

Until an export template has been published with Publish in the Developer Portal or POST /V2/export-templates/{id}/publish, the analyzer uses its current analyzer tests, including unpublished changes. That is the case when the export template has no active revision yet, or when its active revision was created with the legacy POST /V1/export-templates/{id}/commit.

Analyzer test writes put the export template in draft and increment draftVersion. They do not take an If-Match header.

Publish with the API

Publishing takes two values: the export template ID and its current draftVersion.

Get the current draft version

GET /V2/export-templates/{templateId} returns state and draftVersion. The same version is in the ETag response header, for example "7". If-Match accepts both the plain number and the ETag value as it is.

curl "https://export-template-api.productsup.com/V2/export-templates/{templateId}" \
  -H "Authorization: Bearer <token>"
{
  "exportTemplateId": 12345,
  "name": "Example channel",
  "state": "DRAFT",
  "draftVersion": 7,
  "unpublishedChanges": true
}

Publish the draft

Send the draft version in the If-Match header:

curl -X POST "https://export-template-api.productsup.com/V2/export-templates/{templateId}/publish" \
  -H "Authorization: Bearer <token>" \
  -H "If-Match: 7"

A 202 Accepted response returns an operation ID and a Content-Location header that points to the operation:

{
  "operationId": "01980f10-5b04-7845-b0d5-66861c6cabb0",
  "status": "succeeded"
}

The ETM API finishes the publish before it responds, so status is already succeeded or failed, never running. You do not need to poll the operation. succeeded means the new revision is active, not that the platform uses it yet. See Propagation is asynchronous.

The publish creates the next revision, makes it the active revision, sets state to ACTIVE, and increments draftVersion. It records where the publish came from as API. Publishes from the Developer Portal are recorded as DEV_PORTAL.

Check the operation

curl "https://export-template-api.productsup.com/V2/operations/{operationId}" \
  -H "Authorization: Bearer <token>"

status is running only while the publish request is still being processed, then succeeded or failed. On succeeded, result.resourceId is the export template ID. On failed, error contains the reason.

Publish errors

StatusWhen it happens
400 Bad RequestThe If-Match header is missing or invalid, or the export template has no unpublished changes (state is not DRAFT). Nothing is published.
403 ForbiddenYou do not own the export template.
404 Not FoundThe export template does not exist or was deleted.
409 ConflictdraftVersion changed since you read it: someone else changed the export template. Nothing is published.

Avoid overwriting other people's changes

Several people and integrations can work on the same export template, through the API and in the Developer Portal. draftVersion protects the draft against lost updates:

  1. Read the export template and keep its draftVersion.
  2. Send that version as If-Match when you replace the export template (PUT /V2/export-templates/{templateId}), update it (PATCH /V2/export-templates/{templateId}), or publish it.
  3. On 409 Conflict, read the export template again, check the changes, and repeat your request with the new draftVersion.

Replacing, updating, and publishing the export template increment draftVersion, and so do analyzer test writes. A version you read before one of these writes no longer matches.

Other write endpoints, for example the V1 endpoints for tags and attributes, change the draft without changing draftVersion. If-Match does not detect these changes. To see everything a publish would include, check the draft changes first. See Check what is unpublished.

Check what is unpublished

state is DRAFT after any write since the last publish, even if the content is the same as the active revision. To see exactly what a publish would change, send a request to the draft changes endpoint:

curl "https://export-template-api.productsup.com/V2/export-templates/{templateId}/draft/changes" \
  -H "Authorization: Bearer <token>"

See Revisions and version history for the response format.

Propagation is asynchronous

A publish makes the new revision active immediately. The platform picks the revision up on its next synchronization run, which can take up to 6 minutes. Until then, platform users keep seeing the previous revision.

Each revision has a live flag that tells you whether the platform already uses it. A revision can be active but not yet live. See Revisions and version history.

Propagation is one-way. The platform rebuilds its copy of the export template from the published revision. Anything changed directly on the platform side, outside the ETM API, is overwritten by the next publish. Make the change in Export Template Management so it survives.

The V1 commit endpoint

POST /V1/export-templates/{templateId}/commit still exists, but it does not save the content of the export template. A commit is listed in the revision history without a revision number, and its content cannot be viewed or compared. When the active revision is a commit, the platform copies the export template as it is at its next synchronization run, including unpublished changes. The analyzer uses the current analyzer tests of the export template, including unpublished changes.

We strongly recommend publishing with POST /V2/export-templates/{templateId}/publish instead.

Worked example

Adding the allow_override export template tag, which lets sites use their own XSL instead of the export template's XSL, and publishing it takes three calls:

# 1. Write the tag: stored in the draft
curl -X POST "https://export-template-api.productsup.com/V1/export-templates/{templateId}/export-template-tags" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"key": "allow_override", "value": "1"}'

# 2. Read the current draft version
curl "https://export-template-api.productsup.com/V2/export-templates/{templateId}" \
  -H "Authorization: Bearer <token>"

# 3. Publish with that version: the tag becomes part of the new revision
curl -X POST "https://export-template-api.productsup.com/V2/export-templates/{templateId}/publish" \
  -H "Authorization: Bearer <token>" \
  -H "If-Match: <draftVersion>"

Stop after the first call and the tag exists in the draft and is returned by the tag endpoints, but the platform does not use it.

Productsup manages export template tags and attribute tags. Your API client can only add, change, or remove the xslt and allow_override export template tags. Any other tag write returns 403 Forbidden. Sending the existing tags back unchanged, for example in PUT /V2/export-templates/{templateId}, still works.

Next steps

On this page

Still stuck?

Reach out to our support team and we’ll help you get unstuck.

Contact support