REST API reference
Submit and manage user feedback in Looona programmatically from your application.
Base URL
http://localhost:3030/apiReplace localhost:3030 with your Looona server address when deployed.
Authentication
All API requests must be authenticated using an API key. Looona provides two types of API keys depending on where you call the API.
Safe to embed in client-side code — browser apps, mobile apps, SDKs. Scoped to report submission only.
Server-side only. Never expose in client-side code. Grants full API access.
How to get an API key
- Log in to your Looona dashboard as an Admin user
- Navigate to Settings → API Keys
- Click "Create API Key", give it a name, and choose the type
- Copy the generated key
- ⚠️ Save it securely — it won't be shown again!
Authentication header
x-api-key: pk_your_public_key_hereSecurity best practices
- Use
pk_keys in front-end code,sk_keys only on the server - Store secret keys as environment variables — never hard-code them
- Use separate API keys for different environments (dev, staging, production)
- Rotate keys periodically and revoke compromised ones immediately
Rate limiting
The report submission endpoint is rate-limited per IP address to prevent abuse.
POST /api/reports
Report submission
Limit is applied per IP address. Resets every 60 seconds.
Rate limit exceeded (429)
{
"error": "Too many requests. Please try again later."
}Submit a report
/api/reportsSubmit user feedback, bug reports, feature requests, ratings, or any other type of report to Looona.
Request headers
Content-Type: application/json
x-api-key: pk_your_public_key_hereRequest body
| Field | Type | Required | Description |
|---|---|---|---|
| report.name | string | ✅ Yes | Title of the report |
| report.content | JSON string | ✅ Yes | Report data as stringified JSON based on your reporter's template |
| report.reporter | UUID | ✅ Yes | Reporter ID (from Looona dashboard) |
| report.userIdentifier | string | No | User email, ID, or identifier |
| report.groupIdentifier | string | No | Group reports by app version, project, user group, etc. |
| report.extra | JSON string | No | Additional metadata (device info, browser, etc.) |
| report.isTest | boolean | No | Sandbox mode (doesn't trigger external actions) |
| shouldTriggerAction | boolean | No | Forward report to external service (default: true) |
💡 About the content field
The content field should be a stringified JSON object that matches the structure defined in your reporter's template.
For example, if your reporter template uses {{description}}, {{steps}}, and {{rating}}, your content JSON should include these fields.
Examples
Here are some real-world examples showing how to submit reports in different scenarios:
Example 1: Bug report
curl -X POST http://localhost:3030/api/reports \
-H "Content-Type: application/json" \
-H "x-api-key: pk_your_public_key_here" \
-d '{
"report": {
"name": "App crashes when uploading large files",
"content": "{\"description\": \"The app freezes and crashes when trying to upload files larger than 10MB\", \"steps\": \"1. Go to Upload page\\n2. Select file > 10MB\\n3. Click Upload\\n4. App crashes\", \"expectedBehavior\": \"File should upload successfully\"}",
"userIdentifier": "[email protected]",
"groupIdentifier": "premium-users",
"extra": "{\"browser\": \"Chrome 120\", \"os\": \"macOS 14.1\"}",
"reporter": "550e8400-e29b-41d4-a716-446655440000"
}
}'Example 2: Feature request
curl -X POST http://localhost:3030/api/reports \
-H "Content-Type: application/json" \
-H "x-api-key: pk_your_public_key_here" \
-d '{
"report": {
"name": "Add dark mode support",
"content": "{\"description\": \"Please add a dark mode option to reduce eye strain\", \"priority\": \"medium\"}",
"userIdentifier": "[email protected]",
"groupIdentifier": "beta-testers",
"reporter": "550e8400-e29b-41d4-a716-446655440000"
}
}'Example 3: User rating/feedback
curl -X POST http://localhost:3030/api/reports \
-H "Content-Type: application/json" \
-H "x-api-key: pk_your_public_key_here" \
-d '{
"report": {
"name": "5-star rating from satisfied user",
"content": "{\"rating\": 5, \"comment\": \"Love the new design!\", \"category\": \"UI/UX\"}",
"userIdentifier": "[email protected]",
"groupIdentifier": "v2.1.0",
"reporter": "550e8400-e29b-41d4-a716-446655440000"
}
}'Success response (200 OK)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalResource": {
"data": {
"url": "https://github.com/user/repo/issues/42",
"number": 42
}
}
}The id is the unique identifier of the created report. The externalResource.data contains the response from the external service (GitHub issue URL, Slack message timestamp, Jira ticket key, etc.).
Error response (400 Bad Request)
{
"error": "Invalid request body",
"details": [
{ "field": "name", "message": "Required" },
{ "field": "content", "message": "Required" }
]
}Testing & sandbox mode
Control whether reports trigger external actions using the isTest and shouldTriggerAction parameters.
How it works
Default behavior:
isTest: false | undefined→ Report is saved and forwarded to external services by defaultisTest: true→ Report is saved with "Sandbox" badge and NOT forwarded
Force trigger:
shouldTriggerAction: true→ Forces the report to be forwarded to external services (even ifisTest: true)
Sandbox example
curl -X POST http://localhost:3030/api/reports \
-H "Content-Type: application/json" \
-H "x-api-key: pk_your_public_key_here" \
-d '{
"report": {
"name": "Test report - ignore",
"content": "{\"test\": true}",
"reporter": "550e8400-e29b-41d4-a716-446655440000",
"isTest": true
},
"shouldTriggerAction": false
}'Testing checklist
- Create a test reporter in the Looona dashboard
- Generate an API key for testing
- Send test reports with
isTest: true - Verify reports appear in dashboard with "Sandbox" badge
- Check that external services are NOT triggered
- When ready, switch to
isTest: falsefor production
Ready to integrate?
Start collecting feedback from your users by integrating Looona's API into your application. Then customize how reports look with templates.