curl --request POST \
--url https://api.tassyir.io/apps/2026-10/offers/{id}/publish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expectedVersion": 2
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({expectedVersion: 2})
};
fetch('https://api.tassyir.io/apps/2026-10/offers/{id}/publish', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"id": "<string>",
"storeId": "<string>",
"kind": "<string>",
"method": "<string>",
"title": "<string>",
"label": {
"ar": "<string>",
"fr": "<string>",
"en": "<string>"
},
"status": "<string>",
"currency": "<string>",
"quantity": {
"priceMode": "<string>",
"tiers": [
{
"pieces": 0,
"label": {
"ar": "<string>",
"fr": "<string>",
"en": "<string>"
},
"total": "<string>",
"percentOff": 123,
"amountOffEach": "<string>",
"preselected": true,
"freeDelivery": true
}
]
},
"freeDelivery": {
"thresholdKind": "<string>",
"thresholdPieces": 0,
"thresholdAmount": "<string>",
"delivery": "<string>",
"wilayas": [
"<string>"
]
},
"productDiscount": {
"valueType": "<string>",
"percent": 123,
"amount": "<string>",
"maxAmount": "<string>",
"showCountdown": true
},
"orderDiscount": {
"valueType": "<string>",
"percent": 123,
"amount": "<string>",
"maxAmount": "<string>",
"minimumKind": "<string>",
"minimumPieces": 0,
"minimumAmount": "<string>"
},
"bxgy": {
"buyPieces": 0,
"getPieces": 0,
"getDiscountType": "<string>",
"getPercent": 123,
"getPrice": "<string>",
"maxPerOrder": 0
},
"addon": {
"priceType": "<string>",
"price": "<string>",
"percent": 123,
"amountOff": "<string>",
"maxQuantity": 0,
"beforeSubmit": true,
"afterSubmit": true
},
"appRule": {
"typeHandle": "<string>",
"rule": "<unknown>"
},
"combinesWith": {
"product": true,
"order": true,
"delivery": true
},
"eligibility": {
"audience": "<string>",
"channels": [
"<string>"
],
"wilayas": [
"<string>"
],
"deliveryMethods": [
"<string>"
]
},
"targets": [
{
"role": "<string>",
"type": "<string>",
"id": "<string>"
}
],
"codeCount": 0,
"totalUsageLimit": 0,
"perBuyerLimit": 0,
"startsAt": "2023-11-07T05:31:56Z",
"endsAt": "2023-11-07T05:31:56Z",
"publishedAt": "2023-11-07T05:31:56Z",
"pausedAt": "2023-11-07T05:31:56Z",
"archivedAt": "2023-11-07T05:31:56Z",
"appOwned": true,
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
}{
"type": "<string>",
"title": "<string>",
"status": 400,
"detail": "<string>",
"code": "BAD_REQUEST",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 401,
"detail": "<string>",
"code": "APP_TOKEN_INVALID",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 403,
"detail": "<string>",
"code": "OFFER_NOT_OWNED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 404,
"detail": "<string>",
"code": "NOT_FOUND",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 409,
"detail": "<string>",
"code": "IDEMPOTENCY_KEY_IN_USE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 413,
"detail": "<string>",
"code": "PAYLOAD_TOO_LARGE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 415,
"detail": "<string>",
"code": "UNSUPPORTED_MEDIA_TYPE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 422,
"detail": "<string>",
"code": "IDEMPOTENCY_KEY_REUSED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 429,
"detail": "<string>",
"code": "BUSINESS_RATE_LIMITED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 500,
"detail": "<string>",
"code": "INTERNAL_ERROR",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 503,
"detail": "<string>",
"code": "API_BUSY",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}Publish an offer
Puts a draft live (from its start date). An incomplete offer is 400 OFFER_INVALID; past the plan’s active_offers cap it is 403 PLAN_LIMIT_REACHED (the cap counts an app’s offers like the merchant’s). Publishing a published offer changes nothing. An app changes, and reads the codes and redemptions of, only the offers its own installation created (ownerInstallationId is set from the token when it creates one). A merchant’s offer, or another app’s, is 403 OFFER_NOT_OWNED; an offer the token cannot see (another business, a store outside the installation’s stores) is 404.
Needs the write_offers scope (permission offers:update).
curl --request POST \
--url https://api.tassyir.io/apps/2026-10/offers/{id}/publish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expectedVersion": 2
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({expectedVersion: 2})
};
fetch('https://api.tassyir.io/apps/2026-10/offers/{id}/publish', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"id": "<string>",
"storeId": "<string>",
"kind": "<string>",
"method": "<string>",
"title": "<string>",
"label": {
"ar": "<string>",
"fr": "<string>",
"en": "<string>"
},
"status": "<string>",
"currency": "<string>",
"quantity": {
"priceMode": "<string>",
"tiers": [
{
"pieces": 0,
"label": {
"ar": "<string>",
"fr": "<string>",
"en": "<string>"
},
"total": "<string>",
"percentOff": 123,
"amountOffEach": "<string>",
"preselected": true,
"freeDelivery": true
}
]
},
"freeDelivery": {
"thresholdKind": "<string>",
"thresholdPieces": 0,
"thresholdAmount": "<string>",
"delivery": "<string>",
"wilayas": [
"<string>"
]
},
"productDiscount": {
"valueType": "<string>",
"percent": 123,
"amount": "<string>",
"maxAmount": "<string>",
"showCountdown": true
},
"orderDiscount": {
"valueType": "<string>",
"percent": 123,
"amount": "<string>",
"maxAmount": "<string>",
"minimumKind": "<string>",
"minimumPieces": 0,
"minimumAmount": "<string>"
},
"bxgy": {
"buyPieces": 0,
"getPieces": 0,
"getDiscountType": "<string>",
"getPercent": 123,
"getPrice": "<string>",
"maxPerOrder": 0
},
"addon": {
"priceType": "<string>",
"price": "<string>",
"percent": 123,
"amountOff": "<string>",
"maxQuantity": 0,
"beforeSubmit": true,
"afterSubmit": true
},
"appRule": {
"typeHandle": "<string>",
"rule": "<unknown>"
},
"combinesWith": {
"product": true,
"order": true,
"delivery": true
},
"eligibility": {
"audience": "<string>",
"channels": [
"<string>"
],
"wilayas": [
"<string>"
],
"deliveryMethods": [
"<string>"
]
},
"targets": [
{
"role": "<string>",
"type": "<string>",
"id": "<string>"
}
],
"codeCount": 0,
"totalUsageLimit": 0,
"perBuyerLimit": 0,
"startsAt": "2023-11-07T05:31:56Z",
"endsAt": "2023-11-07T05:31:56Z",
"publishedAt": "2023-11-07T05:31:56Z",
"pausedAt": "2023-11-07T05:31:56Z",
"archivedAt": "2023-11-07T05:31:56Z",
"appOwned": true,
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
}{
"type": "<string>",
"title": "<string>",
"status": 400,
"detail": "<string>",
"code": "BAD_REQUEST",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 401,
"detail": "<string>",
"code": "APP_TOKEN_INVALID",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 403,
"detail": "<string>",
"code": "OFFER_NOT_OWNED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 404,
"detail": "<string>",
"code": "NOT_FOUND",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 409,
"detail": "<string>",
"code": "IDEMPOTENCY_KEY_IN_USE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 413,
"detail": "<string>",
"code": "PAYLOAD_TOO_LARGE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 415,
"detail": "<string>",
"code": "UNSUPPORTED_MEDIA_TYPE",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 422,
"detail": "<string>",
"code": "IDEMPOTENCY_KEY_REUSED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 429,
"detail": "<string>",
"code": "BUSINESS_RATE_LIMITED",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 500,
"detail": "<string>",
"code": "INTERNAL_ERROR",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}{
"type": "<string>",
"title": "<string>",
"status": 503,
"detail": "<string>",
"code": "API_BUSY",
"docs": "<string>",
"fix": "<string>",
"requestId": "<string>",
"errors": [
"<string>"
]
}Authorizations
An app access token from POST /apps/oauth/token, valid 1 hour. An offline token acts as the app; an online token acts as the app on behalf of one dashboard user (the intersection of both permission sets).
Headers
Makes a write safe to retry: the same key with the same method, path, query and body within 24 hours answers the stored result (Idempotent-Replayed: true) without running the write again. Only a successful answer is stored, so a retry after a failure runs. A key reused for a different request is 422 IDEMPOTENCY_KEY_REUSED; one whose first request still runs is 409 IDEMPOTENCY_KEY_IN_USE.
1 - 255^[\x21-\x7E]+$Path Parameters
A resource id. One this installation cannot read, or a malformed one, is 404 NOT_FOUND.
1Query Parameters
Return only these top-level fields, separated by commas; the id is always kept. The response schema describes the whole resource. An unknown name is 400 INVALID_FIELDS. Fields: id, storeId, kind, method, title, label, status, currency, quantity, freeDelivery, productDiscount, orderDiscount, bxgy, addon, appRule, combinesWith, eligibility, targets, codeCount, totalUsageLimit, perBuyerLimit, startsAt, endsAt, publishedAt, pausedAt, archivedAt, appOwned, createdAt, updatedAt.
1000Body
x >= 1Response
The offer as it is now.
An offer (API 2026-10).
Show child attributes
Show child attributes