Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Subscription error/bug

ANSWERED

Hello,
i'm started implementing our sollution to subscribe a user to endpoint.
Its working (i think), but not in one of our tester.
I'm using OAuth2 to get the credentials.

For this user, first
1.) I refresh the stored tokens, then i try to subscribe him to an endpoint.
2.) I got a response: 409 Conflict, so
3.) I list all of the user subscriptions. For this the url is  "https://api.fitbit.com/1/user/"+encoded_userid + "/apiSubscriptions.json";
The response is {"apiSubscriptions":[]} - its empty.  On my user, and an another testuser i got the response right, so i can delete and read

So, i cant delete this user from the subsciprions and every time i try to subscribe i got 409 -> infinity loop.
Any idea why the response is empty?

Best Answer
1 BEST ANSWER

Accepted Solutions

@freeubi wrote:

@JeremiahFitbit it seems to work now,
but now if i add the same user 2 times to the endpoint, then i dont get 409 Conflict error. This is the correct behaviour?


If you create a subscription to the same user for the same resource collection with the same subscription name, it will succeed. It's just a nice idempotent behavior we've added. However, if you try to subscribe to the same user for the same resource collection with a different subscription name, a HTTP 409 Conflict error will be returned.

View best answer in original post

Best Answer
0 Votes
16 REPLIES 16

I'm having the same issue... After a refresh of the access token, when I try to list subscriptions, I get an empty array... So I try to re-add the subscription, and get a 409 (conflict)...

 

2 questions...

 

1) should subscriptions be wiped out with a token refresh?  and if not, any idea what is happening here?

2) if they are supposed to be wiped, what's the proper protocol to add them back to users?

 

 

Best Answer
0 Votes

I'm pretty sure that this is a bug - i hope that they will solve soon.

Best Answer
0 Votes

@freeubi @SidBit:

 

1. Do you have multiple subscriber endpoints defined for your application in your app settings on https://dev.fitbit.com/apps ?

 

2. Are you creating a unique subscription name for each user?

Best Answer
0 Votes

1.) Yes, i have 2, i want to use the default.
2.) No.

I'm not using the X-Fitbit-Subscriber-Id header,but using activities collection path.
I want to subscribe our user only this one channel.

Best Answer
0 Votes

@freeubi:

 

1) The collection you are subscribing to and the X-Fitbit-Subscriber-Id are independent of each other.

 

If you have multiple subscriber endpoints, you need to specify the X-Fitbit-Subscriber-Id with every request you make to a Subscriptions API endpoint so that Fitbit knows what subscriber you're referring to. It's better to be explicit than to rely on missing header == default subscriber. I'd strongly suggest not using multiple subscriber endpoints unless you have a really good reason to split the notification traffic.

 

2) Each subscription to a user's data you create must be uniquely named. Two users of your application can't both have a subscription with the same id.

Best Answer
0 Votes

Okay, then i will delete the other endpoint.

2.) I'm missing this name creation in the docs. Can you point that for me?

Or maybe the subscription-id (in the Add Subscription part) is this unique name? I thought that this id is the unique subscription endpoint id that i set in my app settings [https://dev.fitbit.com/apps]

Best Answer
0 Votes

Think I found the point of confusion. subscription-id is not subscriber-id

 

Subscriber = the endpoint in your application that Fitbit makes requests to.

Subscription = the resource you create that tells Fitbit you want to be notified about data changes

 

For example, I would recommend naming your subscription with something easy for your app to identify, such as the user's id. I might do something like:

 

POST https://api.fitbit.com/1/user/-/apiSubscriptions/X1Y2Z3.json  
POST https://api.fitbit.com/1/user/-/activities/apiSubscriptions/X1Y2Z3-activities.json  
POST https://api.fitbit.com/1/user/-/foods/apiSubscriptions/X1Y2Z3-foods.json  
POST https://api.fitbit.com/1/user/-/sleep/apiSubscriptions/X1Y2Z3-sleep.json  
POST https://api.fitbit.com/1/user/-/body/apiSubscriptions/X1Y2Z3-body.json

 

 

For the documentation, see https://dev.fitbit.com/docs/subscriptions/#add-a-subscription

 

Best Answer
0 Votes

Yeah, thats a bit confuse, now i get it.

I will test it tomorrow and tell you the result.
Thanks anyway!

Best Answer
0 Votes

@JeremiahFitbit, thanks for reaching out!

 

1) I only have 1 subscriber end point, that is set to default, and with an ID of 1

2) For each user, I execute a POST request to the "add a subscription" FB API end point (as described in the FitBit API Docs here).  

 

After the initial time I do this, I can retrieve the subscription list perfectly fine with the appropriate subscription returned in an array.  

 

However, after a token refresh, any call to "list the subscription" (based on the docs here), results in the return of an empty array.  Upon assuming that means the subscription for that user was deleted, I execute another "add subscription" call, but recieve a 409 conflict error.  Deleting the user subscriptions returns a 204 (no content), and then I can list it again properly.

 

Are subscriptions only associated with the original access token with which they were created?

Best Answer
0 Votes

SidBit wrote:

Are subscriptions only associated with the original access token with which they were created?


No, subscriptions are associated with the user they were created for. It sounds like you might not be using an OAuth 2.0 access token for the same user you created the subscription for.

Best Answer
0 Votes

It sounds like you might not be using an OAuth 2.0 access token for the same user you created the subscription for.

 

@JeremiahFitbit, I'm not sure what you mean.  I'm using the OAuth2.0 Grant Flow described in the docs to obtain and then refresh the access token.  Then the new access token provided is what I'm using to request a list of the user's subscriptions, which is where I get the empty array...

 

In the end, the empty array isn't the issue... the issue is that once the refresh token flow is completed, and a new access token is provided, the subscriptions don't seem to send notifications anymore.  Do I need to refresh a user's subscriptions when I refresh the access token?

Best Answer
0 Votes

@SidBit: OAuth 2 and the Subscriptions API don't have any relation to each other beyond validating the application has permission from the user. You don't need re-create a subscription when an access token is refreshed.

 

I just did a quick test to verify that subscriptions are not deleted after an OAuth 2.0 access token is refreshed:

 

1) Final step of the OAuth 2.0 code flow, Access Token Request

curl -X POST -H "Authorization: Basic ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮" --data "client_id=228YX6&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%2F&code=7a6d0698896b7cf90257fff65d34df5aa944c28a" https://api.fitbit.com/oauth2/token

Response:
{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDA0NTY3MzgsInNjb3BlcyI6Indsb2Mgd3BybyB3bnV0IHdzZXQgd3NsZSB3d2VpIHdociB3YWN0IHdzb2MiLCJzdWIiOiIyNkZXRkwiLCJhdWQiOiIyMjhZWDYiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0NDA0NTMxMzh9.dXtMQCvJh0ccJVmAu_kdLadcPwZg9WvBnubwWT0-Ilk",
    "expires_in": 3600,
    "refresh_token": "175f47414e95d4d1faa30cb6e68c4776c9adf7d52552fc089a9df2e0bb90e619",
    "scope": "sleep nutrition settings social heartrate activity profile weight location",
    "token_type": "Bearer",
    "user_id": "26FWFL"
}


2) Create a subscription

curl -X POST -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDA0NTY3MzgsInNjb3BlcyI6Indsb2Mgd3BybyB3bnV0IHdzZXQgd3NsZSB3d2VpIHdociB3YWN0IHdzb2MiLCJzdWIiOiIyNkZXRkwiLCJhdWQiOiIyMjhZWDYiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0NDA0NTMxMzh9.dXtMQCvJh0ccJVmAu_kdLadcPwZg9WvBnubwWT0-Ilk" -H "X-Fitbit-Subscriber-Id: 1" https://api.fitbit.com/1/user/-/activities/apiSubscriptions/26FWFL-activities.json

Response:
{
    "collectionType": "activities",
    "ownerId": "26FWFL",
    "ownerType": "user",
    "subscriberId": "1",
    "subscriptionId": "26FWFL-activities"
}


3) List subscriptions for the user

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDA0NTY3MzgsInNjb3BlcyI6Indsb2Mgd3BybyB3bnV0IHdzZXQgd3NsZSB3d2VpIHdociB3YWN0IHdzb2MiLCJzdWIiOiIyNkZXRkwiLCJhdWQiOiIyMjhZWDYiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0NDA0NTMxMzh9.dXtMQCvJh0ccJVmAu_kdLadcPwZg9WvBnubwWT0-Ilk" https://api.fitbit.com/1/user/-/apiSubscriptions.json

Response:
{
    "apiSubscriptions": [
        {
            "collectionType": "activities",
            "ownerId": "26FWFL",
            "ownerType": "user",
            "subscriberId": "1",
            "subscriptionId": "26FWFL-activities"
        }
    ]
}


4) Refresh the OAuth 2.0 access token

curl -X POST -H "Authorization: Basic ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮" --data "grant_type=refresh_token&refresh_token=175f47414e95d4d1faa30cb6e68c4776c9adf7d52552fc089a9df2e0bb90e619" https://api.fitbit.com/oauth2/token

Response:
{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDA0NTY4MTMsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiIyNkZXRkwiLCJhdWQiOiIyMjhZWDYiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0NDA0NTMyMTN9.Xr3PZlB18c50uvhGRNiPiFptvqUpTZ2SRjOv5eIxTRo",
    "expires_in": 3600,
    "refresh_token": "d34e76441ad3c0f8274c00d5434d128eec2934245920f0bc7c50433fa688dbce",
    "scope": "social nutrition location weight profile heartrate activity settings sleep",
    "token_type": "Bearer",
    "user_id": "26FWFL"
}


5) Check subscriptions list with the new access token

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDA0NTY4MTMsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiIyNkZXRkwiLCJhdWQiOiIyMjhZWDYiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0NDA0NTMyMTN9.Xr3PZlB18c50uvhGRNiPiFptvqUpTZ2SRjOv5eIxTRo" https://api.fitbit.com/1/user/-/apiSubscriptions.json

Response:
{
    "apiSubscriptions": [
        {
            "collectionType": "activities",
            "ownerId": "26FWFL",
            "ownerType": "user",
            "subscriberId": "1",
            "subscriptionId": "26FWFL-activities"
        }
    ]
}

 

You might try using a tool like Runscope Traffic Inspector to verify that your application is making the HTTP requests that you think it's making.

Best Answer
0 Votes

@JeremiahFitbit, thanks so much for the prompt feedback.  I'll take another pass at it this week/weekend, and see if I can debug.  Will keep you posted.  Thanks again!

 

 

Best Answer
0 Votes

@JeremiahFitbit it seems to work now,
but now if i add the same user 2 times to the endpoint, then i dont get 409 Conflict error. This is the correct behaviour?

I'm using this url to subscribe [encoded_userid is the user encoded userid]:
https://api.fitbit.com/1/user/"+encoded_userid+"/activities/apiSubscriptions/"+encoded_userid+"-acti...


Today, i will test more.


Best Answer
0 Votes

@freeubi wrote:

@JeremiahFitbit it seems to work now,
but now if i add the same user 2 times to the endpoint, then i dont get 409 Conflict error. This is the correct behaviour?


If you create a subscription to the same user for the same resource collection with the same subscription name, it will succeed. It's just a nice idempotent behavior we've added. However, if you try to subscribe to the same user for the same resource collection with a different subscription name, a HTTP 409 Conflict error will be returned.

Best Answer
0 Votes

I tested in the last few days, it working.

Thanks for your help.

Best Answer
0 Votes