Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f1e2419
Add Snippet Methods
n7studios May 18, 2026
51f591e
Merge branch 'add-posts-methods' into add-snippets-methods
n7studios May 18, 2026
9d78a79
Remove delete_snippets(), as the API has no delete snippet endpoint
n7studios May 18, 2026
f0d74a3
Added Tests
n7studios May 18, 2026
dbeb217
Updated .env
n7studios May 18, 2026
a597aea
List Subscribers: Add Support for `include` parameter
n7studios May 18, 2026
dd16795
Add Sequence Email Methods
n7studios May 18, 2026
ebe0e95
PHPStan compat.
n7studios May 18, 2026
2714473
Merge branch 'add-snippets-methods' into add-list-subscribers-include…
n7studios May 18, 2026
2f35278
Merge branch 'add-list-subscribers-include-parameter' into add-sequen…
n7studios May 18, 2026
38535df
Added tests
n7studios May 18, 2026
8754ed6
Fix tests
n7studios May 18, 2026
cc87e84
Coding standards
n7studios May 18, 2026
fa75a30
Remove redundant test
n7studios May 18, 2026
8bc72ad
Merge branch 'add-snippets-methods' into add-list-subscribers-include…
n7studios May 18, 2026
236da62
Merge branch 'add-list-subscribers-include-parameter' into add-sequen…
n7studios May 18, 2026
f16feb4
Run Tests Sequentially
n7studios May 18, 2026
f29083f
PHPStan compat.
n7studios May 18, 2026
835a758
Merge branch 'add-list-subscribers-include-parameter' into add-sequen…
n7studios May 18, 2026
7063af2
Coding standards
n7studios May 18, 2026
c9ccbcd
Fix test
n7studios May 19, 2026
4d23e7b
Fix `testCreateGetUpdateAndDeleteSequenceEmail` test
n7studios May 19, 2026
57f599f
Merge branch 'add-sequence-emails-methods' into run-tests-sequential
n7studios May 19, 2026
7eb8361
Merge pull request #137 from Kit/run-tests-sequential
n7studios May 21, 2026
c5e2389
Merge pull request #136 from Kit/add-sequence-emails-methods
n7studios May 21, 2026
78ad8c0
Merge pull request #135 from Kit/add-list-subscribers-include-parameter
n7studios May 21, 2026
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
1 change: 1 addition & 0 deletions .env.dist.testing
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ CONVERTKIT_API_SUBSCRIBER_EMAIL="optin@n7studios.com"
CONVERTKIT_API_SUBSCRIBER_ID="1579118532"
CONVERTKIT_API_EMAIL_TEMPLATE_ID="5215567"
CONVERTKIT_API_POST_ID="3175837"
CONVERTKIT_API_SNIPPET_ID="136038"
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ CONVERTKIT_API_TAG_NAME_2="gravityforms-tag-1"
CONVERTKIT_API_TAG_ID_2="2907192"
CONVERTKIT_API_SUBSCRIBER_EMAIL="optin@n7studios.com"
CONVERTKIT_API_SUBSCRIBER_ID="1579118532"
CONVERTKIT_API_EMAIL_TEMPLATE_ID="5215567"
CONVERTKIT_API_POST_ID="3175837"
CONVERTKIT_API_SNIPPET_ID="136038"
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
# Defines PHP Versions matrix to run tests on
strategy:
fail-fast: false
max-parallel: 1
matrix:
php-versions: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ]

Expand Down
342 changes: 342 additions & 0 deletions src/ConvertKit_API_Traits.php
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,343 @@ public function get_sequence_subscriptions(
);
}

/**
* List sequence emails
*
* @param integer $sequence_id Sequence ID.
* @param boolean $include_total_count To include the total count of records in the response, use true.
* @param string $after_cursor Return results after the given pagination cursor.
* @param string $before_cursor Return results before the given pagination cursor.
* @param integer $per_page Number of results to return.
*
* @see https://developers.kit.com/api-reference/sequence-emails/list-sequence-emails
*
* @return false|mixed
*/
public function get_sequence_emails(
int $sequence_id,
bool $include_total_count = false,
string $after_cursor = '',
string $before_cursor = '',
int $per_page = 100
) {
return $this->get(
sprintf('sequences/%s/emails', $sequence_id),
$this->build_total_count_and_pagination_params(
[],
$include_total_count,
$after_cursor,
$before_cursor,
$per_page
)
);
}

/**
* Create a sequence email
*
* @param integer $sequence_id Sequence ID.
* @param string $subject Subject line of the email.
* @param integer $delay_value Number of days or hours to wait before sending this email after the previous one.
* @param string $delay_unit Unit for the send delay. Use `days` for schedule-aware delivery, `hours` for a fixed hourly delay.
* @param string|null $preview_text Preview text shown in email clients before the email is opened.
* @param string|null $content HTML body content of the email.
* @param integer|null $email_template_id ID of the email template to use for layout and styling.
* @param boolean $published Whether the email is active and will be sent to subscribers.
* @param array<string>|null $send_days Days of the week this email may be sent. Defaults to all 7 days (inherits the sequence schedule). Pass a subset to restrict delivery, or null to reset to all days.
* @param integer|null $position Zero-based position of the email in the sequence. Assigned automatically after the last email if omitted.
*
* @see https://developers.kit.com/api-reference/sequence-emails/create-a-sequence-email
*
* @return mixed|object
*/
public function create_sequence_email(
int $sequence_id,
string $subject,
int $delay_value,
string $delay_unit,
string|null $preview_text = null,
string|null $content = null,
int|null $email_template_id = null,
bool $published = false,
array|null $send_days = null,
int|null $position = null,
) {
$options = [
'subject' => $subject,
'delay_value' => $delay_value,
'delay_unit' => $delay_unit,
'published' => $published,
'send_days' => $send_days,
];

if (!empty($preview_text)) {
$options['preview_text'] = $preview_text;
}
if (!empty($content)) {
$options['content'] = $content;
}
if (!empty($email_template_id)) {
$options['email_template_id'] = $email_template_id;
}
if (!empty($position)) {
$options['position'] = $position;
}

// Send request.
return $this->post(
sprintf('sequences/%s/emails', $sequence_id),
$options
);
}

/**
* Get a sequence email.
*
* @param integer $sequence_id Sequence ID.
* @param integer $email_id Email ID.
*
* @see https://developers.kit.com/api-reference/sequence-emails/get-a-sequence-email
*
* @return mixed|object
*/
public function get_sequence_email(int $sequence_id, int $email_id)
{
return $this->get(sprintf('sequences/%s/emails/%s', $sequence_id, $email_id));
}

/**
* Updates a sequence
*
* @param integer $sequence_id Sequence ID.
* @param integer $email_id Sequence Email ID.
* @param string|null $subject Subject line of the email.
* @param integer|null $delay_value Number of days or hours to wait before sending this email after the previous one.
* @param string|null $delay_unit Unit for the send delay. Use `days` for schedule-aware delivery, `hours` for a fixed hourly delay.
* @param string|null $preview_text Preview text shown in email clients before the email is opened.
* @param string|null $content HTML body content of the email.
* @param integer|null $email_template_id ID of the email template to use for layout and styling.
* @param boolean|null $published Whether the email is active and will be sent to subscribers.
* @param array<string>|null $send_days Days of the week this email may be sent. Defaults to all 7 days (inherits the sequence schedule). Pass a subset to restrict delivery, or null to reset to all days.
* @param integer|null $position Zero-based position of the email in the sequence. Assigned automatically after the last email if omitted.
*
* @see https://developers.kit.com/api-reference/sequences/create-a-sequence
*
* @return mixed|object
*/
public function update_sequence_email(
int $sequence_id,
int $email_id,
string|null $subject = null,
int|null $delay_value = null,
string|null $delay_unit = null,
string|null $preview_text = null,
string|null $content = null,
int|null $email_template_id = null,
bool|null $published = null,
array|null $send_days = null,
int|null $position = null,
) {
// Build parameters.
$options = ['send_days' => $send_days];

if (!is_null($subject)) {
$options['subject'] = $subject;
}
if (!is_null($delay_value)) {
$options['delay_value'] = $delay_value;
}
if (!is_null($delay_unit)) {
$options['delay_unit'] = $delay_unit;
}
if (!is_null($preview_text)) {
$options['preview_text'] = $preview_text;
}
if (!is_null($content)) {
$options['content'] = $content;
}
if (!is_null($email_template_id)) {
$options['email_template_id'] = $email_template_id;
}
if (!is_null($published)) {
$options['published'] = $published;
}
if (!is_null($send_days)) {
$options['send_days'] = $send_days;
}
if (!is_null($position)) {
$options['position'] = $position;
}

// Send request.
return $this->put(
sprintf('sequences/%s/emails/%s', $sequence_id, $email_id),
$options
);
}

/**
* Deletes a sequence email.
*
* @param integer $sequence_id Sequence ID.
* @param integer $email_id Email ID.
*
* @see https://developers.kit.com/api-reference/sequence-emails/delete-a-sequence-email
*
* @return mixed|object
*/
public function delete_sequence_email(int $sequence_id, int $email_id)
{
return $this->delete(sprintf('sequences/%s/emails/%s', $sequence_id, $email_id));
}

/**
* List snippets
*
* @param boolean $archived When `true`, returns only archived snippets. Defaults to `false`.
* @param boolean $include_content When `true`, includes both the content and document fields for each snippet in the response. Defaults to `false`.
* @param string|null $snippet_type Filter snippets by type. Use inline for text snippets or block for rich-text block snippets.
* @param boolean $include_total_count To include the total count of records in the response, use true.
* @param string $after_cursor Return results after the given pagination cursor.
* @param string $before_cursor Return results before the given pagination cursor.
* @param integer $per_page Number of results to return.
*
* @see https://developers.kit.com/api-reference/snippets/list-snippets
*
* @return false|mixed
*/
public function get_snippets(
bool $archived = false,
bool $include_content = false,
string|null $snippet_type = null,
bool $include_total_count = false,
string $after_cursor = '',
string $before_cursor = '',
int $per_page = 100
) {
$options = [
'archived' => $archived,
'include_content' => $include_content,
];
if (!is_null($snippet_type)) {
$options['snippet_type'] = $snippet_type;
}
return $this->get(
'snippets',
$this->build_total_count_and_pagination_params(
$options,
$include_total_count,
$after_cursor,
$before_cursor,
$per_page
)
);
}

/**
* Create a snippet
*
* @param string $name Name of the snippet.
* @param string $snippet_type Type of snippet. Must be one of: `inline`, `block`.
* @param string $content Content of the snippet.
*
* @see https://developers.kit.com/api-reference/snippets/create-a-snippet
*
* @return mixed|object
*/
public function create_snippet(
string $name,
string $snippet_type,
string $content
) {
$options = [
'name' => $name,
'snippet_type' => $snippet_type,
];

switch ($snippet_type) {
case 'inline':
$options['content'] = $content;
break;

case 'block':
default:
$options['document_attributes'] = ['value_html' => $content];
break;
}

// Send request.
return $this->post(
'snippets',
$options
);
}

/**
* Get a snippet.
*
* @param integer $id Snippet ID.
*
* @see https://developers.kit.com/api-reference/snippets/get-a-snippet
*
* @return mixed|object
*/
public function get_snippet(int $id)
{
return $this->get(sprintf('snippets/%s', $id));
}

/**
* Updates a snippet
*
* @param integer $snippet_id Snippet ID.
* @param string $name Name of the snippet.
* @param string $snippet_type Type of snippet. Must be one of: `inline`, `block`.
* @param boolean $archived Pass `true` to archive or `false` to restore the snippet.
* @param string $content Content of the snippet.
*
* @see https://developers.kit.com/api-reference/snippets/update-a-snippet
*
* @return mixed|object
*/
public function update_snippet(
int $snippet_id,
string $name = '',
string $snippet_type = '',
bool $archived = false,
string $content = ''
) {
$options = [
'name' => $name,
'snippet_type' => $snippet_type,
'archived' => $archived,
];

switch ($snippet_type) {
case 'inline':
$options['content'] = $content;
break;

case 'block':
default:
$options['document_attributes'] = ['value_html' => $content];
break;
}

// Iterate through options, removing blank entries.
foreach ($options as $key => $value) {
if (is_string($value) && strlen($value) === 0) {
unset($options[$key]);
}
}

// Send request.
return $this->put(
sprintf('snippets/%s', $snippet_id),
$options
);
}

/**
* List tags.
*
Expand Down Expand Up @@ -1023,6 +1360,7 @@ public function get_post(int $id)
* @param \DateTime|null $updated_before Filter subscribers who have been updated before this date.
* @param string $sort_field Sort Field (id|updated_at|cancelled_at).
* @param string $sort_order Sort Order (asc|desc).
* @param array<string> $include Additional fields to include: attribution, tags, location, canceled_at.
* @param boolean $include_total_count To include the total count of records in the response, use true.
* @param string $after_cursor Return results after the given pagination cursor.
* @param string $before_cursor Return results before the given pagination cursor.
Expand All @@ -1043,6 +1381,7 @@ public function get_subscribers(
\DateTime|null $updated_before = null,
string $sort_field = 'id',
string $sort_order = 'desc',
array $include = [],
bool $include_total_count = false,
string $after_cursor = '',
string $before_cursor = '',
Expand Down Expand Up @@ -1075,6 +1414,9 @@ public function get_subscribers(
if (!empty($sort_order)) {
$options['sort_order'] = $sort_order;
}
if (!empty($include)) {
$options['include'] = implode(',', $include);
}

// Send request.
return $this->get(
Expand Down
Loading
Loading