API Authentication Guide

API authentication OAuth 2.0 authorization code developer guide

Authentication Guide

The ReceiptRoller API uses the OAuth 2.0 authorization code flow. A third-party developer registers an app, and once a business owner authorizes access, the developer can obtain a token and call the API.


Step 1: Register an app

  1. Log in to your ReceiptRoller account
  2. Go to Business account detail⋮ menuDeveloper apps
  3. Click Create app
  4. Enter the app name, redirect URI, and select the API scopes you need
  5. After creation, a client_id and client_secret are issued
⚠ Important: The client_secret is shown only once. Be sure to copy it and store it securely. If you lose it, you'll need to regenerate it (which immediately invalidates the existing secret).

Step 2: Redirect the business owner to the authorization screen

When a business owner links their account to your app, redirect their browser to the following URL:

GET https://your-domain/oauth/authorize
    ?client_id=YOUR_CLIENT_ID
    &redirect_uri=YOUR_REDIRECT_URI
    &response_type=code
    &scope=store.products.read store.orders.read
    &state=RANDOM_STATE_STRING
Parameter Required Description
client_id Yes The app's client ID
redirect_uri Yes Must exactly match the redirect URI registered for the app
response_type Yes Specify code
scope Yes A space-separated list of scopes (see Available scopes below)
state Recommended A random string to prevent CSRF attacks. It is returned as-is on the callback.
code_challenge Optional PKCE code challenge (the base64url-encoded SHA-256 hash of the code_verifier)
code_challenge_method Optional S256 (required when using PKCE)

The business owner sees a consent screen showing the app name and the access permissions being requested. They can choose to allow or deny.


Step 3: Receive the authorization code

If access is granted, the business owner's browser is redirected to redirect_uri:

GET https://your-app.com/callback
    ?code=AUTHORIZATION_CODE
    &state=RANDOM_STATE_STRING

If denied:

GET https://your-app.com/callback
    ?error=access_denied
    &state=RANDOM_STATE_STRING
ℹ Note: The authorization code is valid for 10 minutes and can only be used once.

Step 4: Exchange the code for a token

From your server side (not the browser), exchange the code for an access token with the following POST request:

POST /api/v1/auth/token
Content-Type: application/json

{
    "grantType": "authorization_code",
    "clientId": "YOUR_CLIENT_ID",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "code": "AUTHORIZATION_CODE",
    "redirectUri": "YOUR_REDIRECT_URI"
}

Success response (200):

{
    "accessToken": "aBcDeFgH1234567890...",
    "refreshToken": "xYzAbCdEfG098765...",
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "scope": "store.products.read store.orders.read"
}
Field Description
accessToken Used when calling the API. Valid for 1 hour.
refreshToken Used to obtain a new token when the access token expires. Valid for 30 days.
expiresIn The token's lifetime in seconds. 3600 = 1 hour
scope The scopes the business owner approved

Step 5: Call the API

Include the access token in the Authorization header of your request:

GET /api/v1/store/products
Authorization: Bearer aBcDeFgH1234567890...
Content-Type: application/json

The API returns data associated with the business account that authorized the app. You can access only the data allowed by the approved scopes.


Step 6: Refresh an expired token

When the access token expires, use the refresh token to obtain a new token pair:

POST /api/v1/auth/token
Content-Type: application/json

{
    "grantType": "refresh_token",
    "clientId": "YOUR_CLIENT_ID",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "refreshToken": "xYzAbCdEfG098765..."
}

The response format is the same as Step 4. The old access token and refresh token are invalidated, and a new pair is returned.


Revoking a token

To revoke an access token or refresh token:

POST /api/v1/auth/revoke
Content-Type: application/json

{
    "token": "the token to revoke",
    "clientId": "YOUR_CLIENT_ID"
}

A business owner can also revoke an app's access at any time from their account settings.


Error responses

HTTP status Error Description
400 unsupported_grant_type Only authorization_code and refresh_token are supported
400 invalid_request A required parameter is missing
401 invalid_grant Invalid code, expired code, credential mismatch, or redirect URI mismatch
400 invalid_client Unknown client_id
400 invalid_redirect_uri The redirect_uri doesn't match the registered URI

Available scopes

Store

Scope Description
store.products.read Read product and inventory information
store.products.write Create and update products
store.orders.read Read order data
store.orders.write Update order status
store.customers.read Read customer data
store.coupons.read Read coupon data
store.coupons.write Create and update coupons
store.inventory.read Read warehouse and stock data

CRM (Customer Relationship Management)

Scope Description
crm.profiles.read Read CRM customer profiles
crm.segments.read Read CRM segments and lists

SNS / Analytics

Scope Description
sns.content.read Read SNS post data
sns.audience.read Read SNS audience data
analytics.read Read analytics snapshots

Flow diagram

┌──────────────┐     ┌──────────────┐     ┌──────────────────┐
│  Your app    │     │ Business     │     │  ReceiptRoller   │
│  (developer) │     │ owner        │     │  platform        │
└──────┬───────┘     └──────┬───────┘     └────────┬─────────┘
       │                    │                      │
       │  1. Redirect to /oauth/authorize          │
       │──────────────────────▶│──────────────────────▶│
       │                    │                      │
       │                    │  2. Show consent screen │
       │                    │◀──────────────────────│
       │                    │                      │
       │                    │  3. Allow             │
       │                    │──────────────────────▶│
       │                    │                      │
       │  4. Redirect with ?code=authorization code │
       │◀──────────────────│◀──────────────────────│
       │                    │                      │
       │  5. POST /api/v1/auth/token               │
       │  (code + client_id + client_secret)       │
       │────────────────────────────────────────────▶│
       │                                           │
       │  6. { accessToken, refreshToken }         │
       │◀────────────────────────────────────────────│
       │                                           │
       │  7. GET /api/v1/store/products            │
       │  Authorization: Bearer {accessToken}      │
       │────────────────────────────────────────────▶│
       │                                           │
       │  8. { data: [...] }                       │
       │◀────────────────────────────────────────────│

Security best practices

  • Keep the client_secret on the server side only. Never include it in frontend code or a mobile app.
  • Always verify the state parameter to prevent CSRF attacks.
  • Use PKCE (code_challenge / code_verifier) for mobile apps and single-page app scenarios.
  • Store tokens securely. Don't log access tokens or include them in URLs.
  • Implement token refresh before expiry to avoid service interruptions.
  • Request only the scopes your app actually needs.
Published: 2026-03-27 Updated: 2026-07-05