Moved my code to client's Checkfront account, doesn't work.

edited April 2014 in Developers

I generated API key/secret on my client's account, but the same code that worked for on my account doesn't work on his account. Even simple example code using the PHP-SDK from the command line - I get "


    [error] => invalid_grant

    [error_description] => The access token provided is invalid.


He signed up for the Soho account. Is there a limitation that Soho accounts can't use the API?


  • Update: I tried using token auth, and it works. Any idea why OAuth2 isn't working for my client's account? Don't know if it's significant, but I see that the consumer_secret generated on my client's account is WAY longer than the one on my account.

  • All accounts have API access.  "The access token provided is invalid" explicitly means that the token was provided in the request, but could not be loaded -- meaning the token as submitted does not exist in the database.  You may have inadvertently copied over a stored token from a previous account that your application is attempting to submit, or possibly transposed the access/refresh tokens somewhere.

    Consumer credentials are only involved in the token granting process, and are not sent to the API endpoint.  If you're able to obtain a token pair, the credentials are working, and any tokens the system returns will be stored for use.

  • I definitely copied the key and secret correctly - I've done it over and over again, even went as far as creating new ones and I still got the same result. I'm at a complete loss here.

  • Now it gets worse. My test program was evidently using a hidden file which came from the example code in store(). I deleted that and now it's not working on my developer account either. As far as I can tell, "refresh_token" is set but empty, so init() doesn't call refresh_token to set it.

  • If you're getting this error, the key and secret are not the issue at hand - the SDK has an access token available to it already, but it is invalid, which is why it sounds like it could be a leftover token from your own account.  Where are you storing token pairs for refreshing?  If you're still using the old example flat filestore in tmp, you'll want to clear it or specify a different location.  If you're using sqlite or some full-fledged database, you'll want to clear the fields you're storing, or modify the script to automatically remove tokens on a fatal error to require an OAuth2 user to log in again.  

    Assuming you're using the standard SDK call workflow, what is most likely happening is this:

    1. The constructor for the CheckfrontAPI library is loading an existing access and refresh token from your storage implementation.
    2. Because the token is most likely expired, it will attempt to refresh the token.  However, because the stored refresh token doesn't exist in the database, it silently fails, and therefore doesn't update the stored tokens (this is something that could be improved on in the SDK).
    3. The token refresh failure doesn't stop the application, so it attempts to make an API call using the access token it had already loaded on initialization.
    4. The API recognizes that a token has been sent, but it does not match any registered access tokens, so throws the error you're getting.
  • I know things changed in the 3.0 API, but didn't the API site used to generate an initial value for the refresh token for you? I can't see how to do that any more.

  • edited April 2014
    (oops, double posted)
  • edited April 2014

    I did a lot of tracing through the CheckfrontAPI.php code, and it appears that since the Developer API page doesn't give you a way to generate the refresh_token, I'm not setting one in the constructor. And because it's not set, when it calls init(), it never calls refresh_token() method to ask for a new one. Because of *that*, it never generates an access_token, and so it's not connecting.

  • While it doesn't specify due to the type of example that was needed at the time, it would make sense to verify that valid tokens exit when loading them up and passing them to the class, and gracefully fail if not so you can offer the opportunity to log in to a Checkfront account.  A refresh token is generated every time you're given an access token by the API, and must be replaced every time it is refreshed thereafter.  The presence of the generate tokens button on the API page created confusion as to how the OAuth2 protocol works, and since the primary need of the initial token functionality provided for headless server-to-server applications is handled by token authentication in the update, it is no longer recommended to use the initial token setup for new applications.

    We have some information on how the OAuth2 protocol works in this context here:
    And a bit about use with the SDK here:

    If you do need to generate tokens, the login process is very simple to implement, but you can get the same output of the old button by using:
    oauth/?client_id=*consumer key*&response_type=code&redirect_uri=oob

  • Yeah, I wasn't imagining it. The Developer API page has the "Generate Access Tokens" buttons commented out:


    <button type="submit" name="delete_app" value="1">Delete</button>

    <!--<button type="submit" name="set_access_token" value="1">Generate Access Tokens</button>-->

    <button type="submit">Update</button>


    And the API documentation says you need the existing refresh_token to generate a new one. So I'm stuck.

    I guess the question then becomes: should I be using the token authentication? This is customer facing code, so I thought not.

  • Token auth is used primarily for server-to-server applications where either you don't need to represent a staff account, or have your own login processes and user mapping.  Example use would be things like a customer-facing booking page.

    OAuth2 is better suited for applications where you have staff members logging in and interfacing with the systems directly, or have the application distributed to members of your organization.  Could be things like mobile applications, administration interfaces, applications building on Checkfront functionality, using accounts directly from Checkfront, etc.

    As far as generating access tokens, refresh tokens are only used in the period between the expiration of an access token and the expiration of a refresh token.  These are effectively an extension to your access token to provide a way for it to be renewed for longer access... think of it kind of like a cookie that will expire if you don't use it within 2 weeks, but if you do use it, you get a new one that will last 2 weeks.  That said, if you have an access token, you should always have the associated refresh token stored with it.

    If either the access or refresh token is invalid, the user needs to go through the oauth login process to generate a new access/refresh token pair (as in those docs referring to staff logins).

  • Evidently generating access and refresh tokens doesn't do me any good because the code in the CheckfrontAPI.php's constructor that used to set them based on the parameters has been deleted. I guess I'm going to bed now, and in the morning I'm going to re-write my code to use token authentication.

This discussion has been closed.