ConvertKit - v1.0.0
Feed Dry-Run
Runs a feed's conditional logic + field mapper against a sample submission payload and reports what would happen — without touching Kit.
Use this to sanity-check a feed's config while iterating.
POST /admin/convertkit/feeds/{id}/test
Auth: manage-convertkit-feeds Gate (same as CRUD). Not rate-limited.
Route name: convertkit.feeds.test.
Request body:
{
"values": {
"email": "jane@example.com",
"name": "Jane",
"plan": "pro"
}
}
Keys in values are your submission's field slugs — the same shape the field mapper expects. values is required and must be an array.
Response: always 200 OK (unless auth fails or the feed doesn't exist). Body shape:
{
"would_send": true|false,
"reason": "conditional_logic" | "field_map" | null,
"payload": { ... } | null
}
Response shapes
Feed would fire
{
"would_send": true,
"reason": null,
"payload": {
"email_address": "jane@example.com",
"first_name": "Jane",
"fields": {
"plan_type": "pro"
}
}
}
payload is the exact object that would be sent to Kit if you dispatched a real subscribe.
Conditional logic blocks the feed
{
"would_send": false,
"reason": "conditional_logic",
"payload": null
}
The feed's conditional_logic evaluated to false. Adjust your rules or the submission values.
Field map cannot produce a payload
{
"would_send": false,
"reason": "field_map",
"payload": null
}
The field mapper threw — usually because the submission has no value for the slug mapped to email_address, or the map itself is missing email_address. The underlying exception message is logged server-side via Log::warning with the feed id and the raw error; the response body deliberately does not surface it so this endpoint can't be turned into an information oracle.
Errors
422 Unprocessable Entity—valueswas missing or not an array.403 Forbidden— Gate denied.404 Not Found— feed id doesn't exist.
Example — curl
curl -X POST https://your-app.test/admin/convertkit/feeds/1/test \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-CSRF-TOKEN: <token>' \
-d '{"values": {"email": "jane@example.com", "plan": "pro"}}'
Example — from a Livewire admin UI
public function testFeed(): void
{
$response = Http::withCookies( request()->cookies->all(), request()->getHost() )
->post( route( 'convertkit.feeds.test', $this->feedId ), [
'values' => $this->sampleValues,
] );
$this->result = $response->json();
}
Or invoke the mapper + evaluator directly if you're already server-side:
use ArtisanPackUI\ConvertKit\Models\KitFeed;
use ArtisanPackUI\ConvertKit\Support\ConditionalLogicEvaluator;
use ArtisanPackUI\ConvertKit\Support\FieldMapper;
$feed = KitFeed::find( $feedId );
$evaluator = app( ConditionalLogicEvaluator::class );
$mapper = app( FieldMapper::class );
if ( ! $evaluator->evaluate( $feed->conditional_logic, $values ) ) {
// conditional_logic reason
}
$payload = $mapper->mapValues( $values, $feed->field_map );
Skips the HTTP round-trip when you don't need the JSON envelope.