The Subscriptions & Memberships add-on registers its endpoints under https://your-store.. Authentication and conventions are the same as for the rental endpoints: a WooCommerce REST API key with Read/Write permissions, JSON bodies, X-WP-Total pagination headers and 409 for conflicts. See the REST API overview. For what subscriptions, memberships and queues are from the store owner’s side, see Setting up Subscriptions and Setting up Memberships.
Subscriptions #
| Method and path | What it does |
|---|---|
GET /subscriptions | List subscriptions. Filters: user_id, status, search, page, per_page. |
POST /subscriptions | Create one. Required: user_id, items (array of { product_id, quantity, recurring_amount }), billing_period (day, week, month, year). Optional: billing_interval (default 1), next_payment_date, parent_order_id, status (default active). |
GET /subscriptions/{id} | One subscription with its items, its pending scheduled renewals and the ids of memberships it pays for. |
PUT /subscriptions/{id} | Change billing_period, billing_interval, next_payment_date, parent_order_id, user_id, status or replace the items. |
DELETE /subscriptions/{id} | Remove the subscription, its items and its scheduled actions. Orders already created are kept. |
POST /subscriptions/ | Cancel it. The parent order’s rental reservations are released and a note is added to the order. |
POST /subscriptions/ | Pause billing (status paused). |
POST /subscriptions/ | Resume a paused subscription (only a paused one; anything else is a 409). |
{
"id": 57,
"user_id": 2,
"status": "active",
"parent_order_id": 4402,
"last_synced_order_id": 4519,
"billing_period": "month",
"billing_interval": 1,
"next_payment_date": "2026-10-14 00:00:00",
"last_payment_date": "2026-09-14 09:12:31",
"date_created": "2026-06-14 09:12:31",
"date_modified": "2026-09-14 09:12:31",
"items": [
{ "id": 91, "subscription_id": 57, "product_id": 2101, "variation_id": 0, "quantity": 1, "recurring_amount": 89, "line_subtotal": 89, "billing_period": "month", "billing_interval": 1, "tax_class": "", "is_one_time": 0, "priced": 1 }
],
"scheduled_actions": [
{ "action_id": 3310, "subscription_id": 57, "action_type": "renewal_order", "action_date": "2026-10-14 00:00:00", "status": "pending", "renewal_order_id": null, "completed_date": null, "notes": null, "created_date": "2026-09-14 09:12:31" }
],
"memberships": [ 12 ]
}
Renewals are charged by the plugin’s daily cron using the payment method saved on the parent order, so a subscription created through the API with no parent_order_id has nothing to charge: it is useful for migrating records or for subscriptions billed outside WooCommerce, and its next_payment_date should then be managed by the caller. Setting status to cancelled or expired through PUT has the same side effects as the /cancel action.
Switching plans #
These two routes are for the store admin: they move one line of a subscription to another plan, the same change a customer makes from My Account. They are in Subscriptions & Memberships 1.1.0 and later. A plan is another variation of the line’s product, or a product listed in the product’s “Customers can switch to” field. Only subscription products that sell the subscription’s billing length are offered, never a rental. The subscription must be active and have a next_payment_date.
An upgrade applies at once and charges the prorated difference. A downgrade applies at the next renewal. With when you can force either one as an admin. Only one change waits at a time: a new switch replaces a scheduled one, and a change waiting for its payment blocks the next one for 7 days.
GET /subscriptions/{id}/switch-options #
Lists the plans the subscription can move to, each with its price preview, and the subscription’s switch log (newest first).
| Parameter | Notes |
|---|---|
item_id | Integer, default 0. The subscription line to switch (the id of an entry in items). Leave it out when the subscription has one line; with several lines and no item_id the first line is used. |
The response has two keys. options is a list of previews, one per plan (empty when the product lists no other plan). log is the list of earlier switches: id, item_id, from_product_id, to_product_id, from_amount, to_amount, direction, apply_at, amount, credit_topup, order_id, status (scheduled, pending_payment, applying, done, failed or cancelled), actor, notify, note, created_at and applied_at. A preview has these fields:
| Field | Notes |
|---|---|
subscription_id, item_id | The subscription and the line. |
from_product_id, from_variation_id, from_name, from_amount | The current plan and what it costs per cycle. |
to_product_id, to_variation_id, target_id, name, to_amount, price_html | The new plan. target_id is the variation id, or the product id when the plan is not a variation. Send it as target_id to the switch route. |
direction | up, down or same, from the two amounts. |
apply_at | now or next_renewal. |
due | The amount charged now, in the store currency. 0 for a change at the next renewal. |
days_left, days_in_cycle | What the proration is based on. |
credit_topup | Store credit added now when both plans are store credit memberships. |
benefits, summary, notes, tax_class | Text for display (it can contain HTML entities such as $) and the new plan’s tax class. |
POST /subscriptions/{id}/switch #
Switches one line to another plan, or previews the switch with dry_run.
| Parameter | Notes |
|---|---|
target_id | Integer, required. The target_id of one of the options. |
item_id | Integer, default 0. The line to switch, as for switch-options. |
when | auto (default), now or next_renewal. auto applies an upgrade now and a downgrade at the next renewal. A plan with the same price counts as an upgrade, so it applies now. |
charge | prorated (default), none or custom. Used only when the change applies now. prorated charges the difference for the days left in the cycle, none charges nothing, custom charges amount. |
amount | Number. The amount to charge with charge set to custom, in the store currency. |
notify | Boolean, default true. Send the customer the plan change email. |
dry_run | Boolean, default false. Return the preview (the same fields as a switch-options entry) and change nothing. |
A real switch returns status, switch_id and message:
| status | Meaning |
|---|---|
done | The plan changed. With a charge, the response also has order_id: the switch order was paid with the payment method saved on the parent order. |
scheduled | The change waits for the next renewal. |
pending_payment | There is an amount to pay and it could not be charged by itself (no saved payment method, or a gateway that does not charge on its own). The response has order_id and pay_url. The plan changes when the order is paid; an unpaid change lapses after 7 days. |
| Error | When |
|---|---|
400 rest_ | target_id is missing. |
404 sibooking_ | No subscription with that id. |
409 sibooking_ | The subscription is not active. |
409 sibooking_ | The subscription has no next_payment_date, so the change cannot be priced. |
409 sibooking_ | An earlier change is still waiting for its payment. |
409 sibooking_ | item_id is not a line of this subscription, or the subscription has no items. |
409 sibooking_ | target_id is not one of the plans this line can switch to. |
409 sibooking_ | The subscription is being renewed or changed right now. Try again in a minute. |
409 sibooking_ | The saved payment method was declined. The plan is unchanged and the switch order is marked failed. |
Preview a switch first, then send it without dry_run:
curl -u "ck_your_key:cs_your_secret" \
"https://example.com/wp-json/wc-sisubscriptions/v1/subscriptions/57/switch-options"
curl -X POST -u "ck_your_key:cs_your_secret" \
-H "Content-Type: application/json" \
-d '{"target_id": 2102, "when": "auto", "dry_run": true}' \
"https://example.com/wp-json/wc-sisubscriptions/v1/subscriptions/57/switch"
curl -X POST -u "ck_your_key:cs_your_secret" \
-H "Content-Type: application/json" \
-d '{"target_id": 2102, "charge": "none", "notify": false}' \
"https://example.com/wp-json/wc-sisubscriptions/v1/subscriptions/57/switch"
Memberships #
| Method and path | What it does |
|---|---|
GET /memberships | List memberships. Filters: user_id, status, page, per_page. |
POST /memberships | Create one. Required: user_id. Then either queue_items (how many rentals the member may have out at once: a rental queue membership) or storecredit_amount (a store credit membership). Optional: subscription_id that pays for it, status (active, paused, cancelled, expired). |
GET /memberships/{id} | One membership with the credit used so far, the number of rentals out and the linked subscription’s status and dates. |
PUT /memberships/{id} | Change any of the fields above. |
DELETE /memberships/{id} | Delete the membership. |
{
"id": 12,
"user_id": 2,
"subscription_id": 57,
"type": "queue",
"status": "active",
"storecredit_amount": null,
"credit_used": 0,
"queue_items": 3,
"rentals_out": 1,
"date_created": "2026-06-14 09:12:31",
"date_modified": "2026-09-14 09:12:31",
"subscription_status": "active",
"next_payment_date": "2026-10-14 00:00:00",
"last_payment_date": "2026-09-14 09:12:31",
"parent_order_id": 4402
}
Rental queue #
A rental queue is the list of products a queue member wants next, in priority order. Sending the item at the top checks it out against one of the member’s free slots; returning it frees the slot. These endpoints do exactly what the member’s “Manage Queue” page and the admin Rental queue screens (Send and Return tabs) do.
| Method and path | What it does |
|---|---|
GET /queue?user_id=2 | The member’s queue, top priority first. |
POST /queue | Add a product: user_id, product_id. For a variable product also send variation_id and, for its “Any …” attributes, attributes (an object of attribute values). A product already queued is a 409. |
PUT /queue/{id} | Move an item: priority (1 = next). Send variation_id (and attributes) instead, or as well, to change a variable product’s option; one already queued is a 409. Send neither and it is a 400. |
DELETE /queue/{id} | Remove an item from the queue. |
POST /queue/{id}/send | Check the queued item out to the member (with serials on a serial-tracked product). Refused with 409 when the member has no free slot or no unit is available. |
POST /queue-sent/ | Take a sent item back; {id} is the id from /queue/out. |
GET /queue/out?user_id=2 | What the member currently has out, with the sent date and serials. |
A queue checkout creates a rental reservation without a WooCommerce order, so it appears in the bookings endpoints with order_id 0 and counts against the product’s availability like any other booking.
