Support reports

Send bugs, suggestions and questions from your application to the IntelligenceBox support queue. Include screenshots, documents and logs so support receives the context in a single ticket, labelled with the source application.

Auth service address

Use AUTH_URL, the authentication service URL for your installation. This endpoint stores tickets in the cloud support service; the box address and the key received when launching an embedded app cannot be used for this request.

Submit a report#

POSTAUTH_URL/api/v1/ticketsJWT / cloud API key

Creates an open ticket for the authenticated user. It appears in the existing support queue, filterable by sourceApp.

curl --request POST "$AUTH_URL/api/v1/tickets" \
  --header "Authorization: Bearer $REPORTS_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "sourceApp": "customer-portal",
    "type": "BUG",
    "title": "Exported PDF does not open",
    "description": "Exporting from the documents page produces an unreadable PDF.",
    "context": { "externalId": "PORT-123", "appVersion": "2.4.0" }
  }'

Authentication#

Send Authorization: Bearer <credential> with a cloud JWT signed by the auth service or an active, unexpired cloud API key. The user must exist and must not be banned. This endpoint does not accept the x-api-key header, better-auth session tokens or box-local JWTs.

Create a cloud key with the user’s JWT through POST /api/auth/api-key. The example expires after 30 days. Store the returned key in your application’s backend and use it as REPORTS_API_KEY.

Shell
curl --request POST "$AUTH_URL/api/auth/api-key" \
  --header "Authorization: Bearer $USER_JWT" \
  --header 'Content-Type: application/json' \
  --data '{"name":"customer-portal-reports","expiresIn":2592000}'

Keys with permissions: null retain full access. A restricted key must include {"tickets":["create"]}. Local box keys and embedded-app boxe_ keys are not cloud keys.

Who the ticket belongs to

The user, email and company come from the credentials and database. A shared key submits tickets as its owner; individual attribution requires each user’s credentials. Existing visibility rules for reporters, companies, partners and staff still apply.

Request body#

Send JSON with Content-Type: application/json. No tRPC or SuperJSON envelope is needed. Unknown fields are rejected: the caller cannot set the user, company, status, priority or support notes.

sourceAppstringrequired
Application name, 1–60 characters. Starts with an ASCII letter or digit; spaces, dots, underscores and hyphens are also allowed. Converted to lowercase, with spaces and underscores becoming hyphens: Portale Web → portale-web. This is a declared source, not a verified identity.
titlestringrequired
Title, 3–200 characters after trimming leading and trailing whitespace.
descriptionstringrequired
Description, 1–10,000 characters after trimming leading and trailing whitespace.
type"BUG" | "SUGGESTION" | "QUESTION"
BUG for a problem, SUGGESTION for a proposal, QUESTION for a question.Default: BUG.
brandstring
Brand associated with the report, up to 100 characters.
screenshotstring
Data URL starting with data:image/, up to 4,000,000 characters. Do not send a remote URL.
attachmentstring
One document as a data URL starting with data:, up to 8,000,000 characters.
attachmentNamestring
Document name, up to 255 characters. Directory components are removed; the fallback is allegato. Ignored when attachment is absent.
attachmentMimestring
Document MIME type, up to 255 characters. Ignored when attachment is absent.
uiLogsobject[]
Up to 500 entries per array. Each entry contains ts (max 40 characters), level (16), message (4,000) and optionally src (120).
serverLogsobject[]
Up to 500 entries per array. Each entry contains ts (max 40 characters), level (16), message (4,000) and optionally src (120).
contextobject
JSON metadata such as app version, page, reproduction steps or an ID in your system.

Size and usage limits#

The complete HTTP body must not exceed 20,000,000 bytes, even without Content-Length. Individual field limits also apply. Configured key quotas and rate limits are enforced; quota usage and the ticket insert share a transaction. Invalid payloads and failed saves do not consume quota.

Call from your backend

This is a server-to-server integration. Keep API keys in your backend: the auth service’s CORS policy does not enable arbitrary web origins.

Response#

A successful request returns 201 Created and Cache-Control: no-store. Store ticket.id in your system. Reading tickets and conversations remain available in the support dashboard and through the auth.tickets.* APIs.

201 Created
{
  "ticket": {
    "id": "cmexampleticket",
    "createdAt": "2026-09-07T10:00:00.000Z",
    "status": "OPEN",
    "sourceApp": "customer-portal"
  }
}

Repeated submissions

Every successful POST creates a new ticket. context.externalId is metadata and does not deduplicate requests. After a timeout, verify the outcome before submitting again.

Errors#

Errors return error.code and error.message. Validation errors also include error.issues with each field path and message. Internal database details are never returned.

400 Bad Request
{
  "error": {
    "code": "INVALID_JSON",
    "message": "Il corpo della richiesta non è JSON valido"
  }
}
  • 400INVALID_JSON / VALIDATION_ERROR — missing body, malformed JSON or invalid fields.
  • 401UNAUTHORIZED — missing, expired or invalid credentials, disabled key or unavailable account.
  • 403FORBIDDEN — the key does not grant tickets.create.
  • 413PAYLOAD_TOO_LARGE — body exceeds 20,000,000 bytes.
  • 415UNSUPPORTED_MEDIA_TYPE — use Content-Type: application/json.
  • 429RATE_LIMITED / QUOTA_EXCEEDED — rate limit or quota reached. RETRY_REQUEST — key changed or used concurrently: no ticket was created; retry with a short backoff if the key is still valid.
  • 500INTERNAL_ERROR — the report could not be saved.
Support reports | IntelligenceBox