Parameters
1 query
Query parameters
· 1issueKeystringRequiredIssue key (e.g. "PROJ-123").
PROJ-123Returns full issue detail including description, project info, assignee, reporter, parent issue, due date, and linked URLs. Returns { exist: false } if the issue is not found.
1 query
issueKeystringRequiredIssue key (e.g. "PROJ-123").
PROJ-1231 status code documented
idstringRequiredIssue key.
internalIdnumberRequiredInternal numeric ID.
externalIdstringRequiredImmutable 16-char alphanumeric public identifier (pm__issue.external_id). Used in customer-facing URLs (support portal, e-mail deep links, [BKH-ISSUE:xxxxxxxxxxxxxxxx] tokens) and for cross-system references — never changes across the ticket's lifetime, unlike issueKey which is tied to the project prefix and could theoretically re-key on a merge.
issueKeystringRequiredIssue key (e.g. "PROJ-123").
subjectstringRequiredIssue subject/title.
descriptionstringRequiredIssue description (HTML).
internalDescriptionstring | nullRequiredInternal notes visible only to team members.
aiSummarystring | nullRequiredLLM-produced short paraphrase of the description in the reporter's language (~400 chars). Read-only in the admin UI — writes only originate from the inbound-mail classifier, updateIssue regen when the description is edited, or the explicit /bff/issue/generate-summary button. null when no summary has been generated yet.
prioritynumberRequiredPriority (1-5).
priorityLabelstringRequiredHuman-readable priority label.
velocitynumberRequiredEffort/complexity score (0..100). DB default 25. Anchors: 1 trivial, 25 default ~20 min, 50 ~4 h, 75 ~2 days, 90+ split, 100 unsolvable/unclear.
projectIdnumberRequiredInternal project id — link the admin breadcrumb to /project/{projectId}.
projectKeystringRequiredProject key (e.g. "PROJ").
projectNamestringRequiredProject display name.
typeobjectRequiredidnumberRequiredIssue type ID (pm__issue_type.id).
codestringRequiredStable slug (story, epic, task, sub_task, bug, …). Admin resolves the localized label from its dictionary.
iconstring | nullRequiredLucide icon name to render alongside the subject.
statusobjectRequiredidnumberRequiredStatus ID.
labelstringRequiredStatus display label (localized to the viewing organisation).
categoryIdnumberRequiredStatus category ID (1=new, 2=progress, 3=waiting, 4=done).
categoryCodestringRequiredStatus category code.
assigneeobject | nullRequiredidnumberRequiredContact ID.
externalIdstring | nullRequiredPublic contact identifier used in admin URLs (/contact/{externalId}) and in /bff/contact/detail?customerId=.... null for legacy rows that predate the external-id backfill; the UI should render the name without a link in that case.
namestringRequiredFull name.
emailstring | nullRequiredContact e-mail. null for phone-only contacts (no e-mail registered) and for contacts anonymised via GDPR. UI should fall back to name or the contact ID.
avatarUrlstringOptionalAvatar image URL resolved via core__blob. Falls back through the contact's own avatar_blob_id, then the linked member user's contact avatar_blob_id. Omitted when neither has an avatar uploaded.
reporterobject | nullRequiredidnumberRequiredContact ID.
externalIdstring | nullRequiredPublic contact identifier used in admin URLs (/contact/{externalId}) and in /bff/contact/detail?customerId=.... null for legacy rows that predate the external-id backfill; the UI should render the name without a link in that case.
namestringRequiredFull name.
emailstring | nullRequiredContact e-mail. null for phone-only contacts (no e-mail registered) and for contacts anonymised via GDPR. UI should fall back to name or the contact ID.
avatarUrlstringOptionalAvatar image URL resolved via core__blob. Falls back through the contact's own avatar_blob_id, then the linked member user's contact avatar_blob_id. Omitted when neither has an avatar uploaded.
isSpamboolean | nullRequiredSpam classification. Null = not yet classified.
parentIdnumber | nullRequiredInternal ID of the parent issue (for sub-tasks or merged children).
parentobject | nullRequiredPopulated when this issue has been merged into another via /bff/issue/merge (or filed as a sub-task with a parent). The admin renders a prominent "merged into" callout linking here. null for regular top-level issues.
issueKeystringRequiredParent issue key — use in /issue/{issueKey} for the FE link.
subjectstringRequiredParent subject, rendered inline in the "merged into" callout.
statusCategoryCodestringRequiredCanonical bucket code (new / progress / waiting / done) so the FE can dot-color the callout.
dueDateDate | string | string | number | nullRequiredDue date.
Due date.
testUrlstring | nullRequiredURL to test environment.
documentationUrlstring | nullRequiredURL to documentation.
humanOnlybooleanRequiredWhen true, the AI orchestrator (and any future automated agent) aborts and never touches this ticket. Set by operators for tickets that need human judgement (legal escalation, incident, VIP).
securedTicketbooleanRequiredWhen true, the ticket is marked confidential (pm__issue.secured_ticket) and only ORG ROOT members can see it. Regular members receive { exist: false } from /bff/issue/detail for this issue and never see it in lists or counts. Written by the AI classifiers (mail + triage) on the way in — a Comgate payment-status mail auto-flags the issue as secured — and toggled by root operators from the sidebar.
insertedDateDate | string | string | numberRequiredWhen the issue was created.
When the issue was created.
updatedDateDate | string | string | number | nullRequiredLast update timestamp.
Last update timestamp.
attachmentsobject[]RequiredFiles linked to the issue via pm__issue_attachment. Empty when the issue has none.
blobTokenstringRequiredcore__blob.token — pass to
filenamestringRequiredOriginal filename as stored on the blob. Never null — when the blob was ingested without a filename (e.g. an inbound e-mail attachment with a missing Content-Disposition: filename=…), the endpoint substitutes a priloha.<ext> placeholder derived from the MIME type.
contentTypestringOptionalMIME type.
sizenumberRequiredFile size in bytes.
downloadUrlstringRequiredSigned direct-download URL to the storage bucket.
positionnumberRequiredDisplay order within the issue (1-based).
sourceEmailsobject[]RequiredInbound-mail rows linked via brj__emailer_received_email.issue_id. Ordered oldest first — the first entry is the originating mail that lifted the ticket. Empty when the issue was not created from mail.
externalIdstringRequiredPublic 16-char identifier of the inbound mail — use in /emailer/received/:externalId for the admin link.
subjectstringRequiredSubject as received from Resend.
fromAddressstringRequiredEnvelope From address.
receivedAtDate | string | string | numberRequiredWhen Resend received the message.
When Resend received the message.
ipnull | objectRequiredReporter geolocation snapshot resolved from the request IP at ticket creation. Same shape as the order-detail ip block so the admin can reuse the same rendering component. null for tickets created without request-time IP context (cron, mail pipeline, manual admin entry). Admin hides the block for 127.0.0.1.
ipstringRequiredAccepted formats:
1.1.1.1 (4 octets, 0–255, no leading zeros).2001:0db8:0000:0000:0000:0000:0000:0001, zero-compressed 2001:db8::1, IPv4-mapped ::ffff:1.2.3.4, or scoped literals. Both upper- and lower-case hex are accepted.Server-side canonicalization (ipNormalize in core/src/lib/network/ipNormalize.ts):
::ffff:X.X.X.X is unwrapped to plain IPv4 (RFC 4291 §2.5.5.2) so 1.2.3.4 and ::ffff:1.2.3.4 share one brj__geo_ip row.::1, 0.0.0.0, localhost, empty string) collapse to 127.0.0.1.127.0.0.1 (loopback).On the wire: every response returns the canonicalized form — clients can safely rely on lowercase IPv6 and the plain-IPv4 unwrap when de-duping or joining. Server-originated writers (activity log, session log, ban list) resolve the visitor IP via resolveClientIp / resolveClientIpOrNull — always native IPv6 on Vercel Edge (there is no auto-mapping to ::ffff:X.X.X.X).
Enrichment: the system resolves reverse DNS, geolocation, ASN, mobile/proxy/hosting/Tor flags via our VikiTron GEO/IP resolver for both address families. Learn more
1.1.1.12001:4860:4860::8888citystring | nullRequiredCity name (brj__geo_ip_city.city).
countrystring | nullRequiredCountry name (brj__geo_ip_city.country).
countryRegionstring | nullRequiredISO 3166-2 country subdivision (brj__geo_ip_city.country_region).
latitudenumber | nullRequiredCity-center latitude (brj__geo_ip_city.latitude).
longitudenumber | nullRequiredCity-center longitude (brj__geo_ip_city.longitude).
hostnamestring | nullRequiredReverse-DNS hostname (brj__geo_ip.hostname), when resolved.
timezonestring | nullRequiredIANA timezone (cas__timezone.timezone) resolved via brj__geo_ip.timezone_id.
mobilebooleanRequiredtrue when ip-api flagged the IP as a mobile carrier network. Defaults to false when the enrichment has not yet run.
proxybooleanRequiredtrue when ip-api flagged the IP as an anonymising proxy / VPN. Defaults to false when the enrichment has not yet run.
hostingbooleanRequiredtrue when ip-api flagged the IP as hosting infrastructure (data-center, cloud provider). Defaults to false when the enrichment has not yet run.
torboolean | nullRequiredtrue when the IP is on the TOR exit-node list at the time the ticket was created. null when TOR classification has not yet been resolved (distinct from a known non-TOR false).
originChannelnull | objectRequiredEntry point that created the issue, resolved via pm__issue.origin_channel_id → pm__issue_origin_channel. null for pre-migration rows and paths that do not yet pass a channel code. Rendered as "Zdroj: …" in the admin sidebar Details card.
codestringRequiredStable machine identifier of the entry point (contact_form, mail_in, admin, api, cron, agent) from pm__issue_origin_channel.code. Opaque to the admin — used as a lookup key into the FE i18n dictionary.
labelstringRequiredCanonical Czech label from pm__issue_origin_channel.label. Used as a fallback when the admin has no translation for the code.
localestringRequiredISO 639-1 code (e.g. "cs", "en") of the language this issue is conducted in — the value of pm__issue.locale_id joined to core__localization_locale.locale. Populated deterministically at INSERT (reporter → org fallback) and refined by AI during triage; NOT NULL invariant, so every issue has a real code. The admin renders it as "EN — angličtina" (short code + Intl.DisplayNames full name in the operator's UI locale) in the sidebar Details card.
exist"false"Required{
"id": "example_id",
"internalId": 0,
"externalId": "example_externalId",
"issueKey": "example_issueKey",
"subject": "example_subject",
"description": "example_description",
"priority": 0,
"priorityLabel": "example_priorityLabel",
"velocity": 0,
"projectId": 0,
"projectKey": "example_projectKey",
"projectName": "example_projectName",
"type": {
"id": 0,
"code": "example_code"
},
"status": {
"id": 0,
"label": "example_label",
"categoryId": 0,
"categoryCode": "example_categoryCode"
},
"humanOnly": false,
"securedTicket": false,
"attachments": [
{
"blobToken": "example_blobToken",
"filename": "example_filename",
"contentType": "example_contentType",
"size": 0,
"downloadUrl": "example_downloadUrl",
"position": 0
}
],
"sourceEmails": [
{
"externalId": "example_externalId",
"subject": "example_subject",
"fromAddress": "example_fromAddress"
}
],
"locale": "example_locale"
}GET /bff/issue/detail
curl -X GET "https://api.bizkithub.com/bff/issue/detail?issueKey=PROJ-123" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY"All BizKitHub public API endpoints require authentication via API key.