04-27-2026 14:08
04-27-2026 14:08
Even though all the steps are followed and all the permission are given, I'm still getting 403.
{
"error": {
"code": 403,
"message": "The caller does not have permission",
"errors": [
{
"message": "The caller does not have permission",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}Attaching node js script which I used for calling.
/**
* Calls Google Health API CreateSubscriber for the webhook URL.
*
* Prerequisites:
* - Application Default Credentials with permission health.subscribers.create on the project
* (often: gcloud auth application-default login as a user with that role, or a service account key).
* - Public HTTPS endpoint that already implements POST /trackers/fitbit/webhook and passes verification.
*
* Env:
* - GOOGLE_APPLICATION_CREDENTIALS (required) absolute path to the service account JSON key file
* - GOOGLE_CLOUD_PROJECT_ID (required)
* - GOOGLE_HEALTH_WEBHOOK_ENDPOINT_URI (required) e.g. https://api.example.com/trackers/fitbit/webhook
* - GOOGLE_HEALTH_WEBHOOK_AUTHORIZATION_TOKEN (required) same full Authorization value as the server (e.g. Bearer ...)
* - GOOGLE_HEALTH_SUBSCRIBER_ID (optional) default "trackers-webhook"
*/
const fs = require("fs");
const path = require("path");
require("dotenv").config({
path: path.resolve(__dirname, "../environment/env/.env.sandbox"),
});
const { GoogleAuth } = require("google-auth-library");
async function main() {
const keyPath = (process.env.GOOGLE_APPLICATION_CREDENTIALS || "").trim();
if (!keyPath) {
console.error(
"Missing GOOGLE_APPLICATION_CREDENTIALS (path to your service account JSON key).\n" +
"Example:\n" +
' export GOOGLE_APPLICATION_CREDENTIALS="/Users/you/Downloads/your-project-xxxxx.json"\n' +
"Or add that variable to environment/env/.env.sandbox (never commit the key file itself).\n" +
"This is separate from gcloud; you only need the key downloaded from IAM → Service accounts → Keys."
);
process.exit(1);
}
if (!fs.existsSync(keyPath)) {
console.error(`GOOGLE_APPLICATION_CREDENTIALS file not found:\n ${keyPath}`);
process.exit(1);
}
const projectId = process.env.GOOGLE_CLOUD_PROJECT_ID;
const endpointUri = process.env.GOOGLE_HEALTH_WEBHOOK_ENDPOINT_URI;
const secret = process.env.GOOGLE_HEALTH_WEBHOOK_AUTHORIZATION_TOKEN;
const subscriberId = process.env.GOOGLE_HEALTH_SUBSCRIBER_ID || "trackers-webhook";
if (!projectId || !endpointUri || !secret) {
console.error(
"Set GOOGLE_CLOUD_PROJECT_ID, GOOGLE_HEALTH_WEBHOOK_ENDPOINT_URI, and GOOGLE_HEALTH_WEBHOOK_AUTHORIZATION_TOKEN"
);
process.exit(1);
}
const auth = new GoogleAuth({
keyFilename: keyPath,
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
});
const client = await auth.getClient();
const url =
`https://health.googleapis.com/v4/projects/${encodeURIComponent(projectId)}/subscribers` +
`?subscriberId=${encodeURIComponent(subscriberId)}`;
const body = {
endpointUri,
endpointAuthorization: { secret },
subscriberConfigs: [
{
dataTypes: ["steps", "distance", "floors", "sleep", "weight", "heart-rate", "exercise"],
subscriptionCreatePolicy: "AUTOMATIC",
},
],
};
const res = await client.request({ url, method: "POST", data: body });
console.log(JSON.stringify(res.data, null, 2));
if (res.data?.name && !res.data?.done && res.data?.metadata) {
console.error(
"\nNote: API returned a long-running Operation. Poll the operations API or re-check subscriber state in Cloud Console until done === true."
);
}
}
main().catch((e) => {
const err = e?.response?.data ?? e?.message ?? e;
console.error(typeof err === "string" ? err : JSON.stringify(err, null, 2));
process.exit(1);
});I have also checked if handshake is failing but there are no request made to my server from google!
Best Answer05-01-2026 17:04
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
05-01-2026 17:04
Welcome to the community.
Thanks for sharing your question.
The error you're encountering is because the example you followed was based on a previous beta version of the API. This was changed in our latest release. To fix this, could you please refer to the updated technical details in our reference documentation here: EndpointAuthorization Reference. We will go through and update the example and documentation to reflect this change. Please let us know if this helps you resolve the issues!
Best Answer05-04-2026 18:37
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
05-04-2026 18:37
I want to check in on the problem you reported. It looks like you are missing the endpointAuthorization section of the endpoint. The syntax should look similar to this
POST {{google_health_v4_host}}/projects/6183080339/subscribers?subscriberId=webhooks
Authorization: Bearer {{access_token}}
Accept: application/json
{
"endpointUri": "<endpoint-URL>",
"subscriberConfigs": [
{
"dataTypes": [
"steps", "weight", "sleep"
],
"subscriptionCreatePolicy": "AUTOMATIC"
}
],
"endpointAuthorization" : {
"secret": "Bearer 618308034039-au5r1vjbnic6pp.apps.googleusercontent.com"
}
}
Does this example help you get further?
Best Answer