OAuth 2.0
Tip: If other Appfigures users don’t need to log in to your integration, use Personal Access Tokens instead. They take less work to implement than full OAuth 2.0 support.
With OAuth 2.0, your integration can access the API on behalf of you or another Appfigures user without handling passwords.
Most languages and frameworks have OAuth 2.0 packages. If you use one, configure it with your API Client’s client_key (also called client_id) and client_secret, plus the Authorization and Token endpoints below.
Summary URLs and Signature Methods
Section titled “Summary URLs and Signature Methods”- Client Registration:
https://appfigures.com/developers/keys - Authorization Endpoint:
https://api.appfigures.com/v2/oauth2/authorize - Token Endpoint:
https://api.appfigures.com/v2/oauth2/access_token - Token Revocation Endpoint:
https://api.appfigures.com/v2/oauth2/revoke(rfc7009) - Token Introspection Endpoint:
https://api.appfigures.com/v2/oauth2/tokeninfo(rfc7662) - Supported Grant Types:
authorization_codeonly. (rfc6749 4.1)
Scopes
Section titled “Scopes”The following scopes are supported: account:read, account:write, products:read, products:write, public:read, public:write, private:read, private:write
Redirect URLs
Section titled “Redirect URLs”Both the Authorization and Token Endpoints require a redirect_uri. It must match a redirect URL set up in your Appfigures API Client. It MUST be an https URL in production. Query string parameters are supported, but they must match exactly too. To set up redirect URLs, go to My API Keys and select a client to edit.
We don’t normalize the redirect_uri, so the value you send must exactly match a redirect URL in the API Client configuration.
Out of Band Flows: If you must support an out-of-band flow, use urn:ietf:wg:oauth:2.0:oob as the redirect_uri. We’ll show the user a token to paste back into your application.
Token Expiration
Section titled “Token Expiration”The access_token from the Token Endpoint doesn’t expire. We don’t issue a refresh_token. You can revoke the access_token with the Token Revocation Endpoint or on your Key Management page.
Using an Access Token
Section titled “Using an Access Token”To authenticate API calls, pass the bearer from the Token Endpoint in the Authorization header: Authorization: Bearer THE_TOKEN. Here’s an example with the token t_1234:
curl -H"Authorization: Bearer t_1234" "https://api.appfigures.com/v2/"Example Flow
Section titled “Example Flow”The examples below assume:
- The Client ID is
client_id_1234and the Client Secret isclient_secret_abcd. - The desired scopes are
account:read private:read products:write. - The
redirect_uriishttps://mydomain.com/oauth_callback.
1. Make the Authorization Request
Section titled “1. Make the Authorization Request”Each OAuth 2.0 flow needs a randomly generated state. It lets you verify that your client isn’t being tricked into accepting a token for or from an attacker. You can also use it to match the two legs of the flow.
In this example, the state is state_wxyz. Send a request to the Authorization Endpoint with response_type=code, the client_id, the redirect_uri, the desired scope and the generated state.
GET https://api.appfigures.com/v2/oauth2/authorize?response_type=code&client_id=client_id_1234&redirect_uri=https%3A%2F%2Fmydomain.com%2Foauth_callback&scope=account%3Aread%20private%3Aread%20products%3Awrite&state=state_wxyzResponse (to Appfigures, where the user approves the request)
302 Temporary RedirectLocation: (appfigures.com)Response (after approval, we redirect the user back to your application)
302 Temporary RedirectLocation: https://mydomain.com/oauth_callback?code=code_5678&state=state_wxyzError
302 Temporary RedirectLocation: https://mydomain.com/oauth_callback?error=invalid_scope&error_description=scopes%20cannot%20exceed%20scopes%20configured%20in%20api%20client&state=state_wxyz2. Verifying the Results of the Authorization Request
Section titled “2. Verifying the Results of the Authorization Request”Once the user approves your application’s request, we redirect them back to your redirect_uri with two added parameters, state and code. You MUST verify that state matches the state you generated in step 1. The URL looks like this: https://mydomain.com/oauth_callback?code=code_5678&state=state_wxyz.
If there’s an error, you’ll get error and error_description parameters instead, as documented in rfc6749 4.1.2.1. If we can’t verify the redirect_uri or client, we show the user a message.
3. Exchanging the Intermediate Code for an access_token
Section titled “3. Exchanging the Intermediate Code for an access_token”Exchange the code from step 2 for an access_token. You’ll use it to make requests on behalf of the authorizing user. Make an application/x-www-form-urlencoded POST request to the Token Endpoint with grant_type=authorization_code, the code obtained from step 2, and the redirect_uri given in step 1.
The easiest way to authenticate your API client here is to send your client_id and client_secret as the HTTP Basic username and password. You can send client_id and client_secret in the request body instead, but we don’t recommend it.
>> Request POST https://api.appfigures.com/v2/oauth2/access_token Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=code_5678&redirect_uri=https%3A%2F%2Fmydomain.com%2Foauth_callback
<< Sample Success Response 200 OK Content-Type: application/json
{ "token_type": "bearer", "access_token": "access_token_rstu", "scope": "account:read" }
<< Sample Error Response 400 Bad Request Content-Type: application/json
{"error": "invalid_request", "error_description": "redirect_uri does not match"}4. Making Authenticated Requests
Section titled “4. Making Authenticated Requests”Use the access_token from the Token Endpoint response to authenticate requests to the API.
>> Request GET https://api.appfigures.com/v2/ Authorization: Bearer access_token_rstu
<< Response 200 OK { "status": "200", "message": "OK", "see": "https://docs.appfigures.com/api", "version": "2.0", "user": { "id": 42, "name": "Test User", "email": "test@test.com", "avatar_url": "https://secure.gravatar.com/avatar/dbe9de53f77958ee4ff7e19697a58990?d=mm" }, . . . snip . . . }Inspecting a Token
Section titled “Inspecting a Token” >> Request POST https://api.appfigures.com/v2/oauth2/tokeninfo Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk Content-Type: application/x-www-form-urlencoded
token=access_token_rstu
<< Response 200 OK { "active": true, "scope": "account:read", "client_id": "client_id_1234", "username": "test@test.com" }Revoking a Token
Section titled “Revoking a Token” >> Request POST https://api.appfigures.com/v2/oauth2/revoke Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk Content-Type: application/x-www-form-urlencoded
token=access_token_rstu
<< Response 200 OK {}