Consent API
Every device that shares bandwidth through EarnFM must have a recorded, granted user consent. The Consent API is how you report those consent decisions to EarnFM — either directly over HTTPS or through the built-in SDK helper (storeConsent, available in the Java and Android SDKs).
How it works
- You show the user a consent prompt in your app (see User Consent for what it must contain).
- You report the user’s decision — grant or revoke — to the Consent API, together with a stable
device_id. - EarnFM stores the decision, the exact consent text (deduplicated by SHA-256 hash), and an immutable audit trail.
- When the device later connects to share bandwidth, EarnFM checks that a granted consent exists for it.
Consent is stored per device: the same device_id you use when running the SDK on a device is the one its consent is recorded under. A later revoke for the same device overrides an earlier grant (and vice versa — the latest decision wins).
Recommended consent text
You can word the prompt to fit your product, but it must clearly say that the user’s internet connection will be shared. We strongly recommend using the default text below as-is (just fill in your app name) — it has been written to give both you and EarnFM the broadest possible legal cover while staying honest and readable:
Support {Your App} by sharing your unused internet bandwidth.
By tapping “Enable”, you confirm that you are of legal age, that you are the owner of this device and internet connection (or have the owner’s permission), and you agree to the following:
{Your App} may securely route a portion of your device’s unused internet bandwidth through the EarnFM network, operated by TeraShift GmbH (Switzerland). Verified and vetted business partners (for example market research, brand protection, ad verification, and web intelligence companies) may send encrypted traffic through your internet connection to access publicly available web content.
- Your data stays yours. No personal data, files, messages, or browsing activity on your device is accessed, read, or collected. The routed traffic is encrypted, is not visible to you, and does not originate from you.
- You are not responsible for the routed traffic. All partner traffic is contractually bound to EarnFM’s acceptable-use policy, is monitored 24/7, and is attributable to the partner that sent it — not to you or to {Your App}.
- Data usage. Bandwidth sharing may consume data from your plan, including mobile data when you are not on Wi-Fi, and may incur charges from your internet provider. You are responsible for your own data plan.
- No warranties. The feature is provided “as is” and “as available”, without warranties of any kind. To the maximum extent permitted by applicable law, neither {Your App} nor TeraShift GmbH is liable for any indirect, incidental, or consequential damages arising from your participation, and their total aggregate liability is limited to the amounts (if any) paid to you for participation.
- Changes and termination. Participation may be suspended, changed, or ended by {Your App} or TeraShift GmbH at any time, for any reason, without prior notice or compensation.
- Your record. Your consent decision (including this text and your device identifier) is recorded and stored by TeraShift GmbH as an auditable proof of consent, as required by law.
This is entirely optional and you can turn it off at any time in the settings — sharing stops and your consent is revoked.
[Enable and support us] [No thanks]
If your product targets the EU/EEA, UK, or California, keep the full text — the age, device-ownership, data-charges, and audit-record clauses exist specifically for GDPR/CCPA defensibility. Shortening the text is at your own risk; if you do, it must at minimum still clearly say that the user’s internet connection will be shared with third parties, may use mobile data, and can be turned off.
Guidelines:
- The prompt must be opt-in: sharing must not start before the user actively accepts.
- Offer a way to turn it off later (and send a
revokewhen they do). - Keep the exact text you showed — you submit it (or its hash) with every consent event.
Endpoint
POST https://api.earn.fm/v2/consent?apikey=YOUR_API_KEY
Content-Type: application/jsonAuthentication uses your EarnFM API key (the same key you pass to the SDK) as the apikey query parameter.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
action |
string | yes | "grant" when the user accepts, "revoke" when the user declines or opts out later. |
device_id |
string | yes | The device identifier the SDK runs with, max 128 characters. Consent is stored per device. |
consent_text |
string | for grants | The exact consent message shown to the user. Required on grant unless you send a known consent_text_hash instead. Max 1 MB. |
consent_text_hash |
string | no | Lowercase SHA-256 hex of consent_text. Once a text has been submitted once, you can send only its hash for subsequent devices (saves bandwidth). Unknown hashes are rejected — submit the full text first. |
metadata |
object | no | Any JSON that helps you identify the user/installation, e.g. {"user": "abc123"}. Max 4 KB. |
If you send both consent_text and consent_text_hash, the hash must match the SHA-256 of the text.
Example: grant
curl -X POST "https://api.earn.fm/v2/consent?apikey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "grant",
"device_id": "device-42",
"consent_text": "Support MyApp by sharing your unused internet bandwidth. ...",
"metadata": {"user": "abc123"}
}'Response:
{
"success": true,
"device_id": "device-42",
"status": "granted",
"consent_text_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}Example: grant by hash (text already registered)
curl -X POST "https://api.earn.fm/v2/consent?apikey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "grant",
"device_id": "device-43",
"consent_text_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}'Example: revoke
Send a revoke whenever the user declines the prompt or later turns sharing off:
curl -X POST "https://api.earn.fm/v2/consent?apikey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action": "revoke", "device_id": "device-42"}'consent_text is optional on revokes.
Errors
| Status | Meaning |
|---|---|
400 |
Invalid body — e.g. missing action/device_id, unknown consent_text_hash, hash mismatch, or a grant without text/hash. The details field explains what is wrong. |
401 |
Missing or invalid apikey. |
503 |
Consent storage temporarily unavailable — retry with backoff. |
Using the SDK helper instead
If you integrate through the Java or Android SDK, you don’t need to call the HTTP endpoint yourself — call storeConsent(consentText, consentTextHash, action, metadata) between initialize() and startSdk(), and the SDK reports the decision (with its own device id) for you. See the Java and Android guides for the exact usage.
For all other languages and custom integrations, call the HTTP endpoint directly with the same device_id you run the SDK with.
Tracking your adoption
Your supplier dashboard shows how many of your devices have a granted consent on record. If the counter shows 0, none of your devices are using the Consent API yet.