Trust Signals: Quick Start
This guide takes you from credentials to a first signal result. It uses one Sensor SDK and the Geolocation signal, which works with a single mobile app or a single web page.
Before you begin
You need:
- A Trust Signals tenant and its
serviceId. - The two OAuth2 clients Futurae provisions for your tenant: one for collection and one for retrieval.
- A backend where you can add an HTTP endpoint.
While Trust Signals is in Early Access, your assigned Solutions Engineer provides the tenant and the credentials. The Futurae endpoints are public; their hosts are listed in Endpoints.
Step 1: Get a collection token
On your backend, exchange the collection client’s credentials for an access token with the audience ts-collection-public.futurae.com:
curl --location 'https://auth.futurae.com/oauth/v2/token?grant_type=client_credentials&scope=urn'\
'%3Azitadel%3Aiam%3Aorg%3Aproject%3Aid%3Ats-collection-public.futurae.com%3Aaud' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic <base64(client_id:client_secret)>'
Copy the access_token from the response. In production your backend caches this token and refreshes it before it expires. See Token lifecycle.
Step 2: Add a collection proxy
The SDKs never hold the collection token. They send observations to an endpoint on your backend, which attaches the token and the user’s identity and forwards the request to Futurae.
Add that endpoint, starting from the example implementation. For this test, the proxy can accept every request, use the token from step 1, and set fixed identity values: accountId set to test-user-1, interactionId set to quickstart-1 and verificationStatus set to verified.
Step 3: Add a Sensor SDK
Set up one of the SDKs below. In each case, collectionUrl is the URL of your proxy endpoint from step 2, and accessToken is a placeholder, because your proxy sets the real token. Every call that collects observations requires serviceId, unitId, accountId, interactionId and verificationStatus.
Android
Add the dependency, which is distributed through GitHub Packages:
// app/build.gradle.kts
implementation("com.futurae.sdk:trust-signals:<version>")
Replace <version> with the latest release tag. The GitHub Packages repository setup is in the Android SDK README.
Initialize the SDK once, in Application.onCreate():
import com.futurae.sdk.ts.TrustSignalsSDK
import com.futurae.sdk.ts.model.public.TSConfiguration
TrustSignalsSDK.initialize(
context = this,
configuration = TSConfiguration(
collectionUrl = "https://your-backend.example.com/trust-signals/collections"
)
)
Then collect and upload, from a coroutine:
import com.futurae.sdk.ts.TrustSignalsSDK
import com.futurae.sdk.ts.model.public.TSCredentials
import com.futurae.sdk.ts.model.public.TSVerificationStatus
val collection = TrustSignalsSDK.collectAndUpload(
TSCredentials(
serviceId = "<your_service_id>",
unitId = "quickstart-android",
accountId = "test-user-1",
accessToken = "placeholder", // your proxy sets the real token
interactionId = "quickstart-1",
verificationStatus = TSVerificationStatus.VERIFIED
)
)
Request the location permission before collecting, so that Geolocation has a device position to report. See Permissions.
iOS
In Xcode, choose File → Add Package Dependencies, enter https://github.com/Futurae-Technologies/ios-trust-signals-sdk.git, set the dependency rule to Exact Version with the latest release tag, and add TrustSignalsSDK to your target. Full setup instructions are in the iOS SDK README.
Initialize the SDK once on app launch, for example in AppDelegate or App.init:
import TrustSignals
await TrustSignalsSDK.initialize(
TSConfiguration(
collectionUrl: URL(string: "https://your-backend.example.com/trust-signals/collections")!
)
)
Then collect and upload:
let collection = try await TrustSignalsSDK.collectAndUpload(
TSCredentials(
accountId: "test-user-1",
accessToken: "placeholder", // your proxy sets the real token
serviceId: "<your_service_id>",
unitId: "quickstart-ios",
interactionId: "quickstart-1",
verificationStatus: .verified
)
)
Add the location purpose string to Info.plist before collecting, so that Geolocation has a device position to report. See Permissions.
Browser
Install the package:
npm i @futurae-public-js/browser-sensor-js
Initialize the SDK on a page of your web application:
import TrustSignalsSDK from '@futurae-public-js/browser-sensor-js';
TrustSignalsSDK.initialize({
collectionUrl: 'https://your-backend.example.com/trust-signals/collections',
serviceId: '<your_service_id>',
unitId: 'quickstart-web',
accountId: 'placeholder', // your proxy sets the real value
accessToken: 'placeholder', // your proxy sets the real token
interactionId: 'placeholder', // your proxy sets the real value
verificationStatus: 'unverified', // your proxy sets the real value
});
The SDK starts collecting at once and uploads every second until the page unloads.
Step 4: Get a signals token
Exchange the retrieval client’s credentials for a second access token, this time with the audience ts-signals-public.futurae.com:
curl --location 'https://auth.futurae.com/oauth/v2/token?grant_type=client_credentials&scope=urn'\
'%3Azitadel%3Aiam%3Aorg%3Aproject%3Aid%3Ats-signals-public.futurae.com%3Aaud' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic <base64(client_id:client_secret)>'
Step 5: Query a signal
Query Geolocation with the accountId your proxy set and the unitId you gave the SDK in step 3. The example uses the Android value; replace it with yours:
curl --location 'https://ts-signals-public.futurae.com/api/v1/signals/geolocation?serviceId=<your_service_id>&accountId=test-user-1&unitId=quickstart-android' \
--header 'Authorization: Bearer <access_token_from_step_4>'
A successful response looks like this, with the location entries inside result:
{
"signalType": "geolocation",
"success": true,
"result": { ... },
"observationTime": "2026-10-05T09:12:44Z"
}
If success is false, the response carries a reason instead of a result. Right after setup the usual reason is insufficient_observations: no stored observation matched the query. Check that the upload reached your proxy, that the Collection API answered 202 Accepted, and that the identifiers in your query match the ones the observations were stored under. Troubleshooting covers the other reasons.
Next steps
- Read Core Concepts before you choose identifier formats for production. They cannot be changed once observations are stored.
- Replace the fixed identity values in your proxy with values from your user sessions. See Collection proxy.
- Work through the go-live checklist.
- Look up every endpoint, parameter and response shape in the Trust Signals API Reference. It is generated from the Signals API OpenAPI specification, which you can also import into Postman or another OpenAPI-aware client.