How to collect feedback in a mobile app
Mobile apps send feedback through the Escuta Produto REST API with the public product key, a single POST request and no SDK. Add the app version and platform as metadata, handle failed sends in the app, and link the hosted form from your store listing.
By Rafael Thayto · Last updated
Mobile apps use the REST API
Escuta Produto does not ship native SDKs for iOS, Android or React Native. The widget is a script for web pages. A native app sends feedback with one HTTPS request to the REST API, and the request is simple enough to write in a few lines in any language.
The endpoint is https://escutaproduto.com/api/v1/feedback. You send a JSON body that includes your product key and a message. The product key is public, so it can sit in the app. The full field list is in the REST API reference. This article focuses on the parts that matter in an app: metadata, error handling and where the link lives.
Send the request from your app
A useful request includes the message, the type, an optional rating and the email when the user is signed in. Here is the body you would build in a Swift app:
struct FeedbackPayload: Encodable {
let key: String
let kind: String
let message: String
let email: String?
let metadata: [String: String]
}
func sendFeedback(_ payload: FeedbackPayload) async throws {
var request = URLRequest(url: URL(string: "https://escutaproduto.com/api/v1/feedback")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(payload)
let (_, response) = try await URLSession.shared.data(for: request)
guard let http = response as? HTTPURLResponse, http.statusCode == 201 else {
throw URLError(.badServerResponse)
}
}
The success response is 201 with a body that contains ok and the new id. Checking for 201 is enough to know the message was saved.
On Android, the same request works with the standard library. Remember that the app needs the internet permission, and that network calls must run off the main thread:
val connection = URL("https://escutaproduto.com/api/v1/feedback").openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json")
connection.doOutput = true
connection.outputStream.use { it.write(json.toByteArray()) }
val saved = connection.responseCode == 201
In a React Native app, fetch does the same job:
const response = await fetch("https://escutaproduto.com/api/v1/feedback", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
key: "pk_your_product_key",
kind: "bug",
message,
metadata: { platform: Platform.OS, appVersion: "2.3.1" },
}),
});
Native HTTP clients usually send no Origin header. The API accepts requests without an origin, so the allowed origins list in your product settings does not block the app.
Add app version and device context
The app version is the most useful piece of metadata you can add. A bug report that says "the sync stopped" is hard to act on. The same report with appVersion: "2.3.1" and platform: "ios" tells you whether the problem existed in the last release or the one before.
Useful keys for a mobile app are appVersion, build, platform, osVersion and deviceModel. Keep the set small and do not send device identifiers, precise location or anything that identifies a person beyond what the user typed. Metadata is a JSON object of up to 4 KB, which is plenty for these fields.
Escuta Produto has no tags, so use metadata for version and platform, then search the message text or export the product to CSV when you want to group reports by release.
Handle failed sends in the app
Mobile networks fail. A user may send feedback in an elevator or on a train. The API will not queue the message for you, so the app should handle the failure itself:
- Keep the draft. If the request fails, leave the text on screen and show a retry button. Users lose patience quickly when a long message disappears.
- Disable the send button while a request is in flight. Double taps create duplicate items.
- Retry network errors, back off on 429. A 429 means more than 10 submissions per minute from the same IP to the same product. Wait a minute before trying again.
- Do not retry 400 responses. A 400 means a field failed validation, such as a message that is too short. Show the user what to fix instead.
- Treat 413 as a size problem. The request body is limited to 16 KB, so trim very long messages before sending.
These rules keep the inbox clean. Retrying a validation error in a loop produces the same error over and over, and the rate limit eventually blocks real feedback.
Use the hosted link in store listings and help
Not every feedback path needs code. The hosted feedback page lives at https://escutaproduto.com/f/your-product-slug, and it works in any browser. Add ?lang=pt or ?lang=en to force a language.
Put the link where people look for help: the support or website field of your store listing, the help screen inside the app, and the replies you send from your support inbox. Use the in-app form for version-specific bug reports, because the hosted page cannot carry app metadata. Use the hosted page for general ideas and for people who do not have the app installed.
Set up Escuta Produto for your mobile app
Create a product for the app in the dashboard, copy its public key and add a feedback screen with four types: bug, idea, praise and other. Send the request with the app version and platform as metadata, and test it against a staging build before you release.
Connect a Slack or Discord webhook so each new item reaches your team. The notifications guide explains the setup. When a request ships, close the loop with the people who asked. The article on releases and feedback covers how to link a changelog entry to the requests it answers. If you also run a web app, collecting feedback in a SaaS product shows how to keep both in one inbox.
Frequently asked questions
Is there a native iOS or Android SDK for Escuta Produto?
No. Mobile apps use the REST API directly with a single POST request. The widget is built for web pages, so native code sends the request itself, with a form you design in your app.
Do I need a secret key in my mobile app?
No. The product key is public and can only create feedback, never read it. It is safe to ship inside an app binary. If the key is abused, rotate it in the product settings.
What happens if the device is offline when a user sends feedback?
The API saves a request only when it arrives, so the app decides what to do with a failed send. Keep the draft on screen, show a retry option and do not retry automatically on a 400 response.
Related
- How to collect feedback in a SaaS productCollect in-app feedback from SaaS customers: load the widget once, identify users after login, add plan metadata and place entry points where work happens.
- How to collect feedback for a Chrome extensionCollect Chrome extension feedback with a REST API call from the popup, a hosted form as the uninstall URL and the extension version on every report.
- How to collect feedback for a WordPress pluginCollect feedback for a WordPress plugin with a settings page link to a hosted form, server-side API posts with site details, and no remote script in wp-admin.
- How to collect feedback for a Shopify appCollect Shopify app feedback from your backend with the REST API, store the shop domain as metadata and link a hosted form in onboarding emails.