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.
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
| Term | What it means |
|---|---|
| Draft | The current, editable state of the export template. Every write changes the draft. |
state | DRAFT while the draft has unpublished changes, ACTIVE after a successful publish. |
draftVersion | A 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. |
| Revision | An immutable copy of the whole export template, created by each publish and numbered from 1. |
| Active revision | The 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
| Status | When it happens |
|---|---|
400 Bad Request | The If-Match header is missing or invalid, or the export template has no unpublished changes (state is not DRAFT). Nothing is published. |
403 Forbidden | You do not own the export template. |
404 Not Found | The export template does not exist or was deleted. |
409 Conflict | draftVersion 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:
- Read the export template and keep its
draftVersion. - Send that version as
If-Matchwhen you replace the export template (PUT /V2/export-templates/{templateId}), update it (PATCH /V2/export-templates/{templateId}), or publish it. - On
409 Conflict, read the export template again, check the changes, and repeat your request with the newdraftVersion.
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
- Revisions and version history — list revisions, read their content, and see what changed
- Publish export template changes — publishing from the Developer Portal interface
- Publish an export template — endpoint reference
How is this guide?