> ## Documentation Index
> Fetch the complete documentation index at: https://dev.smile.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from API keys to OAuth

> Migrate your legacy integration from using merchant credentials (API keys) to using modern OAuth instead.

This guide is for partners who currently integrate with Smile using merchant-created API keys and want to migrate to an [OAuth app](/guides/apps/build) instead. It walks through what changes, how to migrate your code, and how to move your existing merchants over.

## What changes

For your code, surprisingly little — and the experience for merchants gets much better. You still call the same Smile [REST API](/api/introduction): the same endpoints, the same requests, and the same responses. What changes is how merchants connect your app up front, and the `Authorization` header you send with each API call.

At a glance, here's why OAuth is better for developers and merchants alike:

|                                      |      🔑 API keys     |      🔐 OAuth     |
| ------------------------------------ | :------------------: | :---------------: |
| Smile plan required                  |  Plus or Enterprise  |   Any paid plan   |
| Setup experience                     |  Manual copy & paste | One-click connect |
| Access scope selection               | Manual (error prone) |     Automatic     |
| Adding access scopes                 |  Requires a new key  |   Added anytime   |
| Zero-downtime token rotation         |           ❌          |         ✅         |
| Loyalty account creation via the API |           ❌          |         ✅         |
| Webhook access                       |           ❌          |         ✅         |
| In-app integration listing           |           ❌          |         ✅         |
| Partner Portal access                |           ❌          |         ✅         |

## Before you start

This guide assumes you have an app in the [Partner Portal](https://partners.smile.io/) to configure during the migration. If you don't have one yet, refer to our guide on [building an app](/guides/apps/build) to get started.

Before writing any code, it helps to take stock of your current integration:

* **Create a list** of all the REST API endpoints your integration uses. For each one, take note of the required access scope, since you'll need this to configure your OAuth app. The required scope for each endpoint is listed in the [API Reference](/api/introduction).

## How to migrate

### 1. Get familiar with OAuth

OAuth apps use an OAuth 2.0 flow for granting your integration access to a Smile account. If you're not already familiar with OAuth, we recommend reading our [auth guide](/guides/apps/auth/overview) to get a sense for how this works before beginning the migration.

### 2. Configure your app

In the [Partner Portal](https://partners.smile.io/), open your app and configure its settings:

* Add your **Install URL** and one or more **Whitelisted Redirect URLs**.
* Confirm the **Access scopes** your app needs (based on the API endpoints you're using).
* Copy your **Client ID** and **Client secret** — you'll need these for the OAuth flow.

<Tip>
  Treat your Client secret like a password and store it only in secured backend code. If it's ever exposed, you can [rotate it with zero downtime](/guides/apps/auth/oauth-rotation).
</Tip>

### 3. Add a Connect Smile button

Swap the part of your merchant setup flow that asks for an API key with a **Connect Smile** button. When a merchant clicks it, [redirect them to Smile's authorization page](/guides/apps/auth/oauth-flow#step-1-request-authorization), passing your Client ID and a `state` value you can verify later. After they approve the connection, Smile redirects them back to your `redirect_uri` with a temporary authorization `code`. Confirm the `state` matches the one you sent, then continue to the token exchange.

### 4. Exchange for an access token

[Exchange the authorization code](/guides/apps/auth/oauth-flow#step-3-get-an-access-token) for an access token via a server-to-server request authenticated by your Client ID and Client secret. The response includes an access token, a refresh token, an `expires_in` lifetime, and the `smile_account_id`.

For each merchant, securely store the **access token**, **refresh token**, **token expiry** (derived from `expires_in`), and **`smile_account_id`**. The `smile_account_id` identifies which Smile account the tokens belong to — store it alongside the merchant record that previously held their API key.

### 5. Update API call auth

Wherever your integration previously sent the merchant's API key, send their OAuth access token instead. The request is otherwise unchanged:

```shell cURL theme={null} theme={null}
curl https://api.smile.io/v1/customers \
  -H "Authorization: Bearer api_cnzGMghxTmPzK1sp" # [!code --]
  -H "Authorization: Bearer oa2_925f6e2f64f89bf4075bb8172c9a471f7f8b4e331bb7bf6d9c94a8029382cf45" # [!code ++]
```

### 6. Refresh access tokens

Unlike API keys, OAuth access tokens expire — a request made with an expired token returns `401 Unauthorized`. Store each access token's expiry and, before it lapses, use the stored refresh token to [request a new access token](/guides/apps/auth/oauth-flow#step-5-refreshing-an-access-token).

### 7. Use activities for actions

This step only applies if you currently use the [create a points transaction](/api/resources/points-transactions/create-points-transaction) endpoint. Smile offers two ways to issue points to customers, and the right approach depends on *why* you're issuing points:

* **Points transactions** directly add or remove points from a customer's balance, like a ledger entry. Use these for adjustments that aren't tied to a customer action — manual corrections, goodwill credits, or porting over an existing balance from a legacy system.
* **Activities** tell Smile that a customer *performed a rewardable action* — like leaving a review or subscribing to a newsletter. Smile evaluates activities against the merchant's configured ways to earn and issues the correct number of points automatically, without you needing to do any math or additional validation.

<Note>
  Points transactions aren't going away. If you only ever adjusted balances directly and never issued points for a customer action, no changes are required.
</Note>

If your integration used points transactions to **reward customer actions**, switch to using activities instead. Activities have a few benefits for merchants and customers:

1. Merchants configure how many points customers will receive in Smile Admin, centralizing where loyalty program configuration is managed.
2. Points issued via activities are correctly recorded and displayed within the merchant's loyalty program analytics — making it easier for them to understand how customers are earning points.
3. Customers will see how many points they'll earn for performing an activity across all loyalty surfaces (like the rewards widget and Smile's Loyalty Hub).

<Warning>
  Activities issue a fixed number of points per action, set by the merchant's ways to earn. If you need to award a variable amount based on a property of the action — like points per dollar on a scanned receipt — keep using a points transaction and calculate the amount yourself.
</Warning>

To migrate from using points transactions to activities:

<Steps>
  <Step title="Find your points transaction calls">
    Locate each place your integration calls [`POST /points_transactions`](/api/resources/points-transactions/create-points-transaction). For each one, decide whether it rewards a customer action or just adjusts a balance — only action-based calls need to change.
  </Step>

  <Step title="Define an activity type">
    For each customer action, [define a new activity type](/guides/apps/activities#defining-a-new-activity-type) for your app in the [Partner Portal](https://partners.smile.io/apps). This is the action merchants build their ways to earn around.
  </Step>

  <Step title="Switch the API call">
    Replace the points transaction call with a [create activity](/api/resources/activities/create-activity) call, identifying the customer by Smile Customer ID or email. You no longer send a points amount — the merchant's ways to earn determine the reward, and Smile issues it automatically once the activity is evaluated.

    <Check>
      Creating an activity requires the `activity:write` scope, so confirm it's included in your app's access scopes (from step 2).
    </Check>
  </Step>
</Steps>

### 8. Test on a dev account

Once you've finished building, the next step is to verify the end-to-end flow on a development Smile account:

* A merchant can connect your app through OAuth and land back in your app connected.
* Your app exchanges the authorization code for an access token and stores it.
* Your app refreshes an access token successfully.
* Every Smile API endpoint your integration uses works with the granted scopes.
* If applicable, activity behavior works end to end.

<Tip>
  Only development accounts can install unreviewed apps. If you need additional Smile accounts for testing, reach out to your partner manager.
</Tip>

### 9. Submit for review

Once your app is built and tested, make sure it meets the [app requirements](/guides/apps/submission/requirements) and submit it for review through the Partner Portal. Refer to our [submission and review guide](/guides/apps/submission/process) for a full walkthrough of the process.

## Migrate existing merchants

Merchants who already connected your integration with an API key **can't be automatically converted to OAuth** — each one needs to re-connect your app using the OAuth flow.

To move an existing merchant over:

1. Prompt the merchant to connect your app via the **Connect Smile** flow.
2. Once they've connected and you've stored their tokens, switch to using the OAuth access token for that merchant.
3. Stop using their stored API key, and give them guidance on removing the old key from Smile if they'd like to.

Because the new OAuth flow can run alongside your existing API key integration, you can migrate merchants gradually rather than all at once.

### Communicate the benefits

When you prompt a merchant to reconnect, it helps to explain what they get from switching. Lead with the benefits that apply to everyone, then add the ones specific to your integration:

* **More secure** — OAuth uses scoped access tokens with [zero-downtime token rotation](/guides/apps/auth/oauth-rotation) instead of long-lived API keys, keeping the merchant's data safe.
* **New features automatically** — with OAuth, your integration can roll out new features without needing to ask merchants to regenerate and re-copy API keys, so they always get the latest functionality!
* **Better analytics** (if you move to activities) — points issued via activities are recorded in the merchant's loyalty program analytics and shown across all loyalty surfaces, like the rewards widget and Smile's Loyalty Hub.
* **Faster updates** (if you adopt webhooks) — your app can [subscribe to webhooks](/guides/apps/webhooks) instead of polling, so customer updates sync in near real time.

## Migration checklist

Use this to track your migration:

* [ ] I can explain what my current API key integration does.
* [ ] I know which Smile API endpoints my integration calls.
* [ ] I confirmed which OAuth access scopes my app needs.
* [ ] I configured my app's Install URL, Whitelisted Redirect URLs, and access scopes in the Partner Portal.
* [ ] I added a **Connect Smile** button to my app.
* [ ] A merchant can approve my app in Smile and return to my app connected.
* [ ] My app exchanges the authorization code for an access token and stores it securely.
* [ ] My app calls the Smile API with the OAuth access token.
* [ ] My app refreshes the access token when it expires.
* [ ] I moved any action-based points transactions to activities (if applicable).
* [ ] My existing merchants know they need to reconnect once.
* [ ] After a merchant reconnects, my app stops using their old API key.
* [ ] I tested the full flow on a development Smile account.

## Future considerations

You don't need these to migrate, but they're worth revisiting once your OAuth app is live.

### Replace polling with webhooks

OAuth apps can [subscribe to webhooks](/guides/apps/webhooks), so if your integration is currently polling for customer updates, this behavior can be replaced with a webhook subscription. There's no need to rewrite your syncing logic as part of the migration though — you can adopt webhooks whenever it's convenient.

## Where to get help

If you have questions about the migration or your app setup, reach out to your partner manager or our [support team](https://help.smile.io/en/articles/4495476-how-to-get-help-with-smile). For a deeper look at the moving parts, see the [OAuth flow](/guides/apps/auth/oauth-flow), [access scopes](/guides/apps/auth/access-scopes), and [building an app](/guides/apps/build) guides.

## FAQ

<Accordion title="Do the calls I'm making to the Smile REST API need to change?">
  No. The endpoints, request formats, and responses are the same. The only change is the credential in the `Authorization` header — an OAuth access token (`oa2_...`) instead of an API key (`api_...`).
</Accordion>

<Accordion title="Can my integration use API keys and OAuth at the same time?">
  Yes. The OAuth install flow can run alongside your existing API key setup, so you can build and test OAuth, then move merchants over gradually rather than all at once. That said, we don't recommend allowing both indefinitely as it will lead to difficulty with debugging and maintenance over time.
</Accordion>

<Accordion title="What happens to a merchant's existing API key after they reconnect with OAuth?">
  Nothing automatic. Once a merchant has connected via OAuth and you've stored their access token and refresh token, you should advise the merchant to [delete the old API key](https://help.smile.io/en/articles/11328240-manage-api-keys#delete-an-api-key) in Smile — but until they do so, their API key will continue to function as normal.
</Accordion>

<Accordion title="Which OAuth scopes should my app request?">
  Request the scopes that match what your API keys do today. Smile uses the same `read`/`write` scope model for both, and the required scope for each endpoint is listed in the [API Reference](/api/introduction). Refer to our [access scopes](/guides/apps/auth/access-scopes) guide for additional information on how this model works.
</Accordion>
