Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4 API: OAuth #74

Merged
merged 118 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
9bd41a8
Updated methods
n7studios Mar 21, 2024
a47d0e9
Started tests
n7studios Mar 21, 2024
bf6c5d4
Started work on subscriber methods
n7studios Mar 21, 2024
344b717
Completed first pass of subscriber methods
n7studios Mar 21, 2024
2d9db50
Added `callback_url` for bulk add subscribers
n7studios Mar 21, 2024
24faea8
Started stubbing tests
n7studios Mar 21, 2024
b0588ce
Add `get_response_interface` and `get_response_status_code` helper me…
n7studios Mar 21, 2024
ba62560
Remove `status_code`, as response object includes it
n7studios Mar 21, 2024
f116beb
Moved test
n7studios Mar 21, 2024
fc64de9
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-get-re…
n7studios Mar 22, 2024
5ea28c7
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-subscr…
n7studios Mar 22, 2024
58c96ea
Started writing tests for `get_subscribers`
n7studios Mar 22, 2024
134f661
Continued tests for `get_subscribers`
n7studios Mar 22, 2024
f9e515d
Completed `get_subscribers` tests
n7studios Mar 22, 2024
43a2375
Started tests for `create_subscriber`
n7studios Mar 22, 2024
c61d362
Completed `create_subscriber` tests
n7studios Mar 22, 2024
d657bfa
Completed tests
n7studios Mar 22, 2024
099a8b4
testCreateSubscriberWithSubscriberState: Use `cancelled` state for test
n7studios Mar 25, 2024
b07a92f
Merge pull request #78 from ConvertKit/v4-api-get-response-interface
n7studios Mar 25, 2024
1e96e97
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-tags
n7studios Mar 25, 2024
90a293d
Merge remote-tracking branch 'origin/v4-api-subscribers' into v4-api-…
n7studios Mar 25, 2024
0260896
Tests: Added tag subscriber tests
n7studios Mar 25, 2024
c4e213e
Completed tests
n7studios Mar 25, 2024
d6f77de
Coding standards
n7studios Mar 25, 2024
05ec7a7
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-subscr…
n7studios Mar 25, 2024
7d2a27f
Merge remote-tracking branch 'origin/v4-api-subscribers' into v4-api-…
n7studios Mar 25, 2024
37046c4
Merge pull request #79 from ConvertKit/v4-api-subscribers
n7studios Mar 26, 2024
b9a4ac5
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-tags
n7studios Mar 26, 2024
3cb241a
Tests: Fix bulk tag tests
n7studios Mar 26, 2024
142217f
Started work on custom fields endpoint
n7studios Mar 26, 2024
43c1676
Finished tests, coding standards and PHPStan compat.
n7studios Mar 26, 2024
c63ca41
Started work on purchases endpoint
n7studios Mar 26, 2024
6e5fbb4
Completed tests
n7studios Mar 26, 2024
484e468
Coding standards
n7studios Mar 26, 2024
6ca1552
Merge pull request #81 from ConvertKit/v4-api-custom-fields
n7studios Mar 26, 2024
23b7acb
Fix test name
n7studios Mar 26, 2024
ba72fd2
Rename `list_purchases` to `get_purchases`, to match other get methods
n7studios Mar 26, 2024
e55ea9f
Merge pull request #80 from ConvertKit/v4-api-tags
n7studios Mar 26, 2024
fac95a9
Merge branch 'master' into v4-api-oauth
n7studios Mar 26, 2024
f292de3
Standardise method names for subscribers; append `_by_email` to secon…
n7studios Mar 26, 2024
40716d7
Update links to v4 API docs in comments
n7studios Mar 26, 2024
d496d0f
Fix GitHub Action failing
n7studios Mar 26, 2024
cdcf7bf
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-purchases
n7studios Mar 26, 2024
7e3da7d
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-method…
n7studios Mar 26, 2024
6afae4b
PHPStan compat.
n7studios Mar 26, 2024
53ab9ad
Fix named arguments in tests
n7studios Mar 26, 2024
ce145dc
Update tests to reflect changed method names
n7studios Mar 27, 2024
63cf328
Add `tearDown` method to cleanup account data on test pass/fail
n7studios Mar 27, 2024
c4a48b0
Coding standards
n7studios Mar 27, 2024
683108d
Remove test assertions for `has_previous_page` at end of each paginat…
n7studios Mar 27, 2024
a000063
Remove `assertCount` at end of pagination tests, as again tests in pa…
n7studios Mar 27, 2024
8b7817f
Added `get_segments` method
n7studios Mar 27, 2024
f1ed6ae
Merge pull request #84 from ConvertKit/v4-api-cleanup-tests
n7studios Mar 27, 2024
238b576
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-method…
n7studios Mar 27, 2024
a8e809b
Change `unsubscribe_by_id` to `unsubscribe` in test `tearDown`
n7studios Mar 27, 2024
20850c1
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-purchases
n7studios Mar 27, 2024
4ca113b
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-segments
n7studios Mar 27, 2024
9ce7da4
Add `get_email_templates` method
n7studios Mar 27, 2024
4ab0cba
Merge pull request #82 from ConvertKit/v4-api-purchases
n7studios Mar 28, 2024
af25143
Merge pull request #83 from ConvertKit/v4-api-method-names
n7studios Mar 28, 2024
7bdbfb9
Merge pull request #85 from ConvertKit/v4-api-segments
n7studios Mar 28, 2024
bfe2ec9
Merge pull request #86 from ConvertKit/v4-api-email-templates
n7studios Mar 28, 2024
b64d07d
Updated methods and tests
n7studios Mar 28, 2024
6152f05
Added `testGetBroadcastsPagination` test
n7studios Mar 28, 2024
2434844
Added `include_total_count` to pagination args
n7studios Mar 28, 2024
0df40a7
Added `include_total_count` to methods
n7studios Mar 28, 2024
7b5fcef
Started tests
n7studios Mar 28, 2024
2a33578
Coding standards
n7studios Mar 28, 2024
54bf2a8
Fix failing tests
n7studios Mar 28, 2024
b82e8de
Merge pull request #88 from ConvertKit/v4-api-include-total-count
n7studios Mar 29, 2024
1a35c36
Add `sku` to products; reflect required and optional fields
n7studios Mar 29, 2024
1ffa58e
Mock `create_tags` and `create_tags` tests
n7studios Mar 29, 2024
bfac523
Update `get_forms` and `get_landing_pages` methods
n7studios Mar 29, 2024
6e5a0b0
Started tests
n7studios Mar 29, 2024
7e8b632
Merge pull request #90 from ConvertKit/v4-api-mock-create-tag-tests
n7studios Apr 1, 2024
8354a55
Merge pull request #89 from ConvertKit/v4-api-purchases-sku
n7studios Apr 1, 2024
d5d2e4f
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-broadc…
n7studios Apr 1, 2024
d0221a4
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-forms-…
n7studios Apr 1, 2024
a6753fa
Coding standards
n7studios Apr 1, 2024
95a2256
Add form pagination and total count tests
n7studios Apr 1, 2024
c63a6ae
Fix undefined method `build_pagination_params
n7studios Apr 1, 2024
512ea0a
Added landing page tests
n7studios Apr 1, 2024
6197652
Remove deprecated `get_resources` tests
n7studios Apr 1, 2024
12c0618
Add API support
n7studios Apr 1, 2024
b04f628
Started tests
n7studios Apr 1, 2024
b6e94c0
Use `type` parameter to fetch Forms or Landing Pages
n7studios Apr 2, 2024
bf449bf
Completed tests
n7studios Apr 2, 2024
f7fe5e1
Merge pull request #87 from ConvertKit/v4-api-broadcasts
n7studios Apr 2, 2024
69c4cc9
Create subscriber when subscribing to resource (form, tag, sequence)
n7studios Apr 2, 2024
3803eb8
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-improv…
n7studios Apr 2, 2024
8d57692
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-webhooks
n7studios Apr 2, 2024
dba401b
Merge pull request #92 from ConvertKit/v4-api-webhooks
n7studios Apr 2, 2024
0abfdc3
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-improv…
n7studios Apr 2, 2024
87e871a
Completed tests for `type` filtering
n7studios Apr 2, 2024
02de911
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-forms-…
n7studios Apr 2, 2024
59c50ab
Merge pull request #93 from ConvertKit/v4-api-improve-subscriber-tests
n7studios Apr 4, 2024
67e1346
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-forms-…
n7studios Apr 4, 2024
57bbb00
Updated `get_forms` and `get_landing_pages` to support new `status` f…
n7studios Apr 4, 2024
66cb9ae
Completed tests
n7studios Apr 4, 2024
68d149a
Set headers on `Request` object instead of `Client`
n7studios Apr 4, 2024
8fcdcc8
Run `testGetResource` tests
n7studios Apr 4, 2024
688f14e
Coding standards
n7studios Apr 4, 2024
10f8442
Merge pull request #91 from ConvertKit/v4-api-forms-pagination
n7studios Apr 5, 2024
06c94be
Merge remote-tracking branch 'origin/v4-api-oauth' into v4-api-get-ht…
n7studios Apr 9, 2024
2bb2b37
Use helper methods for user agent and headers
n7studios Apr 9, 2024
fcb034f
Add `auth` parameter to `request_headers` method with tests
n7studios Apr 9, 2024
a596a33
Merge pull request #94 from ConvertKit/v4-api-get-html-resource
n7studios Apr 9, 2024
f6563c9
First draft of migration guide
n7studios Apr 11, 2024
f327145
Update wording on how to register an OAuth application
n7studios Apr 11, 2024
fb47594
Added links between readme and migration guide
n7studios Apr 11, 2024
c5ac174
Fixed indenting of sub bullet points
n7studios Apr 11, 2024
3d22954
Implement methods as traits for portability across multiple API clients
n7studios Apr 12, 2024
d93c396
Coding Standards
n7studios Apr 12, 2024
e73f492
Move `VERSION` const
n7studios Apr 12, 2024
6277e11
Fix tests to call correct `get_request_headers` method
n7studios Apr 12, 2024
3276476
Fix `get_subscriber_id` definition when no subscribers found by email
n7studios Apr 12, 2024
4ade456
Merge pull request #95 from ConvertKit/v4-api-docs
n7studios Apr 12, 2024
d079068
Merge pull request #96 from ConvertKit/v4-api-methods-traits
n7studios Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ jobs:
path: .env.dist.testing
contents: |

CONVERTKIT_API_KEY=${{ secrets.CONVERTKIT_API_KEY }}
CONVERTKIT_API_SECRET=${{ secrets.CONVERTKIT_API_SECRET }}
CONVERTKIT_API_KEY_NO_DATA=${{ secrets.CONVERTKIT_API_KEY_NO_DATA }}
CONVERTKIT_API_SECRET_NO_DATA=${{ secrets.CONVERTKIT_API_SECRET_NO_DATA }}
CONVERTKIT_OAUTH_ACCESS_TOKEN=${{ secrets.CONVERTKIT_OAUTH_ACCESS_TOKEN }}
CONVERTKIT_OAUTH_REFRESH_TOKEN=${{ secrets.CONVERTKIT_OAUTH_REFRESH_TOKEN }}
CONVERTKIT_OAUTH_ACCESS_TOKEN_NO_DATA=${{ secrets.CONVERTKIT_OAUTH_ACCESS_TOKEN_NO_DATA }}
CONVERTKIT_OAUTH_REFRESH_TOKEN_NO_DATA=${{ secrets.CONVERTKIT_OAUTH_REFRESH_TOKEN_NO_DATA }}
CONVERTKIT_OAUTH_CLIENT_ID=${{ secrets.CONVERTKIT_OAUTH_CLIENT_ID }}
CONVERTKIT_OAUTH_CLIENT_SECRET=${{ secrets.CONVERTKIT_OAUTH_CLIENT_SECRET }}
CONVERTKIT_OAUTH_REDIRECT_URI=${{ secrets.CONVERTKIT_OAUTH_REDIRECT_URI }}
write-mode: append

# Rename .env.dist.testing to .env, so PHPUnit reads it for tests.
Expand Down
121 changes: 121 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Migrating from v1.x SDK (v3 API) to v2.x SDK (v4 API)

Whilst every best effort is made to minimise the number of breaking changes, some breaking changes exist to ensure improved method naming conventions and compatibility with OAuth authentication and the v4 API.

This guide is designed to cover changes that developers may need to make to their existing implementation when upgrading to the v2 SDK.

## PHP Version

The minimum supported PHP version is `8.0`. Users on older PHP versions should continue to use the v1 SDK.

## Authentication

Authentication is now via OAuth. It's recommended to refer to the README file's [`Getting Started`](README.md#2x-v4-api-oauth-php-80) section for implementation.

Initializing the `ConvertKit_API` class now accepts a `clientID`, `clientSecret` and `accessToken` in place of the existing `api_key` and `api_secret`:

```php
$api = new \ConvertKit_API\ConvertKit_API(
clientID: '<your_oauth_client_id>',
clientSecret: '<your_oauth_client_secret>',
accessToken: '<your_oauth_access_token>'
);
```

## Pagination

For list based endpoints which fetch data from the API (such as broadcasts, custom fields, subscribers, tags, email templates, forms, purchases etc.), cursor based pagination is used. The following parameters can be specified in the API methods:

- `per_page`: Defines the number of results to return, with a maximum value of 100
- `after_cursor`: When specified, returns the next page of results based on the current result's `pagination->end_cursor` value
- `before_cursor`: When specified, returns the previous page of results based on the current result's `pagination->start_cursor` value

## Accounts

- Added: `get_account_colors()`
- Added: `update_account_colors()`
- Added: `get_creator_profile()`
- Added: `get_email_stats()`
- Added: `get_growth_stats()`

## Broadcasts

- Updated: `get_broadcasts()` supports pagination
- Updated: `create_broadcast()`:
- `email_layout_template` is now `email_template_id`. To fetch the ID of the account's email templates, refer to `get_email_templates()`
- `preview_text` option added
- `subscriber_filter` option added
- Updated: `update_broadcast()`
- `email_layout_template` is now `email_template_id`. To fetch the ID of the account's email templates, refer to `get_email_templates()`
- `preview_text` option added
- `subscriber_filter` option added
- Changed: `destroy_broadcast()` is renamed to `delete_broadcast()`

## Custom Fields

- Added: `create_custom_fields()` to create multiple custom fields in a single request
- Updated: `get_custom_fields()` supports pagination

## Subscribers

- Added: `create_subscriber()`. The concept of creating a subscriber via a form, tag or sequence is replaced with this new method. The subscriber can then be subscribed to resources (forms, tag, sequences) as necessary.
- Added: `create_subscribers()` to create multiple subscribers in a single request
- Added: `get_subscribers()`
- Changed: `unsubscribe()` is now `unsubscribe_by_email()`. Use `unsubscribe()` for unsubscribing by a subscriber ID
- Updated: `get_subscriber_tags()` supports pagination

## Tags

- Added: `create_tags()` to create multiple tags in a single request
- Updated: `get_tags()` supports pagination
- Updated: `get_tag_subscriptions()`:
- supports pagination
- supports filtering by subscribers by dates, covering `created_after`, `created_before`, `tagged_after` and `tagged_before`
- `sort_order` is no longer supported
- Changed: `tag_subscriber()` is now `tag_subscriber_by_email()`. Use `tag_subscriber()` for tagging by subscriber ID

## Email Templates

- Added: `get_email_templates()`

## Forms

- Updated: `get_forms()`:
- supports pagination
- only returns active forms by default. Use the `status` parameter to filter by `active`, `archived`, `trashed` or `all`
- Updated: `get_landing_pages()`:
- supports pagination
- only returns active landing pages by default. Use the `status` parameter to filter by `active`, `archived`, `trashed` or `all`
- Updated: `get_form_subscriptions()`:
- supports pagination
- supports filtering by subscribers by dates, covering `created_after`, `created_before`, `added_after` and `added_before`
- `sort_order` is no longer supported
- Changed: `add_subscriber_to_form()` is now `add_subscriber_to_form_by_email()`. Use `add_subscriber_to_form()` for adding subscriber to form by subscriber ID

## Purchases

- Updated: `create_purchase()` now supports named parameters for purchase data, instead of an `$options` array
- Changed: `list_purchases()` is now `get_purchases()`, with pagination support

## Segments

- Added: `get_segments()`

## Sequences

- Changed: `add_subscriber_to_sequence()` is now `add_subscriber_to_sequence_by_email()`. Use `add_subscriber_to_sequence()` for adding a subscriber to a sequence by subscriber ID
- Updated: `get_sequences()` supports pagination
- Updated: `get_sequence_subscriptions()`:
- supports pagination
- supports filtering by subscribers by dates, covering `created_after`, `created_before`, `added_after` and `added_before`
- `sort_order` is no longer supported

## Webhooks

- Added: `get_webhooks()`
- Changed: `destroy_webhook()` is now `delete_webhook()`

## Other

- Removed: `form_subscribe()` was previously deprecated. Use `add_subscriber_to_form()` or `add_subscriber_to_form_by_email()`
- Removed: `add_tag()` was previously deprecated. Use `tag_subscriber()` or `tag_subscriber_by_email()`
107 changes: 105 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ The ConvertKit PHP SDK provides convinient access to the ConvertKit API from app

It includes a pre-defined set of methods for interacting with the API.

## Requirements
## Version Guidance

PHP 7.4 and later.
| SDK Version | API Version | API Authentication | PHP Version |
|-------------|-------------|--------------------|--------------|
| 1.x | v3 | API Key and Secret | 7.4+ |
| 2.x | v4 | OAuth | 8.0+ |

Refer to [this guide](MIGRATION.md) for changes when upgrading to the v2 SDK.

## Composer

Expand Down Expand Up @@ -34,6 +39,104 @@ If you use Composer, these dependencies should be handled automatically.

## Getting Started

### 2.x (v4 API, OAuth, PHP 8.0+)

First, register your OAuth application in the `OAuth Applications` section at https://app.convertkit.com/account_settings/advanced_settings.

Using the supplied Client ID and secret, redirect the user to ConvertKit to grant your application access to their ConvertKit account.

```php
// Require the autoloader (if you're using a PHP framework, this may already be done for you).
require_once 'vendor/autoload.php';

// Initialize the API class.
$api = new \ConvertKit_API\ConvertKit_API(
clientID: '<your_oauth_client_id>',
clientSecret: '<your_oauth_client_secret>'
);

// Redirect to begin the OAuth process.
header('Location: '.$api->get_oauth_url('<your_redirect_uri>'));
```

Once the user grants your application access to their ConvertKit account, they'll be redirected to your Redirect URI with an authorization code. For example:

`your-redirect-uri?code=<auth_code>`

At this point, your application needs to exchange the authorization code for an access token and refresh token.

```php
$result = $api->get_access_token(
authCode: '<auth_code>',
redirectURI: '<your_redirect_uri>'
);
```

`$result` is an array comprising of:
- `access_token`: The access token, used to make authenticated requests to the API
- `refresh_token`: The refresh token, used to fetch a new access token once the current access token has expired
- `created_at`: When the access token was created
- `expires_in`: The number of seconds from `created_at` that the access token will expire

Once you have an access token, re-initialize the API class with it:

```php
// Initialize the API class.
$api = new \ConvertKit_API\ConvertKit_API(
clientID: '<your_oauth_client_id>',
clientSecret: '<your_oauth_client_secret>',
accessToken: '<your_access_token>'
);
```

To refresh an access token:

```php
$result = $api->refresh_token(
refreshToken: '<your_refresh_token>',
redirectURI: '<your_redirect_uri>'
);
```

`$result` is an array comprising of:
- `access_token`: The access token, used to make authenticated requests to the API
- `refresh_token`: The refresh token, used to fetch a new access token once the current access token has expired
- `created_at`: When the access token was created
- `expires_in`: The number of seconds from `created_at` that the access token will expire

Once you have refreshed the access token i.e. obtained a new access token, re-initialize the API class with it:

```php
// Initialize the API class.
$api = new \ConvertKit_API\ConvertKit_API(
clientID: '<your_oauth_client_id>',
clientSecret: '<your_oauth_client_secret>',
accessToken: '<your_new_access_token>'
);
```

API requests may then be performed:

```php
$result = $api->add_subscriber_to_form(12345, '[email protected]');
```

To determine whether a new entity / relationship was created, or an existing entity / relationship updated, inspect the HTTP code of the last request:

```php
$result = $api->add_subscriber_to_form(12345, '[email protected]');
$code = $api->getResponseInterface()->getStatusCode(); // 200 OK if e.g. a subscriber already added to the specified form, 201 Created if the subscriber added to the specified form for the first time.
```

The PSR-7 response can be fetched and further inspected, if required - for example, to check if a header exists:

```php
$result = $api->add_subscriber_to_form(12345, '[email protected]');
$api->getResponseInterface()->hasHeader('Content-Length'); // Check if the last API request included a `Content-Length` header
```

### 1.x (v3 API, API Key and Secret, PHP 7.4+)

Get your ConvertKit API Key and API Secret [here](https://app.convertkit.com/account/edit) and set it somewhere in your application.

```php
Expand Down
2 changes: 1 addition & 1 deletion phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
<!-- Permit slightly longer line lengths -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="130"/>
<property name="lineLimit" value="150"/>
<property name="absoluteLineLimit" value="0"/>
</properties>
</rule>
Expand Down
7 changes: 1 addition & 6 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,4 @@ parameters:

# Should not need to edit anything below here
# Rule Level: https://phpstan.org/user-guide/rule-levels
level: 8

# Ignore the following errors, as PHPStan either does not have registered symbols for them yet,
# or the symbols are inaccurate.
ignoreErrors:
- '#\$headers of class GuzzleHttp\\Psr7\\Request constructor expects#'
level: 8
7 changes: 1 addition & 6 deletions phpstan.neon.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,4 @@ parameters:

# Should not need to edit anything below here
# Rule Level: https://phpstan.org/user-guide/rule-levels
level: 8

# Ignore the following errors, as PHPStan either does not have registered symbols for them yet,
# or the symbols are inaccurate.
ignoreErrors:
- '#\$headers of class GuzzleHttp\\Psr7\\Request constructor expects#'
level: 8
Loading
Loading