curl --request POST \
--url https://api.tassyir.io/developer/apps/{appId}/versions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"manifest": {},
"bundle": {
"main": "<string>",
"files": [
{
"path": "<string>",
"content": "<string>"
}
]
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
manifest: {},
bundle: {main: '<string>', files: [{path: '<string>', content: '<string>'}]}
})
};
fetch('https://api.tassyir.io/developer/apps/{appId}/versions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"id": "<string>",
"version": 4503599627370496,
"apiVersion": "<string>",
"scopes": [
"<string>"
],
"optionalScopes": [
"<string>"
],
"webhookTopics": [
"<string>"
],
"allowedHosts": [
"<string>"
],
"reviewState": "<string>",
"current": true,
"releasedAt": "2023-11-07T05:31:56Z",
"createdAt": "2023-11-07T05:31:56Z",
"hosting": {
"bundleSha256": "<string>",
"bundleBytes": 4503599627370495,
"files": 4503599627370496,
"main": "<string>",
"lockfile": "<string>",
"scan": {
"status": "pending",
"dispatchedAt": "2023-11-07T05:31:56Z",
"finishedAt": "2023-11-07T05:31:56Z",
"failureCode": "SCAN_DISPATCH_FAILED",
"reasons": [
"<string>"
]
},
"deploy": {
"staging": {
"status": "none",
"deployedAt": "2023-11-07T05:31:56Z",
"errorCode": "SCAN_DISPATCH_FAILED"
},
"production": {
"status": "none",
"deployedAt": "2023-11-07T05:31:56Z",
"errorCode": "SCAN_DISPATCH_FAILED"
}
},
"checks": [
{
"id": "<string>",
"status": "pass",
"summary": "<string>",
"findings": [
{
"rule": "<string>",
"severity": "error",
"file": "<string>",
"line": 4503599627370495,
"message": "<string>"
}
],
"truncated": true
}
],
"review": {
"status": "pass",
"model": "<string>",
"summary": "<string>",
"concerns": [
{
"severity": "high",
"file": "<string>",
"message": "<string>"
}
],
"truncated": true
},
"rejectionReason": "<string>"
},
"manifest": {}
}
}{
"code": "APP_BUNDLE_INVALID",
"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_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>"
}{
"code": "APP_BUNDLE_STORAGE_FAILED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<string>"
}
],
"path": "<string>",
"requestId": "<string>"
}Upload a version of the app's manifest
The body is at most 128 KB (8 MB + 128 KB while Tassyir Hosting is on) and nests at most 16 levels (its own parser). The validator checks the manifest (every error at once); handle must be the app’s; a manifest identical to the latest version’s (and, hosted, the same bundle) is refused. An external version is numbered latest + 1, approved and current at once. A hosted version (hosting.mode = "tassyir", while Tassyir Hosting is on) carries its bundle, stored before the version is created scanning; it is scanned, uploaded and released by the hosting pipeline. 30 uploads per developer per hour, 10 hosted a day.
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 POST \
--url https://api.tassyir.io/developer/apps/{appId}/versions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"manifest": {},
"bundle": {
"main": "<string>",
"files": [
{
"path": "<string>",
"content": "<string>"
}
]
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
manifest: {},
bundle: {main: '<string>', files: [{path: '<string>', content: '<string>'}]}
})
};
fetch('https://api.tassyir.io/developer/apps/{appId}/versions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": {
"id": "<string>",
"version": 4503599627370496,
"apiVersion": "<string>",
"scopes": [
"<string>"
],
"optionalScopes": [
"<string>"
],
"webhookTopics": [
"<string>"
],
"allowedHosts": [
"<string>"
],
"reviewState": "<string>",
"current": true,
"releasedAt": "2023-11-07T05:31:56Z",
"createdAt": "2023-11-07T05:31:56Z",
"hosting": {
"bundleSha256": "<string>",
"bundleBytes": 4503599627370495,
"files": 4503599627370496,
"main": "<string>",
"lockfile": "<string>",
"scan": {
"status": "pending",
"dispatchedAt": "2023-11-07T05:31:56Z",
"finishedAt": "2023-11-07T05:31:56Z",
"failureCode": "SCAN_DISPATCH_FAILED",
"reasons": [
"<string>"
]
},
"deploy": {
"staging": {
"status": "none",
"deployedAt": "2023-11-07T05:31:56Z",
"errorCode": "SCAN_DISPATCH_FAILED"
},
"production": {
"status": "none",
"deployedAt": "2023-11-07T05:31:56Z",
"errorCode": "SCAN_DISPATCH_FAILED"
}
},
"checks": [
{
"id": "<string>",
"status": "pass",
"summary": "<string>",
"findings": [
{
"rule": "<string>",
"severity": "error",
"file": "<string>",
"line": 4503599627370495,
"message": "<string>"
}
],
"truncated": true
}
],
"review": {
"status": "pass",
"model": "<string>",
"summary": "<string>",
"concerns": [
{
"severity": "high",
"file": "<string>",
"message": "<string>"
}
],
"truncated": true
},
"rejectionReason": "<string>"
},
"manifest": {}
}
}{
"code": "APP_BUNDLE_INVALID",
"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_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>"
}{
"code": "APP_BUNDLE_STORAGE_FAILED",
"message": "<string>",
"statusCode": 123,
"fix": "<string>",
"errors": [
{
"code": "<string>",
"path": "<string>",
"message": "<string>",
"fix": "<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
tassyir.app.toml exactly as a TOML parser returns it, handed to the manifest validator untouched (rules: https://developers.tassyir.io/guides/manifest; JSON Schema: @tassyir/app-manifest/schemas/manifest.2026-10.schema.json). Anything else is 400 APP_MANIFEST_INVALID.
A hosted version's code (required for hosting.mode = "tassyir", refused otherwise): { main, files: [{ path, content }], lockfile? }, text modules only, at most 100 files and 3 MB; checked by the bundle validator (every error at once, 400 APP_BUNDLE_INVALID).
Show child attributes
Show child attributes
Response
The new version, with its normalised manifest.
A version of an app, with its normalised manifest.
Show child attributes
Show child attributes