Leaky Paywall REST API

Leaky Paywall REST API

Base URL: https://your-site.com/wp-json/leaky-paywall/v1

Prerequisites: The REST API must be enabled at Leaky Paywall → Settings → Enable REST API. All admin endpoints require HTTP Basic Auth or Application Password authentication as a WordPress admin user.


Authentication

Admin endpoints ( /subscribers, /groups) require credentials with the manage_options capability (or whatever capability is set via the manage_leaky_paywall_settings filter).

Use WordPress Application Passwords (recommended for external integrations):

Authorization: Basic base64(username:application-password)

The /me endpoint requires the user to be logged in (session cookie or Application Password for their own account).


Subscribers

List Subscribers

GET /leaky-paywall/v1/subscribers

Query Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 10 Results per page (max 100)
status string Filter by payment status (e.g.  activecanceled)
level_id string Filter by subscription level ID
search string Search by email or username

Response Headers

  • X-WP-Total — total number of matching subscribers
  • X-WP-TotalPages — total pages

Example
GET /wp-json/leaky-paywall/v1/subscribers?status=active&per_page=25 Authorization: Basic ...

Get a Subscriber

GET /leaky-paywall/v1/subscribers/{id}

Returns a single subscriber by WordPress user ID, plus their notes and status_log.

Example

GET /wp-json/leaky-paywall/v1/subscribers/42 Authorization: Basic ...

Errors

Status Code Meaning
404 rest_subscriber_not_found No user with that ID

Create a Subscriber

POST /leaky-paywall/v1/subscribers

Creates a new WordPress user and activates a subscription for them. If the email already has a subscription on any level, the request is rejected with 409.

Body Parameters

Parameter Required Default Description
email Yes Valid email address
level_id Yes Subscription level ID (from LP Settings → Subscription Levels)
first_name No "" First name
last_name No "" Last name
payment_status No active available payment statuses
payment_gateway No manual e.g.  stripepaypalmanual
subscriber_id No "" Gateway-side customer/subscription ID
plan No "" Plan identifier (e.g.  monthlyannual)

Example

POST /wp-json/leaky-paywall/v1/subscribers Authorization: Basic ... Content-Type: application/json { "email": "[email protected]", "level_id": "1", "first_name": "John", "last_name": "Doe", "payment_gateway": "stripe", "subscriber_id": "sub_xyz789" }

Response: 201 Created with the subscriber object (same shape as Get Subscriber, including notes and status_log).

Errors

Status Code Meaning
409 rest_subscriber_exists Email already has a subscription
400 rest_invalid_level level_id does not match any subscription level
500 rest_subscriber_create_failed Unexpected failure creating the user

Update a Subscriber

PUT /leaky-paywall/v1/subscribers/{id}

Updates one or more fields on an existing subscriber. Only send the fields you want to change — omitted fields are left untouched.

Body Parameters

Parameter Description
level_id Move subscriber to a different level
payment_status See Payment Statuses
expires Expiry date/time string (e.g.  2027-01-01 00:00:00)
subscriber_id Gateway-side ID
payment_gateway e.g.  stripepaypalmanual
plan Plan identifier

Example

— cancel a subscriber:

PUT /wp-json/leaky-paywall/v1/subscribers/42 Authorization: Basic ... Content-Type: application/json { "payment_status": "canceled" }

Response: 200 OK with the updated subscriber object (including notes and status_log).

Errors

Status Code Meaning
404 rest_subscriber_not_found No user with that ID

Get Current User's Subscription

GET /leaky-paywall/v1/me

Returns the subscription data for the currently authenticated user. Useful for logged-in users checking their own access from an external app.

Authentication: Requires a logged-in user (not necessarily an admin).

Response: 200 OK with the subscriber object (without notes/status_log).


Group Accounts

Requires the Leaky Paywall Group Accounts add-on (v1.7.0+).

Get a Group by Owner Email
GET /leaky-paywall/v1/groups?owner_email={email}

Looks up the group account owned by a given user.

Query Parameters

Parameter Required Description
owner_email Yes Email address of the group owner

Example
GET /wp-json/leaky-paywall/v1/[email protected] Authorization: Basic ...

Errors

Status Code Meaning
404 user_not_found No WordPress user with that email
404 group_not_found User exists but has no group account

Update Group Seats

PUT /leaky-paywall/v1/groups/{id}/seats

Adds to or sets the total seat count for a group account. Use the group's numeric post ID (returned by Get Group as id).

Body Parameters

Parameter Required Default Description
seats Yes Number of seats (must be > 0)
mode No add add — increase current seats by this amount; set — replace the total

Example

— add 5 seats to group 101:

PUT /wp-json/leaky-paywall/v1/groups/101/seats Authorization: Basic ... Content-Type: application/json { "seats": 5 }

Example — set group 101 to exactly 30 seats:

PUT /wp-json/leaky-paywall/v1/groups/101/seats Authorization: Basic ... Content-Type: application/json { "seats": 30, "mode": "set" }

Response: 200 OK with the updated group object

Errors

Status Code Meaning
404 group_not_found No  lp_group_account post with that ID

Common Patterns

Create a subscriber and add them to a group

There's no single endpoint that does both. The typical flow from an external site:

  1. POST /subscribers — create the subscriber with the group-level level_id
  2. GET /groups?owner_email=... — retrieve the group ID
  3. PUT /groups/{id}/seats — add a seat if needed (group account membership itself is managed within WordPress/LP once the user logs in and claims their seat)

Check available payment statuses

Valid values for payment_status:

activepending_canceltrialtrialingpast_dueunpaidincompleteincomplete_expiredpausedcanceledexpiredpending_activationrenewal_dueon_holdgrace_perioddeactivated


Error Response Format

All errors follow the standard WordPress REST API format:

{ "code": "rest_subscriber_not_found", "message": "Subscriber not found.", "data": { "status": 404 } }

Still need help? Contact Us Contact Us