Skip to content

Commit b15a21d

Browse files
9.0.0 release (#64)
1 parent 3bf8416 commit b15a21d

891 files changed

Lines changed: 9876 additions & 6035 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [9.0.0] - revision 2024-02-15
5+
6+
### Changed
7+
8+
- OAuth support has been moved to GA, view the [building a new integration guide](https://developers.klaviyo.com/en/docs/build_your_integration) for more information.
9+
410
## [8.0.0] - revision 2024-02-15
511

612
### Added:
@@ -276,4 +282,4 @@ In addition, you can [make client-side API calls](https://developers.klaviyo.com
276282
- Package name: klaviyo-sdk-betaklaviyo-api
277283
- Some functions have changed name
278284
- New resources and endpoints:
279-
- See [API Changelog](https://developers.klaviyo.com/en/docs/changelog_) for full details
285+
- See [API Changelog](https://developers.klaviyo.com/en/docs/changelog_) for full details

README.md

Lines changed: 167 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Klaviyo Typescript SDK
22

3-
- SDK version: 8.0.0
3+
- SDK version: 9.0.0
44

55
- Revision: 2024-02-15
66

@@ -48,7 +48,7 @@ This SDK is organized into the following resources:
4848

4949
You can install this library using `npm`.
5050

51-
`npm install klaviyo-api@8.0.0`
51+
`npm install klaviyo-api@9.0.0`
5252

5353

5454
## source code
@@ -74,17 +74,6 @@ If you want to test out the repo but don't have a consuming app, you can run our
7474
npm run sample --pk=<YOUR PRIVATE KEY HERE>
7575
```
7676

77-
## OAuth Beta
78-
79-
To read about our OAuth beta for users who want to write multi-user integrations, check out this [help center article](https://help.klaviyo.com/hc/en-us/articles/18819413031067#h_01HACEKGF33GHFEH733YK2JKTT)
80-
81-
If you already are in the OAuth beta, read the documentation in the [`oauth-beta` branch](https://github.com/klaviyo/klaviyo-api-node/tree/oauth-beta) in this repo or check out the [example application](https://github.com/klaviyo-labs/node-integration-example).
82-
83-
Install the beta package with the following command:
84-
```bash
85-
npm i klaviyo-api@beta
86-
```
87-
8877
# Usage Example
8978

9079
### To instantiate an API wrapper using an API Key
@@ -138,7 +127,7 @@ you can override
138127
- startingDelay
139128

140129
```Typescript
141-
const retryOptions: RetryOptions = new RetryOptions(3, 5, 500)
130+
const retryOptions: RetryOptions = new RetryOptions({numOfAttempts: 3, timeMultiple: 5, startingDelay: 500)
142131
const session = new ApiKeySession("< YOUR API KEY HERE >", retryOptions)
143132
```
144133
@@ -218,6 +207,170 @@ Profiles.getProfiles().then(result => {
218207
});
219208
```
220209

210+
## Using OAuth to connect to multiple Klaviyo accounts.
211+
212+
For users creating integrations or managing multiple Klaviyo accounts, Klaviyo's OAuth authentication will make these tasks easier.
213+
214+
### Getting started with OAuth
215+
216+
First, configure an integration. If you haven't set up an integration, learn about it in this [guide](https://developers.klaviyo.com/en/v2024-02-15/docs/set_up_oauth)
217+
218+
### Making API Calls with OAuth
219+
The `klaviyo-api` package can keep your `access token` up to date. If you have already developed a system for refreshing tokens or would like a more minimalist option, skip to [OAuthBasicSession](#oauthbasicsession)
220+
221+
#### TokenStorage
222+
For the OAuthApi to be storage agnostic, this interface must be implemented for the `OAuthApi` to retrieve and save you `access` and `refresh` tokens.
223+
Implement the `retrieve` and `save` functions outlined in the interface. If you need help getting started, check out the `storageHelpers.ts` in the [Klaviyo Example Typescript Integration](https://github.com/klaviyo-labs/node-integration-example)
224+
225+
Your implementation needs to include two methods:
226+
1. `save` is called after creating a new `access token` via the authorization flow or after refreshing the `access token`.
227+
Your code needs to update (and insert if you are going to be using `createTokens()`) the new `access` or `refresh` token information into storage
228+
to keep track of which of your integration users' access information you are referencing, the `customerIdentifier` is a unique value to help with lookup later.
229+
```typescript
230+
save(customerIdentifier: string, tokens: CreatedTokens): Promise<void> | void
231+
```
232+
2. `retrieve` leverages the `customerIdentifier` to look up the saved token information and returns it for the `OAuthApi` to use
233+
```typescript
234+
retrieve(customerIdentifier: string): Promise<RetrievedTokens> | RetrievedTokens
235+
```
236+
237+
```typescript
238+
import { TokenStorage } from 'klaviyo-api';
239+
class <Your Token Storage Class Name Here> implements TokenStorage
240+
```
241+
242+
#### OAuthApi
243+
This class holds the information about your specific integration. It takes three inputs:
244+
1. `clientId` - This is the id of your integration. Retrieve it from your integration's settings page
245+
2. `clientSecret` - This is the secret for your integration. The secret is generated upon the creation of your integration.
246+
3. `tokenStorage` - This is an instance of your implementation of `TokenStorage` and is called automatically when creating and refreshing `access tokens`
247+
248+
249+
```typescript
250+
import { OAuthApi } from 'klaviyo-api';
251+
252+
const oauthApi = new OAuthApi("<client id>", "<client secret>", <instance of your TokenStorage implimentation>)
253+
```
254+
255+
#### `OAuthSession`
256+
To make an API call, you need to create an `OAuthSession` instance. This session object is the OAuth equivalent of `ApiKeySession` and is used similarly.
257+
258+
It takes two properties
259+
1. `customerIdentifier` - This is how the session is going to grab a user's authentication information and let your implementation of `TokenStorage` know where to save any update `access token`
260+
2. `oauthApi` - This is the instance of `OAuthApi` created above. It will dictate how the session `saves` and `retrieves` the `access tokens`
261+
3. `retryOptions` - OPTIONAL - the `RetryOptions` instance outlines your desired exponential backoff retry options, outlined in [Retry Options](#retry-options) above
262+
263+
```typescript
264+
import { OAuthSession, ProfilesApi } from 'klaviyo-api';
265+
266+
const session = new OAuthSession(customerIdentifier, oauthApi)
267+
268+
//Pass the session into the API you want to use
269+
const profileApi = new ProfilesApi(session)
270+
```
271+
272+
#### `OAuthBasicSession`
273+
If you don't want to deal with any of the helpers above or don't want `klaviyo-api` to refresh your tokens for you, this is the alternative.
274+
275+
The `OAuthBasicSession` takes up to two parameters
276+
1. `accessToken` - The token is used in the API calls' authentication
277+
2. `retryOptions` - OPTIONAL - the `RetryOptions` instance outlines your desired exponential backoff retry options, outlined in [Retry Options](#retry-options) above
278+
279+
```typescript
280+
import { OAuthBasicSession } from 'klaviyo-api';
281+
282+
const session = new OAuthBasicSession("<access token>")
283+
284+
//Pass the session into the API you want to use
285+
const profileApi = new ProfilesApi(session)
286+
```
287+
288+
Remember to check for `401` errors. A 401 means that your token is probably expired.
289+
290+
#### `KlaviyoTokenError`
291+
292+
If an error occurred during an API call, check the error type with `isKlaviyoTokenError`. The name property will reflect which step the error occurred, reflecting whether it happened during creating, refreshing, saving, or retrieving the `name` tokens. The `cause` property will hold the error object of whatever specific error occurred.
293+
294+
### Authorization Flow
295+
296+
Build The authorization flow in the same application as with the rest of your integrations business logic or separately.
297+
There is no requirement that the authorization flow has to be backend and can be implemented entirely in a frontend application (in that case, you can ignore this section, as this repo shouldn't use this for frontend code)
298+
299+
To understand the authorization flow, there are two major resources to help:
300+
1. [OAuth authorization guide](https://developers.klaviyo.com/en/v2024-02-15/docs/set_up_oauth#1-user-installs-your-integration)
301+
2. [Node Integration Example](https://github.com/klaviyo-labs/node-integration-example)
302+
303+
If you implement your authorization flow on a node server, you can use these exposed helper functions.
304+
305+
#### OAuthApi
306+
307+
The OAuthApi class also exposes helpful Authorization flow utilities.
308+
309+
1. `generateAuthorizeUrl` - This helps correctly format the Klaviyo `/oauth/authorize` URL the application needs to redirect to so a user can approve your integration.
310+
1. `state` - This is the only way to identify which user just authorized your application (or failed to). `state` is passed back via query parameter to your `redirectUrl`.
311+
2. `scope` - The permissions the created `access tokens` will have. The user will be displayed these scopes during the authorization flow. For these permissions to work, also add them to your app settings in Klaviyo [here](www.klaviyo.com/oauth/client)
312+
3. `codeChallenge` - This is the value generated above by the `generateCode` function.
313+
4. `redirectUrl` - This is the URL that Klaviyo will redirect the user to once Authorization is completed (even if it is denied or has an error).
314+
Remember to whitelist this redirect URL in your integration's settings in Klaviyo.
315+
```typescript
316+
import { OAuthApi } from 'klaviyo-api'
317+
318+
const oauthApi = new OAuthApi("<client id>", "<client secret>", <TokenStorage implementation instance>)
319+
oauthApi.generateAuthorizeUrl(
320+
state, // It's suggested to use your internal identifier for the Klaviyo account that is authorizing
321+
scopes,
322+
codeChallenge,
323+
redirectUrl
324+
)
325+
```
326+
2. `createTokens` - Uses Klaviyo `/oauth/token/` endpoint to create `access` and `refresh` tokens
327+
1. `customerIdentifier` - This ID is NOT sent to Klaviyo's API. If the `/token` API call this method wraps is successful, the created tokens will be passed into your `save` method along with this `customerIdentifier` in your implementation of `TokenStorage`.
328+
2. `codeVerifier` - The verifier code must match the challenge code in the authorized URL redirect.
329+
3. `authorizationCode`- A User approving your integration creates this temporary authorization code. Your specified redirect URL receives this under a `code` query parameter.
330+
4. `redirectUrl` - The endpoint set in `generateAuthorizeUrl`. Whitelist the URL in your application settings.
331+
332+
```typescript
333+
import { OAuthApi } from 'klaviyo-api'
334+
335+
const oauthApi = new OAuthApi("<client id>", "<client secret>", <TokenStorage implementation instance>)
336+
await oauthApi.createTokens(
337+
customerIdentifier,
338+
codeVerifier,
339+
authorizationCode,
340+
redirectUrl
341+
)
342+
```
343+
3. `OAuthCallbackQueryParams` For typescript users, this object is an interface representing the possible query parameters sent to your redirect endpoint
344+
345+
346+
347+
#### Proof Key of Code Exchange (PKCE)
348+
349+
All the PKCE helper functions live within the `Pkce` namespace. Read about PKCE [here](https://developers.klaviyo.com/en/v2024-02-15/docs/set_up_oauth#pkce-and-code-challenges)
350+
351+
```typescript
352+
import { Pkce } from 'klaviyo-api'
353+
```
354+
355+
The `Pkce` namespace holds two different helper utilities
356+
1. `generateCodes` - This method will create the `codeVerifier` and `codeChallenge` needed later in the authorization flow.
357+
358+
```typescript
359+
import { Pkce } from 'klaviyo-api'
360+
361+
const pkceCodes = new Pkce.generateCodes()
362+
// the two codes can be accessed by
363+
const codeVerifier: string = pkceCodes.codeVerifier
364+
const codeChallenge: string = pkceCodes.codeChallenge
365+
```
366+
367+
2. `CodeStorage` - This is an OPTIONAL interface to help keep your code organized, to relate a `customerIdentifier` to their generated PKCE code
368+
369+
```typescript
370+
import { Pkce } from 'klaviyo-api'
371+
class <Your Code Storage Class Here> implements Pkce.CodeStorage
372+
```
373+
221374
## Optional Parameters and [JSON:API](https://jsonapi.org/) features
222375
223376
Here we will go over

0 commit comments

Comments
 (0)