API Reference
Complete reference for the Issued API. All endpoints use JSON for requests and responses.
Table of Contents
Authentication
API Authentication Methods
The Issued API uses different authentication methods depending on the endpoint and use case.
Project API Keys (Form Submissions)
Used for form submissions and public-facing endpoints. Generated per project.
POST
/api/submissionsSubmit a form with API key authentication
Headers
Authorization: Bearer issued_abc123def456
Content-Type: application/jsonRequest Body
{
"projectId": "issued_abc123def456",
"fields": {
"subject": {
"visible": true,
"required": true
},
"description": {
"visible": true,
"required": true
}
}
}User Session (Dashboard APIs)
Used for project management and dashboard operations. Requires GitHub OAuth login.
GET
/api/projectsList projects (requires user session)
Webhook Signature Verification
Incoming webhooks from GitHub and email providers are verified using signatures.
// GitHub webhook signature verification
const signature = req.headers['x-hub-signature-256'];
const payload = JSON.stringify(req.body);
const expectedSignature = crypto
.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET)
.update(payload)
.digest('hex');Form Submissions
POST /api/submissions
Submit a support form with embed-level field configuration. This is the core endpoint for all form submissions.
POST
/api/submissionsBasic form submission with visible fields
Request Body
{
"projectId": "issued_abc123def456",
"fields": {
"subject": {
"visible": true,
"required": true
},
"description": {
"visible": true,
"required": true
},
"email": {
"visible": true,
"required": false
}
}
}Field Configuration Reference
| Property | Type | Description |
|---|---|---|
visible | boolean | Whether field appears in the form UI |
required | boolean | Whether visible fields must be completed |
value | any | Pre-populated value (works for visible and hidden fields) |
Standard Fields
Form Fields
subject- Issue title (max 200 chars)description- Issue description (max 5000 chars)email- User email for notificationsname- User display name
GitHub Fields
labels- Comma-separated GitHub labelsassignees- Comma-separated GitHub usernamesmilestone- GitHub milestone number
Project Management
GET /api/projects
List all projects for the authenticated user with optional filtering and pagination.
GET
/api/projects?page=1&limit=10&search=my-appList projects with pagination and search
POST /api/projects
Create a new project and link it to a GitHub repository or Linear team.
POST
/api/projectsCreate a new project with security configuration
Request Body
{
"name": "E-commerce Support",
"githubRepo": "ecommerce-app",
"githubOwner": "mycompany",
"notificationPreferences": {
"email": true,
"emailAddress": "support@mycompany.com",
"webhook": true,
"webhookUrl": "https://mycompany.com/webhooks/issued",
"slack": false
},
"whitelistedDomains": [
"mycompany.com",
"*.staging.mycompany.com",
"localhost:3000"
],
"whitelistedBundleIds": [
"com.mycompany.ecommerce",
"com.mycompany.ecommerce.staging"
],
"defaultLabels": [
"customer-support",
"auto-created"
],
"defaultAssignees": [
"support-team"
]
}GET /api/projects/{id}
Get detailed information about a specific project.
GET
/api/projects/550e8400-e29b-41d4-a716-446655440000Get project details
PUT /api/projects/{id}
Update project configuration including security settings and notification preferences.
PUT
/api/projects/550e8400-e29b-41d4-a716-446655440000Update project configuration
Request Body
{
"name": "Updated App Support",
"notificationPreferences": {
"email": true,
"emailAddress": "newsupport@mycompany.com",
"webhook": true,
"webhookUrl": "https://api.mycompany.com/webhooks/issued",
"slack": true,
"slackWebhookUrl": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
},
"whitelistedDomains": [
"myapp.com",
"*.staging.myapp.com",
"*.preview.myapp.com"
],
"whitelistedBundleIds": [
"com.mycompany.myapp",
"com.mycompany.myapp.beta"
],
"defaultLabels": [
"customer-reported",
"needs-triage"
],
"defaultAssignees": [
"support-team",
"engineering-lead"
]
}Webhooks
POST /api/webhooks/github
Handles GitHub webhook events, particularly issue comment notifications.
POST
/api/webhooks/githubGitHub issue comment webhook
Headers
X-GitHub-Event: issue_comment
X-Hub-Signature-256: sha256=...
Content-Type: application/jsonRequest Body
{
"action": "created",
"issue": {
"id": 1,
"number": 42,
"title": "Support Request: Cannot login to account",
"body": "**Email**: customer@example.com\n**Name**: Jane Smith\n**Description**: I'm unable to login to my account...",
"state": "open",
"html_url": "https://github.com/mycompany/myapp/issues/42"
},
"comment": {
"id": 123456789,
"body": "Hi Jane, thanks for reaching out. Can you please try clearing your browser cache and cookies?",
"user": {
"login": "support-team",
"avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4"
},
"created_at": "2024-01-17T12:30:00Z",
"html_url": "https://github.com/mycompany/myapp/issues/42#issuecomment-123456789"
},
"repository": {
"name": "myapp",
"full_name": "mycompany/myapp"
}
}Email Reply Processing
How email replies are processed and converted to GitHub comments.
Reply Email Format
To: reply+PROJ-1234@issued.dev Subject: Re: Support Request #PROJ-1234 This is a reply from the customer that will be posted as a GitHub comment.
POST
/api/webhooks/emailEmail reply webhook processing
Request Body
{
"messageId": "msg_abc123def456",
"to": "reply+PROJ-1234@issued.dev",
"from": "customer@example.com",
"subject": "Re: Support Request #PROJ-1234",
"text": "Thanks for the quick response! I tried clearing the cache and it worked. The issue is resolved now.",
"html": "<p>Thanks for the quick response! I tried clearing the cache and it worked. The issue is resolved now.</p>",
"receivedAt": "2024-01-17T13:15:00Z"
}File Uploads
POST /api/upload
Upload files for form submissions. Supports images, documents, and text files.
POST
/api/uploadUpload files with form submissions
Request Body
{
"files": [
{
"name": "screenshot.png",
"type": "image/png",
"size": 1024576,
"data": "base64EncodedImageData..."
},
{
"name": "error.log",
"type": "text/plain",
"size": 8192,
"data": "base64EncodedLogData..."
}
],
"submissionId": "550e8400-e29b-41d4-a716-446655440000"
}File Restrictions
Size Limits
- Maximum file size: 10MB per file
- Maximum total size: 50MB per submission
Supported Formats
- Images: JPEG, PNG, GIF, SVG
- Documents: PDF, DOC, DOCX
- Text: TXT, LOG, CSV
Notifications
GET/POST /api/notifications
Manage notification preferences and test notification delivery.
GET
/api/notifications?projectId=550e8400-e29b-41d4-a716-446655440000Get notification preferences for a project
Health Monitoring
GET /api/health
Check system health and service status for monitoring and debugging.
GET
/api/health?service=all&detailed=trueCheck all services with detailed information
Error Handling
Standard Error Response Format
All API endpoints return errors in a consistent format with appropriate HTTP status codes.
Error Response Structure
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "Request validation failed",
"details": {
"field": "subject",
"reason": "Field is required but not provided"
}
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_abc123"
}Common Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | VALIDATION_FAILED | Request data is invalid or missing required fields |
| 401 | UNAUTHORIZED | Authentication required or invalid credentials |
| 403 | INVALID_ORIGIN | Request origin not whitelisted for this project |
| 404 | PROJECT_NOT_FOUND | Specified project does not exist |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests from this IP address |
| 500 | INTERNAL_ERROR | Unexpected server error |
Rate Limiting
API Rate Limits
All API endpoints are subject to rate limiting to ensure fair usage and system stability.
Rate Limit Tiers
Free Tier
- 10 submissions/hour per IP
- 100 API calls/hour per user
- 1 project maximum
Basic Plan
- 100 submissions/hour per IP
- 1,000 API calls/hour per user
- 1 project
Pro Plan
- 1,000 submissions/hour per IP
- 10,000 API calls/hour per user
- Unlimited projects
Rate Limit Headers
All API responses include rate limit information in the headers:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1705316400 X-RateLimit-Window: 3600