curl --request PUT \
--url https://api.tassyir.io/developer/apps/{appId}/listing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"searchTerms": [
"<string>"
],
"iconMediaId": "<string>",
"screenshots": {
"desktop": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": []
}
'const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: {ar: '<string>', en: '<string>'},
tagline: {ar: '<string>', en: '<string>'},
description: {ar: '<string>', en: '<string>'},
features: [{ar: '<string>', en: '<string>'}],
searchTerms: ['<string>'],
iconMediaId: '<string>',
screenshots: {
desktop: [{mediaId: '<string>', alt: {ar: '<string>', en: '<string>'}}],
mobile: [{mediaId: '<string>', alt: {ar: '<string>', en: '<string>'}}]
},
supportUrl: '<string>',
privacyPolicyUrl: '<string>',
externalService: {name: '<string>', url: '<string>', paid: true},
languages: []
})
};
fetch('https://api.tassyir.io/developer/apps/{appId}/listing', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"appId": "<string>",
"distribution": "<string>",
"listedAt": "2023-11-07T05:31:56Z",
"delistedAt": "2023-11-07T05:31:56Z",
"delistedBy": "<string>",
"draft": {
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"category": "orders",
"searchTerms": [
"<string>"
],
"iconMediaId": "<string>",
"screenshots": {
"desktop": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": [
"ar"
]
},
"draftUpdatedAt": "2023-11-07T05:31:56Z",
"issues": [
{
"code": "LISTING_FIELD_UNKNOWN",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"live": {
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"category": "orders",
"searchTerms": [
"<string>"
],
"iconUrl": "<string>",
"screenshots": {
"desktop": [
{
"id": "<string>",
"url": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"id": "<string>",
"url": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": [
"ar"
],
"approvedAt": "2023-11-07T05:31:56Z"
},
"media": [
{
"id": "<string>",
"kind": "<string>",
"url": "<string>",
"contentType": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"bytes": 4503599627370496,
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"retiredAt": "2023-11-07T05:31:56Z"
}
]
}
}{
"code": "BAD_REQUEST",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_TOKEN_INVALID",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_ACCOUNT_SUSPENDED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "APP_NOT_FOUND",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "APP_READ_ONLY",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "PAYLOAD_TOO_LARGE",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "BAD_REQUEST",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_TOKEN_RATE_LIMITED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}Replace your app's draft listing
The whole draft: a field you leave out (or send null) is cleared. Every rule is checked at once (LISTING_INVALID lists each problem with its path); an incomplete draft is saved and its gaps come back as issues. Plain text only: no HTML, no Markdown links, no invisible characters. The draft never reaches the marketplace by itself: Tassyir reviews it first.
Takes the dashboard session or a developer token (tsy_dt_…); either way the caller is the signed-in user, and only their own account, apps and tokens are reachable.
curl --request PUT \
--url https://api.tassyir.io/developer/apps/{appId}/listing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"searchTerms": [
"<string>"
],
"iconMediaId": "<string>",
"screenshots": {
"desktop": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": []
}
'const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: {ar: '<string>', en: '<string>'},
tagline: {ar: '<string>', en: '<string>'},
description: {ar: '<string>', en: '<string>'},
features: [{ar: '<string>', en: '<string>'}],
searchTerms: ['<string>'],
iconMediaId: '<string>',
screenshots: {
desktop: [{mediaId: '<string>', alt: {ar: '<string>', en: '<string>'}}],
mobile: [{mediaId: '<string>', alt: {ar: '<string>', en: '<string>'}}]
},
supportUrl: '<string>',
privacyPolicyUrl: '<string>',
externalService: {name: '<string>', url: '<string>', paid: true},
languages: []
})
};
fetch('https://api.tassyir.io/developer/apps/{appId}/listing', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"appId": "<string>",
"distribution": "<string>",
"listedAt": "2023-11-07T05:31:56Z",
"delistedAt": "2023-11-07T05:31:56Z",
"delistedBy": "<string>",
"draft": {
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"category": "orders",
"searchTerms": [
"<string>"
],
"iconMediaId": "<string>",
"screenshots": {
"desktop": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"mediaId": "<string>",
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": [
"ar"
]
},
"draftUpdatedAt": "2023-11-07T05:31:56Z",
"issues": [
{
"code": "LISTING_FIELD_UNKNOWN",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"live": {
"name": {
"ar": "<string>",
"en": "<string>"
},
"tagline": {
"ar": "<string>",
"en": "<string>"
},
"description": {
"ar": "<string>",
"en": "<string>"
},
"features": [
{
"ar": "<string>",
"en": "<string>"
}
],
"category": "orders",
"searchTerms": [
"<string>"
],
"iconUrl": "<string>",
"screenshots": {
"desktop": [
{
"id": "<string>",
"url": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
],
"mobile": [
{
"id": "<string>",
"url": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"alt": {
"ar": "<string>",
"en": "<string>"
}
}
]
},
"supportUrl": "<string>",
"privacyPolicyUrl": "<string>",
"externalService": {
"name": "<string>",
"url": "<string>",
"paid": true
},
"languages": [
"ar"
],
"approvedAt": "2023-11-07T05:31:56Z"
},
"media": [
{
"id": "<string>",
"kind": "<string>",
"url": "<string>",
"contentType": "<string>",
"width": 4503599627370496,
"height": 4503599627370496,
"bytes": 4503599627370496,
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"retiredAt": "2023-11-07T05:31:56Z"
}
]
}
}{
"code": "BAD_REQUEST",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_TOKEN_INVALID",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_ACCOUNT_SUSPENDED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "APP_NOT_FOUND",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "APP_READ_ONLY",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "PAYLOAD_TOO_LARGE",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "BAD_REQUEST",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"code": "DEVELOPER_TOKEN_RATE_LIMITED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}Authorizations
The dashboard's session token (Authorization: Bearer <JWT>), as the console sends it. Never paste it into a terminal: it opens every business the user belongs to.
Path Parameters
One of your apps' ids. Another developer's app, or a malformed id, is 404 APP_NOT_FOUND.
^\d{1,20}$Body
The app's name: the manifest's name rule (one line, at most 50), and at most 30 characters for the app to be listed.
Show child attributes
Show child attributes
One line, 10 to 100 characters.
Show child attributes
Show child attributes
Plain text, 100 to 1,500 characters: paragraphs and "- " lines only.
Show child attributes
Show child attributes
1 to 6 lines of what the app does.
6Show child attributes
Show child attributes
A marketplace category.
orders, delivery, marketing, messaging, reviews, storefront, catalog, analytics, finance, customer_service, productivity Words merchants may search for; duplicates are dropped.
52 - 30A listing image of kind icon.
^\d{1,20}$3 to 6 desktop screenshots and 0 to 4 mobile ones, in order.
Show child attributes
Show child attributes
Your support page. An https address on your own public domain (port 443, no IP address, no Tassyir domain).
512^https://Your privacy policy (required to submit). An https address on your own public domain (port 443, no IP address, no Tassyir domain).
512^https://An account the app needs on your own service, shown on the listing ("may be paid" when paid).
Show child attributes
Show child attributes
The languages your app's own pages support.
3ar, en, fr Response
The listing as it is now.
Your app's listing: the draft you edit and the live one.
Show child attributes
Show child attributes