Everything you need to know about Signal shoot
If you use an AI coding assistant — Claude Code, Cursor, GitHub Copilot, Windsurf, or any other — you don't need to write integration code yourself. Copy a prompt below, paste it into your AI assistant, and get production-ready code tailored to your app.
1. Copy one of the prompts below 2. Replace [React Native / Flutter / Swift / Kotlin / ...] at the end with your actual stack 3. Paste it into your AI coding assistant and run it 4. Review the generated code and replace the placeholder API keys with your own
Tip
Pass this guide's URL (/guide?tab=api) as additional context to your AI assistant. This helps it generate more accurate code with proper error handling and authentication details.
Add a feedback button to my app that sends one-way user feedback to Signal shoot.
No replies, no conversations.
Endpoint: POST https://api.signalshoot.com/v1/ingest/MY_APP_ID
Headers:
- Content-Type: application/json
- X-API-Key: (see below)
API keys:
- During development: fb_test_MY_KEY
- In production: fb_live_MY_KEY
Request body (JSON):
- type: required string, max 50 chars. Any string is allowed and displayed as-is in dashboard filters. Common examples: "bug", "feedback", "inquiry".
- message: required string, max 5000 chars
- channel: optional string (e.g. "contact", "report")
- metadata: optional object (e.g. { app_version, os, device, screen })
- Do NOT include user_id unless I explicitly need two-way replies
Success response (201):
{ "id": "fb_...", "status": "received", "created_at": "..." }
Error handling:
- Handle 400, 401, 404, and 429 responses
- Do NOT blindly retry 4xx responses
- 429 "too_many_requests": burst limit — wait at least 60 seconds before retrying
- 429 "monthly_limit_exceeded": monthly limit reached. Writes are refused until the next billing period. Show an upgrade prompt.
UI requirements:
- Disable the submit button until a response is received to prevent double submission
- For web apps: NEVER embed a live or test key (fb_live_*, fb_test_*) in client-side JavaScript. Either (a) proxy through your backend with a live key, or (b) for browser-only one-way ingest, use a publishable key (fb_pub_*) from dashboard Settings. Publishable keys are safe for browsers because they are write-only, Origin-allowlisted, and per-IP rate-limited.
Return production-ready code for [React Native / Flutter / Swift / Kotlin / ...].Add feedback with two-way reply support to my app using Signal shoot.
Security requirements:
- Web apps MUST use a backend proxy for live/test keys — do not expose them in client-side JavaScript. (For browser-only ingest, use a publishable key fb_pub_* — but pub keys cannot use user_id or parent_id, so they are not suitable for two-way replies.)
- For mobile apps, backend proxy is recommended for the safest setup
- user_id MUST be an opaque identifier (UUID/ULID/random string). NEVER use sequential database IDs.
- parent_id MUST only use IDs returned by previous Signal shoot API responses. NEVER accept arbitrary client input. The parent must belong to the same app_id.
- Do not replace the original feedback id (fb_...) with the returned reply id (rp_...). Always use the original feedback id as parent_id for future follow-ups.
- Store the API key server-side whenever possible.
- HMAC SIGNATURE (required on every request that carries user_id or parent_id): compute X-Signal-User-Id-Signature = HMAC-SHA256(signing_secret, user_id_utf8_bytes) and send it as a 64-character hex digest. The signing secret is visible in dashboard Settings → Signing Key. Without this header, the API returns 401 signature_required.
Endpoint: POST https://api.signalshoot.com/v1/ingest/MY_APP_ID
Headers:
- Content-Type: application/json
- X-API-Key: fb_test_MY_KEY (development) / fb_live_MY_KEY (production)
- X-Signal-User-Id-Signature: <hex HMAC> (required when user_id or parent_id is present)
Request body field notes:
- type: required string, max 50 chars. Any string is allowed and displayed as-is in dashboard filters. Common examples: "bug", "feedback", "inquiry".
- message: required string, max 5000 chars.
- channel: optional string (e.g. "contact", "report").
- user_id: required for two-way replies. Opaque UUID/ULID/random string, 1–255 chars.
Send feedback (first message):
{ "type": "bug", "message": "...", "user_id": "uuid-opaque-id", "channel": "contact" }
Success response (201):
{ "id": "fb_...", "status": "received", "created_at": "..." }
IMPORTANT: Store the "id" from this response. It is needed as parent_id for follow-ups.
Send follow-up (threaded reply):
{ "type": "bug", "message": "...", "user_id": "uuid-opaque-id", "parent_id": "fb_original_id" }
Follow-up response (201):
{ "id": "rp_...", "parent_id": "fb_original_id", "status": "received", "created_at": "..." }
Note: The returned id is a reply ID (rp_...), not a feedback ID.
Fetch replies:
GET https://api.signalshoot.com/v1/feedback/MY_APP_ID/replies?user_id=uuid-opaque-id
X-API-Key: fb_test_MY_KEY (development) / fb_live_MY_KEY (production)
X-Signal-User-Id-Signature: <hex HMAC of the URL-decoded user_id> (required)
This endpoint returns ALL feedback entries for the specified user, including entries with no replies yet (replies array may be empty).
Example response shape:
{
"feedbacks": [
{
"id": "fb_...", "type": "bug", "channel": "contact",
"message": "...", "status": "...", "created_at": "...",
"replies": [
{ "id": "rp_...", "sender": "developer", "message": "...", "created_at": "..." }
]
}
]
}
Replies:
- Polling only — there is no webhook or push callback
- Poll when the app foregrounds, when the inbox/chat screen opens, or on pull-to-refresh
Error handling:
- Handle 400, 401, 404, and 429 responses
- Do NOT blindly retry 4xx responses
- 429 "too_many_requests": burst limit — wait at least 60 seconds before retrying
- 429 "monthly_limit_exceeded": monthly limit reached. Writes are refused until the next billing period. Show an upgrade prompt.
UI requirements:
- Disable the submit button until a response is received to prevent double submission
Compliance note (optional):
If your app/platform requires account deletion compliance (e.g. Apple Guideline 5.1.1(v), GDPR Article 17), also implement DELETE /v1/feedback/MY_APP_ID/user/{user_id} from your backend. This requires a live key and the X-Signal-User-Id-Signature header (HMAC of the URL-decoded user_id). Test keys are rejected with 403.
Return production-ready code for [platform], including where to store the initial feedback id and how to fetch/display replies.