Support tickets
Conversations with the support team. A ticket belongs to one project, and an API key reaches only the tickets of the project it was issued for. Each ticket carries its whole conversation as a timeline of events, oldest first; when support replies, the ticket moves to `PENDING` and the member who opened it is emailed. Your own reply moves it back to `OPEN`.
The tickets of the project your API key was issued for, most recently active first. The conversation is not included — fetch a ticket to read it.
Pass status to narrow the list to tickets in one state.
Auth: a project API key carrying support:read.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Query Parameters
Value in
- "OPEN"
- "PENDING"
- "IN_PROGRESS"
- "RESOLVED"
- "CLOSED"
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/support-tickets"{ "success": true, "data": [ { "id": "string", "organizationId": "string", "createdByUserId": "string", "subject": "string", "category": "TECHNICAL", "priority": "LOW", "status": "OPEN", "relatedResourceType": "app", "relatedResourceId": "string", "relatedResourceLabel": "string", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "closedAt": "2019-08-24T14:15:22Z", "organization": { "id": "string", "name": "string" }, "createdByUser": { "name": "string", "email": "[email protected]", "image": "string" } } ]}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}Opens a ticket in the project named by organizationId — the project's id, not its slug —
with description as the opening message. The support team is notified as soon as it is
created.
An API key can only open tickets in the project it was issued for; naming any other project
is refused with 403 API_KEY_WRONG_ORGANIZATION.
To point support at a specific resource, send relatedResourceType, relatedResourceId and
relatedResourceLabel together. The label is kept on the ticket as written, so the ticket
still reads sensibly after the resource is deleted.
Auth: a project API key carrying support:write.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/support-tickets" \ -H "Content-Type: application/json" \ -d '{ "organizationId": "string", "subject": "string", "description": "string", "category": "TECHNICAL", "priority": "LOW" }'{ "success": true, "data": { "id": "string", "organizationId": "string", "createdByUserId": "string", "subject": "string", "category": "TECHNICAL", "priority": "LOW", "status": "OPEN", "relatedResourceType": "app", "relatedResourceId": "string", "relatedResourceLabel": "string", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "closedAt": "2019-08-24T14:15:22Z", "organization": { "id": "string", "name": "string" }, "createdByUser": { "name": "string", "email": "[email protected]", "image": "string" }, "events": [ { "id": "string", "ticketId": "string", "authorUserId": "string", "authorRole": "customer", "type": "CREATED", "body": "string", "metadata": { "property1": null, "property2": null }, "createdAt": "2019-08-24T14:15:22Z", "authorUser": { "name": "string", "email": "[email protected]", "image": "string" } } ] }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}The ticket together with its whole conversation, oldest message first.
A ticket outside the project your API key was issued for answers 404 NOT_FOUND, the same as an id that does not exist.
Auth: a project API key carrying support:read.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/support-tickets/string"{ "success": true, "data": { "id": "string", "organizationId": "string", "createdByUserId": "string", "subject": "string", "category": "TECHNICAL", "priority": "LOW", "status": "OPEN", "relatedResourceType": "app", "relatedResourceId": "string", "relatedResourceLabel": "string", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "closedAt": "2019-08-24T14:15:22Z", "organization": { "id": "string", "name": "string" }, "createdByUser": { "name": "string", "email": "[email protected]", "image": "string" }, "events": [ { "id": "string", "ticketId": "string", "authorUserId": "string", "authorRole": "customer", "type": "CREATED", "body": "string", "metadata": { "property1": null, "property2": null }, "createdAt": "2019-08-24T14:15:22Z", "authorUser": { "name": "string", "email": "[email protected]", "image": "string" } } ] }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}Sets the ticket's status to CLOSED or back to OPEN — the only two changes a customer can
make. Sending the status the ticket already has changes nothing and returns it as it is.
A ticket outside the project your API key was issued for answers 404 NOT_FOUND, the same as an id that does not exist.
Auth: a project API key carrying support:write.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/v1/support-tickets/string" \ -H "Content-Type: application/json" \ -d '{ "status": "OPEN" }'{ "success": true, "data": { "id": "string", "organizationId": "string", "createdByUserId": "string", "subject": "string", "category": "TECHNICAL", "priority": "LOW", "status": "OPEN", "relatedResourceType": "app", "relatedResourceId": "string", "relatedResourceLabel": "string", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "closedAt": "2019-08-24T14:15:22Z", "organization": { "id": "string", "name": "string" }, "createdByUser": { "name": "string", "email": "[email protected]", "image": "string" }, "events": [ { "id": "string", "ticketId": "string", "authorUserId": "string", "authorRole": "customer", "type": "CREATED", "body": "string", "metadata": { "property1": null, "property2": null }, "createdAt": "2019-08-24T14:15:22Z", "authorUser": { "name": "string", "email": "[email protected]", "image": "string" } } ] }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}Adds your reply to the conversation. A ticket that was waiting on you (PENDING), or had
been RESOLVED or CLOSED, moves back to OPEN so it returns to the support queue.
A ticket outside the project your API key was issued for answers 404 NOT_FOUND, the same as an id that does not exist.
Auth: a project API key carrying support:write.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/support-tickets/string/replies" \ -H "Content-Type: application/json" \ -d '{ "body": "string" }'{ "success": true, "data": { "id": "string", "organizationId": "string", "createdByUserId": "string", "subject": "string", "category": "TECHNICAL", "priority": "LOW", "status": "OPEN", "relatedResourceType": "app", "relatedResourceId": "string", "relatedResourceLabel": "string", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "closedAt": "2019-08-24T14:15:22Z", "organization": { "id": "string", "name": "string" }, "createdByUser": { "name": "string", "email": "[email protected]", "image": "string" }, "events": [ { "id": "string", "ticketId": "string", "authorUserId": "string", "authorRole": "customer", "type": "CREATED", "body": "string", "metadata": { "property1": null, "property2": null }, "createdAt": "2019-08-24T14:15:22Z", "authorUser": { "name": "string", "email": "[email protected]", "image": "string" } } ] }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "details": { "property1": null, "property2": null }, "issues": null, "docsUrl": "http://example.com" }}Webhooks
Subscriptions to platform events. Each endpoint has a signing secret, returned once when it is created or rotated, that signs every delivery so you can verify it came from us. Repeated failures pause an endpoint automatically; resuming it re-queues what was held.
Web hosting
PHP websites on Apache. Each site runs in its own container, with its own disk, and answers on its own address under `cosmoner.com` as well as on the domains attached to it. The [Web Hosting guide](/docs/guides/web-hosting) explains the folder layout, SFTP and how PHP runs. A site's tier — `STARTER`, `GROWTH` or `SCALE` — sets its PHP workers, memory, CPU, disk, and how many domains and databases it can have. The limits are recorded on the site when it is created, so List sites shows what each one was given, and retuning a tier later does not change an existing site. Extra disk is bought in blocks on top of the tier when the site is created. Creating a site charges the project's payment method straight away; there is no checkout step. **Files.** A site's files are reached over SFTP, or over SSH where the site gives a shell, at the host, port and username Get connection details returns. The file calls here act on the same folder an SFTP login lands in and run as the site's own user, so what they create is owned by that login. Paths are relative to the home folder, with no leading slash, and an empty path is the home folder itself. They list folders, write text files of up to 1 MB, and create, move and delete files and folders; reading a file's contents, uploading and downloading are done in the control panel or over SFTP. **Domains.** Each domain attached to a site, other than its own address, is a domain you own or a subdomain of one, and it serves a folder, redirects, or is parked. The site's own address takes no subdomains. Attaching a domain is done in the control panel for now; the calls here list a site's domains, change what one does and detach it. **Databases.** A site can have MySQL databases, reached from the site only — not from outside, and not from other resources in the project. How many it can have, and how many connections each gets, depend on its tier. The SFTP password and each database's password are shown in the control panel, and changing a site's tier is done there too. Every call that changes a site, its domains, files or databases is refused to members with the viewer role, and to a project blocked over an unpaid invoice (`403 ACCOUNT_BLOCKED`).