Product Guide

Guide

Everything you need to know about Signalshoot.

API Reference

Endpoint

Endpoint
POST https://api.signalshoot.com/v1/ingest/{app_id}

Headers

Content-Typeapplication/json
X-API-KeyLive keys: fb_live_ / Test keys: fb_test_

Request Body

typerequiredAny string up to 50 characters. This categorizes the feedback. Common values: "bug" for bug reports, "feedback" for feature requests, "inquiry" for support questions. But you are not limited to these — use any string that fits your app. Examples: "crash" for crash reports, "praise" for positive feedback, "review" for imported store reviews, "onboarding-issue" for first-run problems, or even values in your own language. Every unique type you send automatically appears as a filter button in the dashboard inbox. No configuration needed — just start sending and the dashboard adapts.
messagerequiredThe actual feedback text from the user. Max 5,000 characters. This is the main content displayed in the inbox and detail view. A good feedback message is whatever the user typed — do not filter or truncate it on the client side before sending. If your app has a multi-field form (e.g. separate fields for "what happened" and "steps to reproduce"), concatenate them into one message string. The message is searchable in the inbox, translatable via one-click translation, and included in data exports.
channeloptionalA string (max 100 chars) that identifies where in your app the feedback was sent from. Defaults to "default" if omitted. Real-world examples: "contact-form" (main contact page), "settings-feedback" (feedback button in settings), "onboarding-survey" (post-onboarding questionnaire), "shake-report" (shake-to-report gesture), "in-app-review" (triggered after a specific action), "checkout-support" (help button during checkout). Each unique channel appears as a filter in the dashboard, letting you see which parts of your app generate the most feedback. Use consistent naming — the dashboard treats "contact" and "Contact" as separate channels.
user_idoptionalYour app's identifier for the user who submitted the feedback. Including this enables two features: (1) you can reply to the user from the dashboard, and (2) the user's app can call the replies endpoint to fetch your response. If omitted, the feedback is anonymous and replies are disabled. Privacy considerations: this ID is stored as-is in the database. Do not send email addresses or real names — use an opaque identifier like a UUID or internal database ID. If your app uses sequential integer IDs (1, 2, 3...), another user could guess IDs and call the replies endpoint to read other users' feedback. Use UUIDs or random strings to prevent this. The user_id is visible to you in the feedback detail view, helping you identify repeat reporters.
parent_idoptionalOptional string. Set this to the ID of an existing feedback entry to create a threaded follow-up instead of a new feedback. When parent_id is provided, the message is added as a reply with sender "user" to the specified feedback thread. The parent feedback must exist and belong to the same app — otherwise a 404 is returned. If the parent feedback was previously resolved or archived, its status is automatically reopened to "in_progress" so the conversation reappears in the active inbox. Follow-up messages sent with parent_id do not count toward your monthly feedback limit. Only the original submission counts. This is how you implement back-and-forth conversations: the user sends initial feedback (no parent_id), you reply from the dashboard, the user sees your reply via the replies endpoint, and the user responds again by sending a new request with parent_id set to the original feedback ID.
metadataoptionalA JSON object containing any additional context you want to attach. There is no fixed schema — include whatever helps you understand the report. Common fields: app_version ("2.1.0"), os ("iOS 18.2" or "Android 15"), device ("iPhone 15" or "Pixel 8"), screen ("MapScreen" or "SettingsView"), locale ("ja-JP"), user_plan ("premium" or "free"), build_number ("1847"), network ("wifi" or "cellular"). You can also include app-specific data: selected_item_count, time_since_install, feature_flags_enabled, etc. Metadata is displayed as a key-value table in the feedback detail view and is included in JSON exports with the object structure preserved. In CSV exports, metadata appears as a raw JSON string.

Response (201 Created)

Response example — 201 Created
{
  "id": "fb_omcizyzblfu2",
  "status": "received",
  "created_at": "2026-04-06T12:00:00Z"
}

Error Responses

400Invalid request body. Returned when: the JSON cannot be parsed (malformed syntax), the required "type" field is missing or empty or exceeds 50 characters, the required "message" field is missing or empty or exceeds 5,000 characters, or the "channel" field exceeds 100 characters. The response body includes an error code (e.g. "invalid_type", "invalid_message", "invalid_body") and a human-readable message describing the specific issue.
401Missing or invalid API key. Returned when: the X-API-Key header is not present in the request, or the provided key does not match any valid key (live or test) for the specified app. The key is verified by comparing SHA-256 hashes — the actual key is never stored in plain text. If you recently regenerated your key, make sure you are using the new one; the old key is rejected immediately after regeneration.
404App not found. Returned when the app_id in the URL does not match any registered app in the database. Double-check that you are using the correct App ID from your Settings page (it looks like fb_a1b2c3d4e5). This error is also returned when using parent_id if the referenced parent feedback does not exist or does not belong to the specified app.
429Monthly feedback limit exceeded. Returned when you have reached the maximum number of new feedback submissions for your current billing period. Free: 200/month, Pro: 1,000/month, Infinite: unlimited. The count resets on the first day of each calendar month. Only new feedback submissions count — threaded follow-ups (sent with parent_id) and developer replies do not count. Test-key submissions also do not count. Existing feedback is not affected; you can still read, triage, and reply to everything already in your inbox. Upgrade your plan from Settings to increase the limit immediately.

Replies Endpoint

Example — Replies request
GET https://api.signalshoot.com/v1/feedback/{app_id}/replies?user_id=user_123
X-API-Key: fb_live_YOUR_KEY

GET /api/v1/feedback/:app_id/replies?user_id=xxx — returns all feedback entries for the specified user, each with its replies array. Requires the same X-API-Key header as the ingest endpoint. The response is an array of feedback objects, each containing: id, type, channel, message, status, created_at, and a replies array. Each reply in the array has: id (string), sender ("developer" or "user"), message (string), and created_at (ISO timestamp). Replies are ordered chronologically within each feedback entry. Use this endpoint in your app to show users the responses you have written from the dashboard, or to display the full conversation thread if you support threaded follow-ups via parent_id.

Response example

Response example — Replies
{
  "feedbacks": [
    {
      "id": "fb_omcizyzblfu2",
      "type": "bug",
      "channel": "contact",
      "message": "The map doesn't load after the update",
      "status": "in_progress",
      "created_at": "2026-04-06T12:00:00Z",
      "replies": [
        {
          "id": "rp_abc123def456",
          "sender": "developer",
          "message": "Thanks for reporting. We're looking into it.",
          "created_at": "2026-04-06T14:30:00Z"
        },
        {
          "id": "rp_xyz789ghi012",
          "sender": "user",
          "message": "Still broken on v2.1.1",
          "created_at": "2026-04-07T09:00:00Z"
        }
      ]
    }
  ]
}

Plan Limits

Free200 feedbacks/month, 1 app
Pro1,000 feedbacks/month, 5 apps
InfiniteUnlimited