# List Source: https://developer.surecart.com/api-reference/abandonded-checkouts/list /openapi/v1/orders.json get /v1/abandoned_checkouts Returns a list of your abandonded checkouts. # Retrieve Source: https://developer.surecart.com/api-reference/abandonded-checkouts/retrieve /openapi/v1/orders.json get /v1/abandoned_checkouts/{id} Retrieves details of a specific abandonded checkout. # Update Source: https://developer.surecart.com/api-reference/abandonded-checkouts/update /openapi/v1/orders.json patch /v1/abandoned_checkouts/{id} Updates a specific abandoned checkout. # Retrieve Source: https://developer.surecart.com/api-reference/abandoned-checkout-protocols/retrieve /openapi/v1/orders.json get /v1/abandoned_checkout_protocol Retrieves details of the current account's abandoned checkout protocol. # Update Source: https://developer.surecart.com/api-reference/abandoned-checkout-protocols/update /openapi/v1/orders.json patch /v1/abandoned_checkout_protocol Updates the current account's abandoned checkout protocol. # Retrieve Source: https://developer.surecart.com/api-reference/accounts/retrieve /openapi/v1/core.json get /v1/account Retrieves details of the current account. # Update Source: https://developer.surecart.com/api-reference/accounts/update /openapi/v1/core.json patch /v1/account Updates the current account. # Create Source: https://developer.surecart.com/api-reference/activations/create /openapi/v1/public.json post /v1/public/activations Creates a new activation. If an activation already exists with the same `fingerprint` then it will be updated and returned. # Delete Source: https://developer.surecart.com/api-reference/activations/delete /openapi/v1/public.json delete /v1/public/activations/{id} Deletes a specific activation. # List Source: https://developer.surecart.com/api-reference/activations/list /openapi/v1/licensing.json get /v1/activations Returns a list of your activations. # Retrieve Source: https://developer.surecart.com/api-reference/activations/retrieve /openapi/v1/public.json get /v1/public/activations/{id} Retrieves details of a specific activation. # Update Source: https://developer.surecart.com/api-reference/activations/update /openapi/v1/public.json patch /v1/public/activations/{id} Updates a specific activation. # Create Source: https://developer.surecart.com/api-reference/affiliation-products/create /openapi/v1/affiliates.json post /v1/affiliation_products Creates a new affiliation product. # Delete Source: https://developer.surecart.com/api-reference/affiliation-products/delete /openapi/v1/affiliates.json delete /v1/affiliation_products/{id} Deletes a specific affiliation product. # List Source: https://developer.surecart.com/api-reference/affiliation-products/list /openapi/v1/affiliates.json get /v1/affiliation_products Returns a list of your affiliation products. # Retrieve Source: https://developer.surecart.com/api-reference/affiliation-products/retrieve /openapi/v1/affiliates.json get /v1/affiliation_products/{id} Retrieves details of a specific a specific affiliation product. # Update Source: https://developer.surecart.com/api-reference/affiliation-products/update /openapi/v1/affiliates.json patch /v1/affiliation_products/{id} updates specific affiliation product. # Retrieve Source: https://developer.surecart.com/api-reference/affiliation-protocols/retrieve /openapi/v1/affiliates.json get /v1/affiliation_protocol Retrieves details of the current account's affiliation protocol. # Update Source: https://developer.surecart.com/api-reference/affiliation-protocols/update /openapi/v1/affiliates.json patch /v1/affiliation_protocol Updates the current account's affiliation protocol. # Activate Source: https://developer.surecart.com/api-reference/affiliation-requests/activate /openapi/v1/affiliates.json patch /v1/affiliation_requests/{id}/approve Approve a specific affiliation request. # Create Source: https://developer.surecart.com/api-reference/affiliation-requests/create /openapi/v1/affiliates.json post /v1/affiliation_requests Creates a new affiliation request. # Deactivate Source: https://developer.surecart.com/api-reference/affiliation-requests/deactivate /openapi/v1/affiliates.json patch /v1/affiliation_requests/{id}/deny Deny a specific affiliation request. # Delete Source: https://developer.surecart.com/api-reference/affiliation-requests/delete /openapi/v1/affiliates.json delete /v1/affiliation_requests/{id} Deletes a specific affiliation request. # List Source: https://developer.surecart.com/api-reference/affiliation-requests/list /openapi/v1/affiliates.json get /v1/affiliation_requests Returns a list of your affiliation requests. # Retrieve Source: https://developer.surecart.com/api-reference/affiliation-requests/retrieve /openapi/v1/affiliates.json get /v1/affiliation_requests/{id} Retrieves details of a specific affiliation request. # Update Source: https://developer.surecart.com/api-reference/affiliation-requests/update /openapi/v1/affiliates.json patch /v1/affiliation_requests/{id} Updates a specific affiliation request. # Activate Source: https://developer.surecart.com/api-reference/affiliations/activate /openapi/v1/affiliates.json patch /v1/affiliations/{id}/activate Activates a specific affiliation. # Create Source: https://developer.surecart.com/api-reference/affiliations/create /openapi/v1/affiliates.json post /v1/affiliations Creates a new affiliation. # Deactivate Source: https://developer.surecart.com/api-reference/affiliations/deactivate /openapi/v1/affiliates.json patch /v1/affiliations/{id}/deactivate Deactivates a specific affiliation. # Delete Source: https://developer.surecart.com/api-reference/affiliations/delete /openapi/v1/affiliates.json delete /v1/affiliations/{id} Deletes a specific affiliation. # List Source: https://developer.surecart.com/api-reference/affiliations/list /openapi/v1/affiliates.json get /v1/affiliations Returns a list of your affiliations. # Retrieve Source: https://developer.surecart.com/api-reference/affiliations/retrieve /openapi/v1/affiliates.json get /v1/affiliations/{id} Retrieves details of a specific affiliation. # Update Source: https://developer.surecart.com/api-reference/affiliations/update /openapi/v1/affiliates.json patch /v1/affiliations/{id} updates specific affiliation. # List Countries Source: https://developer.surecart.com/api-reference/atlas/list-countries /openapi/v1/public.json get /v1/public/atlas Returns a list of all countries. # Retrieve Country Source: https://developer.surecart.com/api-reference/atlas/retrieve-country /openapi/v1/public.json get /v1/public/atlas/{country_code} Returns detailed address information for a given country. # Authentication Source: https://developer.surecart.com/api-reference/authentication The SureCart API uses API keys to authenticate requests. You can view and manage your API keys in the SureCart platform dashboard. There are two types of API keys – public and secret. Your secret API key can be used to make requests to most API endpoints listed in this documentation. Your public API key can be used to make requests to any endpoints within the `Public Endpoints` group. Your public API key is designed to be used in client side code and can be exposed. Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth. All API requests must be made over HTTPS. Calls made over plain HTTP will fail. API requests without authentication will also fail. # Retrieve Source: https://developer.surecart.com/api-reference/auto-fee-protocols/retrieve /openapi/v1/products.json get /v1/auto_fee_protocol Retrieves details of the current account's auto fee protocol. # Update Source: https://developer.surecart.com/api-reference/auto-fee-protocols/update /openapi/v1/products.json patch /v1/auto_fee_protocol Updates the current account's auto fee protocol. # Create Source: https://developer.surecart.com/api-reference/auto-fees/create /openapi/v1/products.json post /v1/auto_fees Creates a new auto fee. # Delete Source: https://developer.surecart.com/api-reference/auto-fees/delete /openapi/v1/products.json delete /v1/auto_fees/{id} Deletes a specific auto fee. # List Source: https://developer.surecart.com/api-reference/auto-fees/list /openapi/v1/products.json get /v1/auto_fees Returns a list of your auto fees. # Retrieve Source: https://developer.surecart.com/api-reference/auto-fees/retrieve /openapi/v1/products.json get /v1/auto_fees/{id} Retrieves details of a specific auto fee. # Rule Schema Source: https://developer.surecart.com/api-reference/auto-fees/rule-schema /openapi/v1/products.json get /v1/auto_fees/rule_schema/{fee_target} Retrieves the rule schema for a specific fee target. # Update Source: https://developer.surecart.com/api-reference/auto-fees/update /openapi/v1/products.json patch /v1/auto_fees/{id} Updates a specific auto fee. # Create Source: https://developer.surecart.com/api-reference/balance-transactions/create /openapi/v1/customers.json post /v1/balance_transactions Creates a new balance transaction. # List Source: https://developer.surecart.com/api-reference/balance-transactions/list /openapi/v1/customers.json get /v1/balance_transactions Returns a list of your balance transactions. # Retrieve Source: https://developer.surecart.com/api-reference/balance-transactions/retrieve /openapi/v1/customers.json get /v1/balance_transactions/{id} Retrieves details of a specific balance transaction. # List Source: https://developer.surecart.com/api-reference/balances/list /openapi/v1/customers.json get /v1/balances Returns a list of your balances. # List Source: https://developer.surecart.com/api-reference/batch-operations/list /openapi/v1/core.json get /v1/batch_operations Returns a list of your batch operations. # Retrieve Source: https://developer.surecart.com/api-reference/batch-operations/retrieve /openapi/v1/core.json get /v1/batch_operations/{id} Retrieves details of a specific batch operation. # Create Source: https://developer.surecart.com/api-reference/batches/create /openapi/v1/core.json post /v1/batches Creates a new batch. # List Source: https://developer.surecart.com/api-reference/batches/list /openapi/v1/core.json get /v1/batches Returns a list of your batches. # Retrieve Source: https://developer.surecart.com/api-reference/batches/retrieve /openapi/v1/core.json get /v1/batches/{id} Retrieves details of a specific batch. # Retrieve Source: https://developer.surecart.com/api-reference/brands/retrieve /openapi/v1/core.json get /v1/brand Retrieves details of the current account's brand. # Update Source: https://developer.surecart.com/api-reference/brands/update /openapi/v1/core.json patch /v1/brand Updates the current account's brand. # Create Source: https://developer.surecart.com/api-reference/bulk-actions/create /openapi/v1/core.json post /v1/bulk_actions Creates a new bulk action. # List Source: https://developer.surecart.com/api-reference/bulk-actions/list /openapi/v1/core.json get /v1/bulk_actions Returns a list of your bulk actions. # Retrieve Source: https://developer.surecart.com/api-reference/bulk-actions/retrieve /openapi/v1/core.json get /v1/bulk_actions/{id} Retrieves details of a specific bulk action. # Create Source: https://developer.surecart.com/api-reference/bumps/create /openapi/v1/products.json post /v1/bumps Creates a new bump. # Delete Source: https://developer.surecart.com/api-reference/bumps/delete /openapi/v1/products.json delete /v1/bumps/{id} Deletes a specific bump. # Duplicate Source: https://developer.surecart.com/api-reference/bumps/duplicate /openapi/v1/products.json post /v1/bumps/{id}/duplicate Duplicates a specific order bump. # List Source: https://developer.surecart.com/api-reference/bumps/list /openapi/v1/products.json get /v1/bumps Returns a list of your bumps. # Retrieve Source: https://developer.surecart.com/api-reference/bumps/retrieve /openapi/v1/products.json get /v1/bumps/{id} Retrieves details of a specific bump. # Update Source: https://developer.surecart.com/api-reference/bumps/update /openapi/v1/products.json patch /v1/bumps/{id} Updates a specific bump. # Create Source: https://developer.surecart.com/api-reference/bundle-items/create /openapi/v1/products.json post /v1/bundle_items Creates a new bundle item. # Delete Source: https://developer.surecart.com/api-reference/bundle-items/delete /openapi/v1/products.json delete /v1/bundle_items/{id} Deletes a specific bundle item. # List Source: https://developer.surecart.com/api-reference/bundle-items/list /openapi/v1/products.json get /v1/bundle_items Returns a list of your bundle items. # Retrieve Source: https://developer.surecart.com/api-reference/bundle-items/retrieve /openapi/v1/products.json get /v1/bundle_items/{id} Retrieves details of a specific bundle item. # Update Source: https://developer.surecart.com/api-reference/bundle-items/update /openapi/v1/products.json patch /v1/bundle_items/{id} Updates a specific bundle item. # List Source: https://developer.surecart.com/api-reference/cancellation-acts/list /openapi/v1/subscriptions.json get /v1/cancellation_acts Returns a list of your cancellation acts. # Retrieve Source: https://developer.surecart.com/api-reference/cancellation-acts/retrieve /openapi/v1/subscriptions.json get /v1/cancellation_acts/{id} Retrieves details of a specific cancellation reason. # Create Source: https://developer.surecart.com/api-reference/cancellation-reasons/create /openapi/v1/subscriptions.json post /v1/cancellation_reasons Creates a new cancellation reason. # Delete Source: https://developer.surecart.com/api-reference/cancellation-reasons/delete /openapi/v1/subscriptions.json delete /v1/cancellation_reasons/{id} Deletes a specific cancellation reason. # List Source: https://developer.surecart.com/api-reference/cancellation-reasons/list /openapi/v1/subscriptions.json get /v1/cancellation_reasons Returns a list of your cancellation reasons. # Retrieve Source: https://developer.surecart.com/api-reference/cancellation-reasons/retrieve /openapi/v1/subscriptions.json get /v1/cancellation_reasons/{id} Retrieves details of a specific cancellation reason. # Update Source: https://developer.surecart.com/api-reference/cancellation-reasons/update /openapi/v1/subscriptions.json patch /v1/cancellation_reasons/{id} Updates a specific cancellation reason. # List Source: https://developer.surecart.com/api-reference/carrier-accounts/list /openapi/v1/shipping.json get /v1/shipping_providers/{shipping_provider_id}/carrier_accounts Returns the carrier accounts connected to a shipping provider, including each account's service levels. # List Source: https://developer.surecart.com/api-reference/carrier-parcel-templates/list /openapi/v1/shipping.json get /v1/shipping_providers/{shipping_provider_id}/carrier_parcel_templates Returns the carrier parcel templates available to a shipping provider. # List Source: https://developer.surecart.com/api-reference/charges/list /openapi/v1/orders.json get /v1/charges Returns a list of your charges. # Retrieve Source: https://developer.surecart.com/api-reference/charges/retrieve /openapi/v1/orders.json get /v1/charges/{id} Retrieves details of a specific charge. # Create Source: https://developer.surecart.com/api-reference/checkout-fees/create /openapi/v1/orders.json post /v1/checkout_fees Creates a new checkout fee. # Delete Source: https://developer.surecart.com/api-reference/checkout-fees/delete /openapi/v1/orders.json delete /v1/checkout_fees/{id} Deletes a specific checkout fee. # List Source: https://developer.surecart.com/api-reference/checkout-fees/list /openapi/v1/orders.json get /v1/checkout_fees Returns a list of your checkout fees. # Retrieve Source: https://developer.surecart.com/api-reference/checkout-fees/retrieve /openapi/v1/orders.json get /v1/checkout_fees/{id} Retrieves details of a specific checkout fee. # Update Source: https://developer.surecart.com/api-reference/checkout-fees/update /openapi/v1/orders.json patch /v1/checkout_fees/{id} Updates a specific checkout fee. # Retrieve Source: https://developer.surecart.com/api-reference/checkout-portal-protocols/retrieve /openapi/v1/orders.json get /v1/checkout_portal_protocol Retrieves details of the current account's checkout portal protocol. # Update Source: https://developer.surecart.com/api-reference/checkout-portal-protocols/update /openapi/v1/orders.json patch /v1/checkout_portal_protocol Updates the current account's checkout portal protocol. # Cancel Source: https://developer.surecart.com/api-reference/checkouts/cancel /openapi/v1/orders.json patch /v1/checkouts/{id}/cancel Cancels a specific checkout, regardless of its payment status. When a checkout is canceled its associated order and invoice are voided, held stock is released, associated purchases are revoked, and subscriptions are canceled. # Create Source: https://developer.surecart.com/api-reference/checkouts/create /openapi/v1/orders.json post /v1/checkouts Creates a new checkout. # Decline Upsell Source: https://developer.surecart.com/api-reference/checkouts/decline-upsell /openapi/v1/orders.json patch /v1/checkouts/{id}/decline_upsell/{upsell_id} Records a decline for the specific upsell – used for upsell analytics and to traverse through an upsell funnel by refreshing the `current_upsell`. # Finalize Source: https://developer.surecart.com/api-reference/checkouts/finalize /openapi/v1/orders.json patch /v1/checkouts/{id}/finalize Finalizes a specific checkout before it can be paid. If succesfull, this will return an associated `PaymentIntent` with the necessary information to capture the payment via the specific processor. # List Source: https://developer.surecart.com/api-reference/checkouts/list /openapi/v1/orders.json get /v1/checkouts Returns a list of your checkouts. # Manually Pay Source: https://developer.surecart.com/api-reference/checkouts/manually-pay /openapi/v1/orders.json patch /v1/checkouts/{id}/manually_pay Manually marks a checkout as paid. This can only be performed on checkouts that have been finalized. When a checkout is paid associated purchases and subscriptions will be created. # Offer Bump Source: https://developer.surecart.com/api-reference/checkouts/offer-bump /openapi/v1/orders.json patch /v1/checkouts/{id}/offer_bump/{bump_id} Records an offer for the specific bump – used for bump analytics. # Offer Upsell Source: https://developer.surecart.com/api-reference/checkouts/offer-upsell /openapi/v1/orders.json patch /v1/checkouts/{id}/offer_upsell/{upsell_id} Records an offer for the specific upsell – used for upsell analytics. # Retrieve Source: https://developer.surecart.com/api-reference/checkouts/retrieve /openapi/v1/orders.json get /v1/checkouts/{id} Retrieves details of a specific checkout. # Update Source: https://developer.surecart.com/api-reference/checkouts/update /openapi/v1/orders.json patch /v1/checkouts/{id} Updates a specific checkout. # Create Source: https://developer.surecart.com/api-reference/clicks/create /openapi/v1/public.json post /v1/public/clicks Creates a new click. # List Source: https://developer.surecart.com/api-reference/clicks/list /openapi/v1/affiliates.json get /v1/clicks Returns a list of your clicks. # Retrieve Source: https://developer.surecart.com/api-reference/clicks/retrieve /openapi/v1/affiliates.json get /v1/clicks/{id} Retrieves details of a specific click. # Create Source: https://developer.surecart.com/api-reference/coupons/create /openapi/v1/products.json post /v1/coupons Creates a new coupon. # Delete Source: https://developer.surecart.com/api-reference/coupons/delete /openapi/v1/products.json delete /v1/coupons/{id} Deletes a specific coupon. # Duplicate Source: https://developer.surecart.com/api-reference/coupons/duplicate /openapi/v1/products.json post /v1/coupons/{id}/duplicate Duplicates a specific coupon. # List Source: https://developer.surecart.com/api-reference/coupons/list /openapi/v1/products.json get /v1/coupons Returns a list of your coupons. # Retrieve Source: https://developer.surecart.com/api-reference/coupons/retrieve /openapi/v1/products.json get /v1/coupons/{id} Retrieves details of a specific coupon. # Update Source: https://developer.surecart.com/api-reference/coupons/update /openapi/v1/products.json patch /v1/coupons/{id} Updates a specific coupon. # Retrieve Source: https://developer.surecart.com/api-reference/customer-notification-protocols/retrieve /openapi/v1/customers.json get /v1/customer_notification_protocol Retrieves details of the current account's customer notification protocol. # Update Source: https://developer.surecart.com/api-reference/customer-notification-protocols/update /openapi/v1/customers.json patch /v1/customer_notification_protocol Updates the current account's customer notification protocol. # Retrieve Source: https://developer.surecart.com/api-reference/customer-portal-protocols/retrieve /openapi/v1/customers.json get /v1/customer_portal_protocol Retrieves details of the current account's customer portal protocol. # Update Source: https://developer.surecart.com/api-reference/customer-portal-protocols/update /openapi/v1/customers.json patch /v1/customer_portal_protocol Updates the current account's customer portal protocol. # Create Source: https://developer.surecart.com/api-reference/customers/create /openapi/v1/customers.json post /v1/customers Creates a new customer. # Delete Source: https://developer.surecart.com/api-reference/customers/delete /openapi/v1/customers.json delete /v1/customers/{id} Deletes a specific customer and permanently removes all of their associated data after 24 hours. # Expose Media Source: https://developer.surecart.com/api-reference/customers/expose-media /openapi/v1/customers.json get /v1/customers/{id}/expose/{media_id} Exposes a specific media that the customer has access to via a purchase. # Filter Source: https://developer.surecart.com/api-reference/customers/filter /openapi/v1/customers.json post /v1/customers/filter Returns a list of customers matching the supplied rule tree. # Filter Schema Source: https://developer.surecart.com/api-reference/customers/filter-schema /openapi/v1/customers.json get /v1/customers/filter_schema Retrieves the filter schema for customers. # List Source: https://developer.surecart.com/api-reference/customers/list /openapi/v1/customers.json get /v1/customers Returns a list of your customers. # Retrieve Source: https://developer.surecart.com/api-reference/customers/retrieve /openapi/v1/customers.json get /v1/customers/{id} Retrieves details of a specific customer. # Update Source: https://developer.surecart.com/api-reference/customers/update /openapi/v1/customers.json patch /v1/customers/{id} Updates a specific customer. # List Discounts Source: https://developer.surecart.com/api-reference/discounts/list-discounts /openapi/v1/products.json get /v1/discounts Returns a list of discounts (only redeemed discounts). # Retrieve Discount Source: https://developer.surecart.com/api-reference/discounts/retrieve-discount /openapi/v1/products.json get /v1/discounts/{id} Retrieves details of a specific discount (only redeemed discounts). # Create Source: https://developer.surecart.com/api-reference/display-currencies/create /openapi/v1/core.json post /v1/display_currencies Creates a new display currency. # Delete Source: https://developer.surecart.com/api-reference/display-currencies/delete /openapi/v1/core.json delete /v1/display_currencies/{id} Deletes a specific display currency. # List Source: https://developer.surecart.com/api-reference/display-currencies/list /openapi/v1/core.json get /v1/display_currencies Returns a list of your display currencies. # Retrieve Source: https://developer.surecart.com/api-reference/display-currencies/retrieve /openapi/v1/core.json get /v1/display_currencies/{id} Retrieves details of a specific display currency. # List Source: https://developer.surecart.com/api-reference/disputes/list /openapi/v1/orders.json get /v1/disputes Returns a list of your disputes. # Retrieve Source: https://developer.surecart.com/api-reference/disputes/retrieve /openapi/v1/orders.json get /v1/disputes/{id} Retrieves details of a specific dispute. # Create Source: https://developer.surecart.com/api-reference/downloads/create /openapi/v1/products.json post /v1/downloads Creates a new download. # Delete Source: https://developer.surecart.com/api-reference/downloads/delete /openapi/v1/products.json delete /v1/downloads/{id} Deletes a specific download. # List Source: https://developer.surecart.com/api-reference/downloads/list /openapi/v1/products.json get /v1/downloads Returns a list of your downloads. # Retrieve Source: https://developer.surecart.com/api-reference/downloads/retrieve /openapi/v1/products.json get /v1/downloads/{id} Retrieves details of a specific download. # Update Source: https://developer.surecart.com/api-reference/downloads/update /openapi/v1/products.json patch /v1/downloads/{id} Updates a specific download. # Errors Source: https://developer.surecart.com/api-reference/errors SureCart uses conventional HTTP response codes to indicate the success or failure of an API request. In general: codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.). Codes in the 5xx range indicate an error with SureCart's servers (these are rare). ### HTTP Status Codes These are all of the status codes that the SureCart API will return. | HTTP Status | Description | | :------------------------- | :---------------------------------------------------------------------- | | `200` OK | Everything worked as expected | | `400` Bad Request | The request was unacceptable, often due to missing a required parameter | | `401`Unauthorized | Invalid API token provided | | `404` Not Found | The requested resource doesn't exist | | `422` Unprocessable Entity | The request failed validation or was not allowed for another reason | | `500` Server Error | Something went wrong on SureCart's end | ### Error Responses All error responses will be formatted like the example below, and they will have at least the following keys: * `http_status` – The HTTP status code – matching the HTTP response status. * `type` – The type of error – more specific than the http\_status. * `code` – The unique code for the error – this should be used for translations. * `message` – The human readable error message. ```json theme={null} { "http_status": "unprocessable_entity", "type": "not_found", "code": "product.not_found", "message": "Unable to find product with id='e0e92d34-aed9-4bb8-9107-89309370c4b'", "validation_errors": {} } ``` ### Validation Errors If an error is due to object validation a validation\_errors key will also be set within the error response. The validation errors response will be formatted like the example below, and each validation error will have the following keys: * `attribute` – The attribute the validation error is associated with. * `type` – The type of validation error. * `code` – The unique code for the validation error – this should be used for translations. * `options` – Any options that apply to this error – these can be used for translation interpolation. (For example, a numerical validation error might have options for min and max.) * `message` – The human readable validation error message. ```json theme={null} { "type": "unprocessable_entity", "code": "product.invalid", "message": "Failed to save product", "validation_errors": [ { "attribute": "name", "type": "blank", "code": "product.name.blank", "options": {}, "message": "can't be blank" } ] } ``` # List Source: https://developer.surecart.com/api-reference/events/list /openapi/v1/core.json get /v1/events Returns a list of your events. # Retrieve Source: https://developer.surecart.com/api-reference/events/retrieve /openapi/v1/core.json get /v1/events/{id} Retrieves details of a specific event. # Expanding Responses Source: https://developer.surecart.com/api-reference/expanding-responses Many objects allow you to request additional information as an expanded response by using the expand request parameter. This parameter is available on all API requests, and applies to the response of that request only. ### Two Types of Expandable Properties In many cases, a response contains the ID of a related object in its properties by default. For example, a `price` has an associated `product`. In others cases, there are expandable properties on a response that are not by default included in the response. For example, a list of all `prices` in the `product` response. ### How to Expand Properties Properties that can be expanded into objects are noted in this documentation with the `Expandable` label. You can request these properties be expanded by using the `expand[]` request parameter. **Example Request:** ```curl theme={null} curl \ -X GET https://api.surecart.com/v1/orders/0d6edf76-98f3-441c-9c43-81a92e929988 \ -H "Authorization: Bearer YOUR-API-KEY" \ -d "expand[]"="checkout" \ -d "expand[]"="checkout.customer" ``` **Example Response:** ```json theme={null} { "id": "0d6edf76-98f3-441c-9c43-81a92e929988", "object": "order", "live_mode": true, "number": "0008", "order_type": "checkout", "statement_url": "https://app.surecart.com/statements/orders/0d6edf76-98f3-441c-9c43-81a92e929988", "status": "paid", "checkout": { "id": "f1a38ad4-f87d-4550-b2e0-91a128cadf06", "object": "checkout", "abandoned_checkout_enabled": true, "amount_due": 1900, ... "customer": { "id": "9efd5506-3b69-47d5-9a1e-fbc718aaf148", "object": "customer", "billing_matches_shipping": true, "email": "test@example.com", "first_name": "Test", "indexed": true, "last_name": "Customer", "live_mode": true, "name": "Test Customer", "phone": null, "unsubscribed": false, "billing_address": null, "default_payment_method": "5dd6179f-ac0d-4532-b84b-cb6a168f6ace", "shipping_address": "3732e0ee-2b76-44a7-9525-580c22845781", "tax_identifier": null, "created_at": 1664390001, "updated_at": 1664479758 }, ... "created_at": 1664479197, "updated_at": 1664479757 }, "created_at": 1664479758, "updated_at": 1664479758 } ``` ### Expand Limits * You can use the expand request parameter on any endpoint which returns expandable fields, including list, create, and update endpoints. * You can expand multiple objects at once by identifying multiple items in the expand request parameter. * Expansions have a maximum depth of two levels, and you can expand up to 15 objects. ### Expanding Recursively You can expand recursively by specifying nested expandable properties after a dot(.). For example, requesting to expand `checkout` and `checkout.customer` on a `order` will expand the checkout and the customer within the checkout. Expanding list requests are plural, but expanding objects within a list are singular. For example, if you wanted to retrieve a checkout's line items and each line item's price, you would pass list\_items and list\_item.price as expand parameters. # Create Source: https://developer.surecart.com/api-reference/exports/create /openapi/v1/core.json post /v1/exports Creates a new export. # List Source: https://developer.surecart.com/api-reference/exports/list /openapi/v1/core.json get /v1/exports Returns a list of your exports. # Retrieve Source: https://developer.surecart.com/api-reference/exports/retrieve /openapi/v1/core.json get /v1/exports/{id} Retrieves details of a specific export. # Create Source: https://developer.surecart.com/api-reference/fees/create /openapi/v1/orders.json post /v1/fees Creates a new fee. # Delete Source: https://developer.surecart.com/api-reference/fees/delete /openapi/v1/orders.json delete /v1/fees/{id} Deletes a specific fee. # List Source: https://developer.surecart.com/api-reference/fees/list /openapi/v1/orders.json get /v1/fees Returns a list of your fees. # Retrieve Source: https://developer.surecart.com/api-reference/fees/retrieve /openapi/v1/orders.json get /v1/fees/{id} Retrieves details of a specific fee. # Update Source: https://developer.surecart.com/api-reference/fees/update /openapi/v1/orders.json patch /v1/fees/{id} Updates a specific fee. # List Source: https://developer.surecart.com/api-reference/fulfillment-items/list /openapi/v1/shipping.json get /v1/fulfillment_items Returns a list of your fulfillment items. # Retrieve Source: https://developer.surecart.com/api-reference/fulfillment-items/retrieve /openapi/v1/shipping.json get /v1/fulfillment_items/{id} Retrieves details of a specific fulfillment item. # Create Source: https://developer.surecart.com/api-reference/fulfillments/create /openapi/v1/shipping.json post /v1/fulfillments Creates a new fulfillment. # Delete Source: https://developer.surecart.com/api-reference/fulfillments/delete /openapi/v1/shipping.json delete /v1/fulfillments/{id} Deletes a specific fulfillment. # List Source: https://developer.surecart.com/api-reference/fulfillments/list /openapi/v1/shipping.json get /v1/fulfillments Returns a list of your fulfillments. # Retrieve Source: https://developer.surecart.com/api-reference/fulfillments/retrieve /openapi/v1/shipping.json get /v1/fulfillments/{id} Retrieves details of a specific fulfillment. # Update Source: https://developer.surecart.com/api-reference/fulfillments/update /openapi/v1/shipping.json patch /v1/fulfillments/{id} Updates a specific fulfillment. # List Source: https://developer.surecart.com/api-reference/import-rows/list /openapi/v1/core.json get /v1/import_rows Returns a list of import rows. # Batch Create Coupons Source: https://developer.surecart.com/api-reference/imports/batch-create-coupons /openapi/v1/core.json post /v1/imports/coupons Creates multiple coupons in batch. # Batch Create Product Collections Source: https://developer.surecart.com/api-reference/imports/batch-create-product-collections /openapi/v1/core.json post /v1/imports/product_collections Creates multiple product collections in batch. # Batch Create Products Source: https://developer.surecart.com/api-reference/imports/batch-create-products /openapi/v1/core.json post /v1/imports/products Creates multiple products in batch. # List Source: https://developer.surecart.com/api-reference/imports/list /openapi/v1/core.json get /v1/imports Returns a list of your imports. # Retrieve Source: https://developer.surecart.com/api-reference/imports/retrieve /openapi/v1/core.json get /v1/imports/{id} Retrieves details of a specific import. # Introduction Source: https://developer.surecart.com/api-reference/introduction The SureCart API is organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs. # Create Source: https://developer.surecart.com/api-reference/invoices/create /openapi/v1/orders.json post /v1/invoices Creates a new invoice. # Delete Source: https://developer.surecart.com/api-reference/invoices/delete /openapi/v1/orders.json delete /v1/invoices/{id} Deletes a specific invoice. # List Source: https://developer.surecart.com/api-reference/invoices/list /openapi/v1/orders.json get /v1/invoices Returns a list of your invoices. # Make Draft Source: https://developer.surecart.com/api-reference/invoices/make-draft /openapi/v1/orders.json patch /v1/invoices/{id}/make_draft Revert an open invoice back to draft. # Open Source: https://developer.surecart.com/api-reference/invoices/open /openapi/v1/orders.json patch /v1/invoices/{id}/open Open an invoice to send it to the customer or collect payment immediately. # Resend Notification Source: https://developer.surecart.com/api-reference/invoices/resend-notification /openapi/v1/orders.json post /v1/invoices/{id}/resend_notification Resend invoice to the customer. # Retrieve Source: https://developer.surecart.com/api-reference/invoices/retrieve /openapi/v1/orders.json get /v1/invoices/{id} Retrieves details of a specific invoice. # Update Source: https://developer.surecart.com/api-reference/invoices/update /openapi/v1/orders.json patch /v1/invoices/{id} Updates a specific invoice. # Create Source: https://developer.surecart.com/api-reference/licenses/create /openapi/v1/licensing.json post /v1/licenses Creates a new license. # Delete Source: https://developer.surecart.com/api-reference/licenses/delete /openapi/v1/licensing.json delete /v1/licenses/{id} Deletes a specific license. # Expose Current Release Source: https://developer.surecart.com/api-reference/licenses/expose-current-release /openapi/v1/public.json get /v1/public/licenses/{key}/expose_current_release Exposes the current release media for the license. # List Source: https://developer.surecart.com/api-reference/licenses/list /openapi/v1/licensing.json get /v1/licenses Returns a list of your licenses. # Retrieve Source: https://developer.surecart.com/api-reference/licenses/retrieve /openapi/v1/public.json get /v1/public/licenses/{key} Retrieves a license by it's key. # Update Source: https://developer.surecart.com/api-reference/licenses/update /openapi/v1/licensing.json patch /v1/licenses/{id} Updates a specific license. # Create Source: https://developer.surecart.com/api-reference/line-items/create /openapi/v1/orders.json post /v1/line_items Creates a new line item. # Delete Source: https://developer.surecart.com/api-reference/line-items/delete /openapi/v1/orders.json delete /v1/line_items/{id} Deletes a specific line item. # List Source: https://developer.surecart.com/api-reference/line-items/list /openapi/v1/orders.json get /v1/line_items Returns a list of your line_items. # Offer Swap Source: https://developer.surecart.com/api-reference/line-items/offer-swap /openapi/v1/orders.json patch /v1/line_items/{id}/offer_swap Records an offer for the specific swap – used for swap analytics. # Retrieve Source: https://developer.surecart.com/api-reference/line-items/retrieve /openapi/v1/orders.json get /v1/line_items/{id} Retrieves details of a specific line item. # Swap Source: https://developer.surecart.com/api-reference/line-items/swap /openapi/v1/orders.json patch /v1/line_items/{id}/swap Performs a swap on the line item for the specific swap price. # Unswap Source: https://developer.surecart.com/api-reference/line-items/unswap /openapi/v1/orders.json patch /v1/line_items/{id}/unswap Reverses the swap on the line item for the original price. # Update Source: https://developer.surecart.com/api-reference/line-items/update /openapi/v1/orders.json patch /v1/line_items/{id} Updates a specific line item. # Upsell Source: https://developer.surecart.com/api-reference/line-items/upsell /openapi/v1/orders.json post /v1/line_items/upsell Creates a new line item as an upsell. An attempt to pay the upsell will be made using the payment method on the checkout. # List Source: https://developer.surecart.com/api-reference/manual-charges/list /openapi/v1/orders.json get /v1/manual_charges Returns a list of your manual charges. # Retrieve Source: https://developer.surecart.com/api-reference/manual-charges/retrieve /openapi/v1/orders.json get /v1/manual_charges/{id} Retrieves details of a specific manual charge. # Create Source: https://developer.surecart.com/api-reference/manual-payment-methods/create /openapi/v1/orders.json post /v1/manual_payment_methods Creates a new manual_payment_method. # Delete Source: https://developer.surecart.com/api-reference/manual-payment-methods/delete /openapi/v1/orders.json delete /v1/manual_payment_methods/{id} Deletes a specific manual payment method. # List Source: https://developer.surecart.com/api-reference/manual-payment-methods/list /openapi/v1/orders.json get /v1/manual_payment_methods Returns a list of your manual payment methods. # Retrieve Source: https://developer.surecart.com/api-reference/manual-payment-methods/retrieve /openapi/v1/orders.json get /v1/manual_payment_methods/{id} Retrieves details of a specific manual payment method. # Update Source: https://developer.surecart.com/api-reference/manual-payment-methods/update /openapi/v1/orders.json patch /v1/manual_payment_methods/{id} Updates a specific manual payment method. # Create Source: https://developer.surecart.com/api-reference/medias/create /openapi/v1/core.json post /v1/medias Creates a new media. # Delete Source: https://developer.surecart.com/api-reference/medias/delete /openapi/v1/core.json delete /v1/medias/{id} Deletes a specific media. # List Source: https://developer.surecart.com/api-reference/medias/list /openapi/v1/core.json get /v1/medias Returns a list of your medias. # Retrieve Source: https://developer.surecart.com/api-reference/medias/retrieve /openapi/v1/core.json get /v1/medias/{id} Retrieves details of a specific media. # Update Source: https://developer.surecart.com/api-reference/medias/update /openapi/v1/core.json patch /v1/medias/{id} Updates a specific media. # Metadata Source: https://developer.surecart.com/api-reference/metadata Some SureCart objects (i.e. Checkout and Product) have a metadata parameter. You can use this parameter to attach key-value data to these objects. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. Metadata is not used by SureCart and won't be seen by your users unless you choose to show it to them. Do not store any sensitive information (bank account numbers, card details, etc.) as metadata. # Live & Test Mode Source: https://developer.surecart.com/api-reference/modes When creating `Checkout`, `PaymentIntent`, `Subscription`, etc. objects you can specify `live_mode`. If you set `live_mode=false` then all interactions with processors will be done in their respective live or sandbox modes. This allows you to create test charges, subscriptions, and run full checkout flows without charging real payment methods. # Create Source: https://developer.surecart.com/api-reference/notes/create /openapi/v1/core.json post /v1/notes Creates a new note. # Delete Source: https://developer.surecart.com/api-reference/notes/delete /openapi/v1/core.json delete /v1/notes/{id} Deletes a specific note. # List Source: https://developer.surecart.com/api-reference/notes/list /openapi/v1/core.json get /v1/notes Returns a list of your notes. # Retrieve Source: https://developer.surecart.com/api-reference/notes/retrieve /openapi/v1/core.json get /v1/notes/{id} Retrieves details of a specific note. # Update Source: https://developer.surecart.com/api-reference/notes/update /openapi/v1/core.json patch /v1/notes/{id} Updates a specific note. # Retrieve Source: https://developer.surecart.com/api-reference/order-protocols/retrieve /openapi/v1/orders.json get /v1/order_protocol Retrieves details of the current account's order protocol. # Update Source: https://developer.surecart.com/api-reference/order-protocols/update /openapi/v1/orders.json patch /v1/order_protocol Updates the current account's order protocol. # Filter Source: https://developer.surecart.com/api-reference/orders/filter /openapi/v1/orders.json post /v1/orders/filter Returns a list of orders matching the supplied rule tree. # Filter Schema Source: https://developer.surecart.com/api-reference/orders/filter-schema /openapi/v1/orders.json get /v1/orders/filter_schema Retrieves the filter schema for orders. # List Source: https://developer.surecart.com/api-reference/orders/list /openapi/v1/orders.json get /v1/orders Returns a list of your orders. # Resend Notification Source: https://developer.surecart.com/api-reference/orders/resend-notification /openapi/v1/orders.json post /v1/orders/{id}/resend_notification Resend order confirmation or subscription renewal email to the customer. # Retrieve Source: https://developer.surecart.com/api-reference/orders/retrieve /openapi/v1/orders.json get /v1/orders/{id} Retrieves details of a specific order. # Pagination & Sorting Source: https://developer.surecart.com/api-reference/pagination SureCart utilizes offset-based pagination, and all top-level API resources have support for bulk fetches via "list" API methods. For instance, you can list products, prices, and customers. These list API methods share a common structure, taking at least these two parameters: `limit`, and `page`. The default pagination limit is `20` and the max is `100`. By default, all list API methods return collections sorted by `created_at` in `desc` order. The sort order can be adjusted by passing the `sort` parameter. The format for this parameter is `?sort=column:order` which allows you to specify the value to sort by and the order. For example, if you wanted to sort by `updated_at` in `asc` order you would set the parameter to `?sort=updated_at:asc`. All list API methods can be sorted by `created_at` and `updated_at` values. Some API endpoints can be sorted by other values, and these methods have further documentation on the sort parameter. # Create Source: https://developer.surecart.com/api-reference/parcel-templates/create /openapi/v1/shipping.json post /v1/parcel_templates Creates a new parcel template. # Delete Source: https://developer.surecart.com/api-reference/parcel-templates/delete /openapi/v1/shipping.json delete /v1/parcel_templates/{id} Deletes a specific parcel template. # List Source: https://developer.surecart.com/api-reference/parcel-templates/list /openapi/v1/shipping.json get /v1/parcel_templates Returns a list of your parcel templates. # Retrieve Source: https://developer.surecart.com/api-reference/parcel-templates/retrieve /openapi/v1/shipping.json get /v1/parcel_templates/{id} Retrieves details of a specific parcel template. # Update Source: https://developer.surecart.com/api-reference/parcel-templates/update /openapi/v1/shipping.json patch /v1/parcel_templates/{id} Updates a specific parcel template. # List Source: https://developer.surecart.com/api-reference/payment-failures/list /openapi/v1/orders.json get /v1/payment_failures Returns a list of your payment failures. # Capture Source: https://developer.surecart.com/api-reference/payment-intents/capture /openapi/v1/orders.json patch /v1/payment_intents/{id}/capture Capture a specific payment intent. # Create Source: https://developer.surecart.com/api-reference/payment-intents/create /openapi/v1/orders.json post /v1/payment_intents Creates a new payment intent. # List Source: https://developer.surecart.com/api-reference/payment-intents/list /openapi/v1/orders.json get /v1/payment_intents Returns a list of your payment intents. # Retrieve Source: https://developer.surecart.com/api-reference/payment-intents/retrieve /openapi/v1/orders.json get /v1/payment_intents/{id} Retrieves details of a specific payment intent. # Detach Source: https://developer.surecart.com/api-reference/payment-methods/detach /openapi/v1/orders.json patch /v1/payment_methods/{id}/detach Detaches a payment method from the associated customer. # List Source: https://developer.surecart.com/api-reference/payment-methods/list /openapi/v1/orders.json get /v1/payment_methods Returns a list of your payment methods. # Retrieve Source: https://developer.surecart.com/api-reference/payment-methods/retrieve /openapi/v1/orders.json get /v1/payment_methods/{id} Retrieves details of a specific payment method. # Create Source: https://developer.surecart.com/api-reference/payout-groups/create /openapi/v1/affiliates.json post /v1/payout_groups Creates a new payout group. # List Source: https://developer.surecart.com/api-reference/payout-groups/list /openapi/v1/affiliates.json get /v1/payout_groups Returns a list of your payout groups. # Retrieve Source: https://developer.surecart.com/api-reference/payout-groups/retrieve /openapi/v1/affiliates.json get /v1/payout_groups/{id} Retrieves details of a specific payout group. # Complete Source: https://developer.surecart.com/api-reference/payouts/complete /openapi/v1/affiliates.json patch /v1/payouts/{id}/complete Completes a specific payout. # Create Source: https://developer.surecart.com/api-reference/payouts/create /openapi/v1/affiliates.json post /v1/payouts Creates a new payout. # Delete Source: https://developer.surecart.com/api-reference/payouts/delete /openapi/v1/affiliates.json delete /v1/payouts/{id} Deletes a specific payout. # List Source: https://developer.surecart.com/api-reference/payouts/list /openapi/v1/affiliates.json get /v1/payouts Returns a list of your payouts. # Make Processing Source: https://developer.surecart.com/api-reference/payouts/make-processing /openapi/v1/affiliates.json patch /v1/payouts/{id}/make_processing Makes a specific payout processing. # Retrieve Source: https://developer.surecart.com/api-reference/payouts/retrieve /openapi/v1/affiliates.json get /v1/payouts/{id} Retrieves details of a specific payout. # List Source: https://developer.surecart.com/api-reference/periods/list /openapi/v1/subscriptions.json get /v1/periods Returns a list of periods. # Retry Payment Source: https://developer.surecart.com/api-reference/periods/retry-payment /openapi/v1/subscriptions.json patch /v1/periods/{id}/retry_payment Retries payment for a specific period. # Update Source: https://developer.surecart.com/api-reference/periods/update /openapi/v1/subscriptions.json patch /v1/periods/{id} Updates a specific period. # Create Source: https://developer.surecart.com/api-reference/prices/create /openapi/v1/products.json post /v1/prices Creates a new price. # Delete Source: https://developer.surecart.com/api-reference/prices/delete /openapi/v1/products.json delete /v1/prices/{id} Deletes a specific price. # Duplicate Source: https://developer.surecart.com/api-reference/prices/duplicate /openapi/v1/products.json post /v1/prices/{id}/duplicate Duplicates a specific price. # List Source: https://developer.surecart.com/api-reference/prices/list /openapi/v1/products.json get /v1/prices Returns a list of your prices. # Retrieve Source: https://developer.surecart.com/api-reference/prices/retrieve /openapi/v1/products.json get /v1/prices/{id} Retrieves details of a specific price. # Update Source: https://developer.surecart.com/api-reference/prices/update /openapi/v1/products.json patch /v1/prices/{id} Updates a specific price. # List Source: https://developer.surecart.com/api-reference/processors/list /openapi/v1/core.json get /v1/processors Returns a list of your processors. # Payment Method Types Source: https://developer.surecart.com/api-reference/processors/payment-method-types /openapi/v1/core.json get /v1/processors/{id}/payment_method_types Retrieves a list of available payment method types for this specific processor and the given parameters (amount, country, etc.). This endpoint is only available for `mollie` processors. # Retrieve Source: https://developer.surecart.com/api-reference/processors/retrieve /openapi/v1/core.json get /v1/processors/{id} Retrieves details of a specific processor. # Create Source: https://developer.surecart.com/api-reference/product-collections/create /openapi/v1/products.json post /v1/product_collections Creates a new product collection. # Delete Source: https://developer.surecart.com/api-reference/product-collections/delete /openapi/v1/products.json delete /v1/product_collections/{id} Deletes a specific product collection. # List Source: https://developer.surecart.com/api-reference/product-collections/list /openapi/v1/products.json get /v1/product_collections Returns a list of your product collections # Retrieve Source: https://developer.surecart.com/api-reference/product-collections/retrieve /openapi/v1/products.json get /v1/product_collections/{id} Retrieves details of a specific product collection. The `{id}` section of the endpoint accepts the product collection ID or slug. # Update Source: https://developer.surecart.com/api-reference/product-collections/update /openapi/v1/products.json patch /v1/product_collections/{id} Updates a specific product collection # Create Source: https://developer.surecart.com/api-reference/product-groups/create /openapi/v1/products.json post /v1/product_groups Creates a new product group. # Delete Source: https://developer.surecart.com/api-reference/product-groups/delete /openapi/v1/products.json delete /v1/product_groups/{id} Deletes a specific product group. # List Source: https://developer.surecart.com/api-reference/product-groups/list /openapi/v1/products.json get /v1/product_groups Returns a list of your product groups. # Retrieve Source: https://developer.surecart.com/api-reference/product-groups/retrieve /openapi/v1/products.json get /v1/product_groups/{id} Retrieves details of a specific product group. # Update Source: https://developer.surecart.com/api-reference/product-groups/update /openapi/v1/products.json patch /v1/product_groups/{id} Updates a specific product group. # Create Source: https://developer.surecart.com/api-reference/product-medias/create /openapi/v1/products.json post /v1/product_medias Create a new product media. # Delete Source: https://developer.surecart.com/api-reference/product-medias/delete /openapi/v1/products.json delete /v1/product_medias/{id} Deletes a specific product media. # List Source: https://developer.surecart.com/api-reference/product-medias/list /openapi/v1/products.json get /v1/product_medias Returns a list of your product medias. # Retrieve Source: https://developer.surecart.com/api-reference/product-medias/retrieve /openapi/v1/products.json get /v1/product_medias/{id} Retrieves details of a specific product media. # Update Source: https://developer.surecart.com/api-reference/product-medias/update /openapi/v1/products.json patch /v1/product_medias/{id} Updates a specific product media. # Create Source: https://developer.surecart.com/api-reference/products/create /openapi/v1/products.json post /v1/products Creates a new product. # Delete Source: https://developer.surecart.com/api-reference/products/delete /openapi/v1/products.json delete /v1/products/{id} Deletes a specific product. # Duplicate Source: https://developer.surecart.com/api-reference/products/duplicate /openapi/v1/products.json post /v1/products/{id}/duplicate Duplicates a specific product. # List Source: https://developer.surecart.com/api-reference/products/list /openapi/v1/products.json get /v1/products Returns a list of your products. # Retrieve Source: https://developer.surecart.com/api-reference/products/retrieve /openapi/v1/products.json get /v1/products/{id} Retrieves details of a specific product. The `{id}` section of this endpoint accepts the product ID or slug. # Update Source: https://developer.surecart.com/api-reference/products/update /openapi/v1/products.json patch /v1/products/{id} Updates a specific product. # Create Source: https://developer.surecart.com/api-reference/promotions/create /openapi/v1/products.json post /v1/promotions Creates a new promotion. # Delete Source: https://developer.surecart.com/api-reference/promotions/delete /openapi/v1/products.json delete /v1/promotions/{id} Deletes a specific promotion. # List Source: https://developer.surecart.com/api-reference/promotions/list /openapi/v1/products.json get /v1/promotions Returns a list of your promotions. # Retrieve Source: https://developer.surecart.com/api-reference/promotions/retrieve /openapi/v1/products.json get /v1/promotions/{id} Retrieves details of a specific promotion. # Update Source: https://developer.surecart.com/api-reference/promotions/update /openapi/v1/products.json patch /v1/promotions/{id} Updates a specific promotion. # Create Source: https://developer.surecart.com/api-reference/purchases/create /openapi/v1/orders.json post /v1/purchases Creates a new purchase. # Invoke Source: https://developer.surecart.com/api-reference/purchases/invoke /openapi/v1/orders.json patch /v1/purchases/{id}/invoke Invokes a specific purchase. # List Source: https://developer.surecart.com/api-reference/purchases/list /openapi/v1/orders.json get /v1/purchases Returns a list of purchases. # Retrieve Source: https://developer.surecart.com/api-reference/purchases/retrieve /openapi/v1/orders.json get /v1/purchases/{id} Retrieves details of a specific purchase. # Revoke Source: https://developer.surecart.com/api-reference/purchases/revoke /openapi/v1/orders.json patch /v1/purchases/{id}/revoke Revokes a specific purchase. # Update Source: https://developer.surecart.com/api-reference/purchases/update /openapi/v1/orders.json patch /v1/purchases/{id} Updates a specific purchase. # Rate Limiting Source: https://developer.surecart.com/api-reference/rate-limiting The SureCart API uses a number of safeguards against bursts of incoming traffic to help maximize its stability. If you send many requests in quick succession, you might see error responses with status code 429. ### API Limiters We have several limiters in the API, including a rate limiter and a concurrency limiter. Treat the limits as maximums, and don’t generate unnecessary load. To prevent abuse, we might reduce the limits. You can request a limit increase to enable a high-traffic application by contacting SureCart Support. ### Rate Limits The basic rate limiter restricts the number of API requests as follows: Default Limit: 150 operations / 10 seconds Sensitive Endpoints: 10 operations / 1 minute Public Endpoints: 60 operations / 1 minute Sensitive endpoints include those that may trigger notifications or call third-party services. In general, these are endpoints that should not be called frequently. Public endpoints are those that are accessible with a public API key. For example, our license check endpoint. # List Source: https://developer.surecart.com/api-reference/referral-items/list /openapi/v1/affiliates.json get /v1/referral_items Returns a list of your referral items. # Retrieve Source: https://developer.surecart.com/api-reference/referral-items/retrieve /openapi/v1/affiliates.json get /v1/referral_items/{id} Retrieves details of a specific referral item. # Approve Source: https://developer.surecart.com/api-reference/referrals/approve /openapi/v1/affiliates.json patch /v1/referrals/{id}/approve Approves a specific referral. # Create Source: https://developer.surecart.com/api-reference/referrals/create /openapi/v1/affiliates.json post /v1/referrals Creates a new referral. # Delete Source: https://developer.surecart.com/api-reference/referrals/delete /openapi/v1/affiliates.json delete /v1/referrals/{id} Deletes a specific referral. # Deny Source: https://developer.surecart.com/api-reference/referrals/deny /openapi/v1/affiliates.json patch /v1/referrals/{id}/deny Denies a specific referral. # List Source: https://developer.surecart.com/api-reference/referrals/list /openapi/v1/affiliates.json get /v1/referrals Returns a list of your referrals. # Make Reviewing Source: https://developer.surecart.com/api-reference/referrals/make-reviewing /openapi/v1/affiliates.json patch /v1/referrals/{id}/make_reviewing Makes a specific referral reveiwing. # Retrieve Source: https://developer.surecart.com/api-reference/referrals/retrieve /openapi/v1/affiliates.json get /v1/referrals/{id} Retrieves details of a specific referral. # Update Source: https://developer.surecart.com/api-reference/referrals/update /openapi/v1/affiliates.json patch /v1/referrals/{id} Updates a specific referral. # List Source: https://developer.surecart.com/api-reference/refund-items/list /openapi/v1/orders.json get /v1/refund_items Returns a list of your refund items. # Retrieve Source: https://developer.surecart.com/api-reference/refund-items/retrieve /openapi/v1/orders.json get /v1/refund_items/{id} Retrieves details of a specific refund item. # Create Source: https://developer.surecart.com/api-reference/refunds/create /openapi/v1/orders.json post /v1/refunds Creates a new refund. # List Source: https://developer.surecart.com/api-reference/refunds/list /openapi/v1/orders.json get /v1/refunds Returns a list of your refunds. # Retrieve Source: https://developer.surecart.com/api-reference/refunds/retrieve /openapi/v1/orders.json get /v1/refunds/{id} Retrieves details of a specific refund. # List Source: https://developer.surecart.com/api-reference/return-items/list /openapi/v1/shipping.json get /v1/return_items Returns a list of your return items. # Retrieve Source: https://developer.surecart.com/api-reference/return-items/retrieve /openapi/v1/shipping.json get /v1/return_items/{id} Retrieves details of a specific return item. # Complete Source: https://developer.surecart.com/api-reference/return-requests/complete /openapi/v1/shipping.json patch /v1/return_requests/{id}/complete Updates status of a specific return request to `complete`. # Create Source: https://developer.surecart.com/api-reference/return-requests/create /openapi/v1/shipping.json post /v1/return_requests Creates a new return request. # Delete Source: https://developer.surecart.com/api-reference/return-requests/delete /openapi/v1/shipping.json delete /v1/return_requests/{id} Deletes a specific return request. # List Source: https://developer.surecart.com/api-reference/return-requests/list /openapi/v1/shipping.json get /v1/return_requests Returns a list of your return requests. # List Return Reasons Source: https://developer.surecart.com/api-reference/return-requests/list-return-reasons /openapi/v1/shipping.json get /v1/return_reasons Returns a list of possible return reasons. # Open Source: https://developer.surecart.com/api-reference/return-requests/open /openapi/v1/shipping.json patch /v1/return_requests/{id}/open Updates status of a specific return request to `open`. # Retrieve Source: https://developer.surecart.com/api-reference/return-requests/retrieve /openapi/v1/shipping.json get /v1/return_requests/{id} Retrieves details of a specific return request. # Update Source: https://developer.surecart.com/api-reference/return-requests/update /openapi/v1/shipping.json patch /v1/return_requests/{id} Updates a specific return request. # Create Source: https://developer.surecart.com/api-reference/review-medias/create /openapi/v1/products.json post /v1/review_medias Create a new review media. # Delete Source: https://developer.surecart.com/api-reference/review-medias/delete /openapi/v1/products.json delete /v1/review_medias/{id} Deletes a specific review media. # List Source: https://developer.surecart.com/api-reference/review-medias/list /openapi/v1/products.json get /v1/review_medias Returns a list of your review medias. # Retrieve Source: https://developer.surecart.com/api-reference/review-medias/retrieve /openapi/v1/products.json get /v1/review_medias/{id} Retrieves details of a specific review media. # Retrieve Source: https://developer.surecart.com/api-reference/review-protocols/retrieve /openapi/v1/products.json get /v1/review_protocol Retrieves details of the current account's review protocol. # Update Source: https://developer.surecart.com/api-reference/review-protocols/update /openapi/v1/products.json patch /v1/review_protocol Updates the current account's review protocol. # Create Source: https://developer.surecart.com/api-reference/reviews/create /openapi/v1/products.json post /v1/reviews Creates a new review. # Delete Source: https://developer.surecart.com/api-reference/reviews/delete /openapi/v1/products.json delete /v1/reviews/{id} Deletes a specific review. # List Source: https://developer.surecart.com/api-reference/reviews/list /openapi/v1/products.json get /v1/reviews Returns a list of your reviews. # Publish Source: https://developer.surecart.com/api-reference/reviews/publish /openapi/v1/products.json patch /v1/reviews/{id}/publish Publishes a specific review. # Retrieve Source: https://developer.surecart.com/api-reference/reviews/retrieve /openapi/v1/products.json get /v1/reviews/{id} Retrieves details of a specific review. # Unpublish Source: https://developer.surecart.com/api-reference/reviews/unpublish /openapi/v1/products.json patch /v1/reviews/{id}/unpublish Unpublishes a specific review. # Update Source: https://developer.surecart.com/api-reference/reviews/update /openapi/v1/products.json patch /v1/reviews/{id} Updates a specific review. # Create Source: https://developer.surecart.com/api-reference/shipments/create /openapi/v1/shipping.json post /v1/shipments Creates a new shipment. # List Source: https://developer.surecart.com/api-reference/shipments/list /openapi/v1/shipping.json get /v1/shipments Returns a list of your shipments. # Purchase Source: https://developer.surecart.com/api-reference/shipments/purchase /openapi/v1/shipping.json patch /v1/shipments/{id}/purchase Purchases a shipping label for a specific shipment using the selected rate. # Quote Source: https://developer.surecart.com/api-reference/shipments/quote /openapi/v1/shipping.json patch /v1/shipments/{id}/quote Fetches shipping rates for a specific shipment. # Retrieve Source: https://developer.surecart.com/api-reference/shipments/retrieve /openapi/v1/shipping.json get /v1/shipments/{id} Retrieves details of a specific shipment. # Update Source: https://developer.surecart.com/api-reference/shipments/update /openapi/v1/shipping.json patch /v1/shipments/{id} Updates a specific shipment. # Void Source: https://developer.surecart.com/api-reference/shipments/void /openapi/v1/shipping.json patch /v1/shipments/{id}/void Voids a purchased shipping label for a specific shipment. # List Source: https://developer.surecart.com/api-reference/shipping-choices/list /openapi/v1/shipping.json get /v1/shipping_choices Returns a list of your shipping choices. # Create Source: https://developer.surecart.com/api-reference/shipping-fees/create /openapi/v1/orders.json post /v1/shipping_fees Creates a new shipping fee. # Delete Source: https://developer.surecart.com/api-reference/shipping-fees/delete /openapi/v1/orders.json delete /v1/shipping_fees/{id} Deletes a specific shipping fee. # List Source: https://developer.surecart.com/api-reference/shipping-fees/list /openapi/v1/orders.json get /v1/shipping_fees Returns a list of your shipping fees. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-fees/retrieve /openapi/v1/orders.json get /v1/shipping_fees/{id} Retrieves details of a specific shipping fee. # Update Source: https://developer.surecart.com/api-reference/shipping-fees/update /openapi/v1/orders.json patch /v1/shipping_fees/{id} Updates a specific shipping fee. # Create Source: https://developer.surecart.com/api-reference/shipping-methods/create /openapi/v1/shipping.json post /v1/shipping_methods Creates a new shipping method. # List Source: https://developer.surecart.com/api-reference/shipping-methods/list /openapi/v1/shipping.json get /v1/shipping_methods Returns a list of your shipping methods. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-methods/retrieve /openapi/v1/shipping.json get /v1/shipping_methods/{id} Retrieves details of a specific shipping method. # Update Source: https://developer.surecart.com/api-reference/shipping-methods/update /openapi/v1/shipping.json patch /v1/shipping_methods/{id} Updates a specific shipping method. # Create Source: https://developer.surecart.com/api-reference/shipping-profiles/create /openapi/v1/shipping.json post /v1/shipping_profiles Creates a new shipping profile. # Delete Source: https://developer.surecart.com/api-reference/shipping-profiles/delete /openapi/v1/shipping.json delete /v1/shipping_profiles/{id} Deletes a specific shipping profile. # List Source: https://developer.surecart.com/api-reference/shipping-profiles/list /openapi/v1/shipping.json get /v1/shipping_profiles Returns a list of your shipping profiles. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-profiles/retrieve /openapi/v1/shipping.json get /v1/shipping_profiles/{id} Retrieves details of a specific shipping profile. # Update Source: https://developer.surecart.com/api-reference/shipping-profiles/update /openapi/v1/shipping.json patch /v1/shipping_profiles/{id} Updates a specific shipping profile. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-protocols/retrieve /openapi/v1/shipping.json get /v1/shipping_protocol Retrieves details of the current account's shipping protocol. # Update Source: https://developer.surecart.com/api-reference/shipping-protocols/update /openapi/v1/shipping.json patch /v1/shipping_protocol Updates the current account's shipping protocol. # List Source: https://developer.surecart.com/api-reference/shipping-providers/list /openapi/v1/shipping.json get /v1/shipping_providers Returns a list of your shipping providers. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-providers/retrieve /openapi/v1/shipping.json get /v1/shipping_providers/{id} Retrieves details of a specific shipping provider. # Create Source: https://developer.surecart.com/api-reference/shipping-rates/create /openapi/v1/shipping.json post /v1/shipping_rates Creates a new shipping rate. # Delete Source: https://developer.surecart.com/api-reference/shipping-rates/delete /openapi/v1/shipping.json delete /v1/shipping_rates/{id} Deletes a specific shipping rate. # List Source: https://developer.surecart.com/api-reference/shipping-rates/list /openapi/v1/shipping.json get /v1/shipping_rates Returns a list of your shipping rates. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-rates/retrieve /openapi/v1/shipping.json get /v1/shipping_rates/{id} Retrieves details of a specific shipping rate. # Update Source: https://developer.surecart.com/api-reference/shipping-rates/update /openapi/v1/shipping.json patch /v1/shipping_rates/{id} Updates a specific shipping rate. # Create Source: https://developer.surecart.com/api-reference/shipping-zones/create /openapi/v1/shipping.json post /v1/shipping_zones Creates a new shipping zone. # Delete Source: https://developer.surecart.com/api-reference/shipping-zones/delete /openapi/v1/shipping.json delete /v1/shipping_zones/{id} Deletes a specific shipping zone. # List Source: https://developer.surecart.com/api-reference/shipping-zones/list /openapi/v1/shipping.json get /v1/shipping_zones Returns a list of your shipping zones. # Retrieve Source: https://developer.surecart.com/api-reference/shipping-zones/retrieve /openapi/v1/shipping.json get /v1/shipping_zones/{id} Retrieves details of a specific shipping zone. # Update Source: https://developer.surecart.com/api-reference/shipping-zones/update /openapi/v1/shipping.json patch /v1/shipping_zones/{id} Updates a specific shipping zone. # Orders Source: https://developer.surecart.com/api-reference/statistics/orders /openapi/v1/core.json get /v1/stats/orders Returns order statistics. # Retrieve Source: https://developer.surecart.com/api-reference/subscription-protocols/retrieve /openapi/v1/subscriptions.json get /v1/subscription_protocol Retrieves details of the current account's subscription protocol. # Update Source: https://developer.surecart.com/api-reference/subscription-protocols/update /openapi/v1/subscriptions.json patch /v1/subscription_protocol Updates the current account's subscription protocol. # Cancel/Pause Source: https://developer.surecart.com/api-reference/subscriptions/cancelpause /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/cancel Cancels a specific subscription. If a `restore_at` value is provided, the subscription will be effectively "paused" until that date when it will automatically renew. # Complete Source: https://developer.surecart.com/api-reference/subscriptions/complete /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/complete Completes a specific subscription. # Create Source: https://developer.surecart.com/api-reference/subscriptions/create /openapi/v1/subscriptions.json post /v1/subscriptions Creates a new subscription. # Filter Source: https://developer.surecart.com/api-reference/subscriptions/filter /openapi/v1/subscriptions.json post /v1/subscriptions/filter Returns a list of subscriptions matching the supplied rule tree. # Filter Schema Source: https://developer.surecart.com/api-reference/subscriptions/filter-schema /openapi/v1/subscriptions.json get /v1/subscriptions/filter_schema Retrieves the filter schema for subscriptions. # List Source: https://developer.surecart.com/api-reference/subscriptions/list /openapi/v1/subscriptions.json get /v1/subscriptions Returns a list of your subscriptions. # Pay Off Source: https://developer.surecart.com/api-reference/subscriptions/pay-off /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/pay_off Pays off all remaining periods for a specific subscription. # Preserve Source: https://developer.surecart.com/api-reference/subscriptions/preserve /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/preserve Preserves a specific subscription. # Restore Source: https://developer.surecart.com/api-reference/subscriptions/restore /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/restore Restores a specific subscription. # Retrieve Source: https://developer.surecart.com/api-reference/subscriptions/retrieve /openapi/v1/subscriptions.json get /v1/subscriptions/{id} Retrieves details of a specific subscription. # Upcoming Period Source: https://developer.surecart.com/api-reference/subscriptions/upcoming-period /openapi/v1/subscriptions.json patch /v1/subscriptions/{id}/upcoming_period Generates a preview of the upcoming period. # Update Source: https://developer.surecart.com/api-reference/subscriptions/update /openapi/v1/subscriptions.json patch /v1/subscriptions/{id} Updates a specific subscription. # Create Source: https://developer.surecart.com/api-reference/swaps/create /openapi/v1/products.json post /v1/swaps Creates a new swap. # Delete Source: https://developer.surecart.com/api-reference/swaps/delete /openapi/v1/products.json delete /v1/swaps/{id} Deletes a specific swap. # List Source: https://developer.surecart.com/api-reference/swaps/list /openapi/v1/products.json get /v1/swaps Returns a list of your swaps. # Retrieve Source: https://developer.surecart.com/api-reference/swaps/retrieve /openapi/v1/products.json get /v1/swaps/{id} Retrieves details of a specific swap. # Update Source: https://developer.surecart.com/api-reference/swaps/update /openapi/v1/products.json patch /v1/swaps/{id} Updates a specific swap. # Create Source: https://developer.surecart.com/api-reference/tax-overrides/create /openapi/v1/tax.json post /v1/tax_overrides Creates a new tax override. # Delete Source: https://developer.surecart.com/api-reference/tax-overrides/delete /openapi/v1/tax.json delete /v1/tax_overrides/{id} Deletes a specific tax override. # List Source: https://developer.surecart.com/api-reference/tax-overrides/list /openapi/v1/tax.json get /v1/tax_overrides Returns a list of your tax overrides. # Retrieve Source: https://developer.surecart.com/api-reference/tax-overrides/retrieve /openapi/v1/tax.json get /v1/tax_overrides/{id} Retrieves details of a specific tax override. # Update Source: https://developer.surecart.com/api-reference/tax-overrides/update /openapi/v1/tax.json patch /v1/tax_overrides/{id} Updates a specific tax override. # Retrieve Source: https://developer.surecart.com/api-reference/tax-protocols/retrieve /openapi/v1/tax.json get /v1/tax_protocol Retrieves details of the current account's tax protocol. # Update Source: https://developer.surecart.com/api-reference/tax-protocols/update /openapi/v1/tax.json patch /v1/tax_protocol Updates the current account's tax protocol. # Create Source: https://developer.surecart.com/api-reference/tax-registrations/create /openapi/v1/tax.json post /v1/tax_registrations Creates a new tax registration. # Delete Source: https://developer.surecart.com/api-reference/tax-registrations/delete /openapi/v1/tax.json delete /v1/tax_registrations/{id} Deletes a specific tax registration. # List Source: https://developer.surecart.com/api-reference/tax-registrations/list /openapi/v1/tax.json get /v1/tax_registrations Returns a list of your tax registrations. # Retrieve Source: https://developer.surecart.com/api-reference/tax-registrations/retrieve /openapi/v1/tax.json get /v1/tax_registrations/{id} Retrieves details of a specific tax registration. # Update Source: https://developer.surecart.com/api-reference/tax-registrations/update /openapi/v1/tax.json patch /v1/tax_registrations/{id} Updates a specific tax registration. # List Source: https://developer.surecart.com/api-reference/tax-zones/list /openapi/v1/tax.json get /v1/tax_zones Returns a list of all available tax zones. # List Source: https://developer.surecart.com/api-reference/trackings/list /openapi/v1/shipping.json get /v1/trackings Returns a list of your trackings. # Retrieve Source: https://developer.surecart.com/api-reference/trackings/retrieve /openapi/v1/shipping.json get /v1/trackings/{id} Retrieves details of a specific tracking. # Create Source: https://developer.surecart.com/api-reference/upsell-funnels/create /openapi/v1/products.json post /v1/upsell_funnels Creates a new upsell funnel. # Delete Source: https://developer.surecart.com/api-reference/upsell-funnels/delete /openapi/v1/products.json delete /v1/upsell_funnels/{id} Deletes a specific upsell funnel. # Duplicate Source: https://developer.surecart.com/api-reference/upsell-funnels/duplicate /openapi/v1/products.json post /v1/upsell_funnels/{id}/duplicate Duplicates a specific upsell funnel. # List Source: https://developer.surecart.com/api-reference/upsell-funnels/list /openapi/v1/products.json get /v1/upsell_funnels Returns a list of your upsell funnels. # Retrieve Source: https://developer.surecart.com/api-reference/upsell-funnels/retrieve /openapi/v1/products.json get /v1/upsell_funnels/{id} Retrieves details of a specific upsell funnel. # Update Source: https://developer.surecart.com/api-reference/upsell-funnels/update /openapi/v1/products.json patch /v1/upsell_funnels/{id} Updates a specific upsell funnel. # Create Source: https://developer.surecart.com/api-reference/upsells/create /openapi/v1/products.json post /v1/upsells Creates a new upsell. # Delete Source: https://developer.surecart.com/api-reference/upsells/delete /openapi/v1/products.json delete /v1/upsells/{id} Deletes a specific upsell. # List Source: https://developer.surecart.com/api-reference/upsells/list /openapi/v1/products.json get /v1/upsells Returns a list of your upsells. # Retrieve Source: https://developer.surecart.com/api-reference/upsells/retrieve /openapi/v1/products.json get /v1/upsells/{id} Retrieves details of a specific upsell. # Update Source: https://developer.surecart.com/api-reference/upsells/update /openapi/v1/products.json patch /v1/upsells/{id} Updates a specific upsell. # List Source: https://developer.surecart.com/api-reference/variant-options/list /openapi/v1/products.json get /v1/variant_options Returns a list of your variant options. # Retrieve Source: https://developer.surecart.com/api-reference/variant-options/retrieve /openapi/v1/products.json get /v1/variant_options/{id} Retrieves details of a specific variant option. # Create Source: https://developer.surecart.com/api-reference/variants/create /openapi/v1/products.json post /v1/variants Creates a new variant. # Delete Source: https://developer.surecart.com/api-reference/variants/delete /openapi/v1/products.json delete /v1/variants/{id} Deletes a specific variant. # List Source: https://developer.surecart.com/api-reference/variants/list /openapi/v1/products.json get /v1/variants Returns a list of your variants. # Retrieve Source: https://developer.surecart.com/api-reference/variants/retrieve /openapi/v1/products.json get /v1/variants/{id} Retrieves details of a specific variant. # Update Source: https://developer.surecart.com/api-reference/variants/update /openapi/v1/products.json patch /v1/variants/{id} Updates a specific variant. # Create Source: https://developer.surecart.com/api-reference/verification-codes/create /openapi/v1/customers.json post /v1/verification_codes Creates a new verification code. # Verify Source: https://developer.surecart.com/api-reference/verification-codes/verify /openapi/v1/customers.json post /v1/verification_codes/verify Verifies a verification code. # Create Source: https://developer.surecart.com/api-reference/warehouses/create /openapi/v1/shipping.json post /v1/warehouses Creates a new warehouse. # Delete Source: https://developer.surecart.com/api-reference/warehouses/delete /openapi/v1/shipping.json delete /v1/warehouses/{id} Deletes a specific warehouse. # List Source: https://developer.surecart.com/api-reference/warehouses/list /openapi/v1/shipping.json get /v1/warehouses Returns a list of your warehouses. # Retrieve Source: https://developer.surecart.com/api-reference/warehouses/retrieve /openapi/v1/shipping.json get /v1/warehouses/{id} Retrieves details of a specific warehouse. # Update Source: https://developer.surecart.com/api-reference/warehouses/update /openapi/v1/shipping.json patch /v1/warehouses/{id} Updates a specific warehouse. # Create Source: https://developer.surecart.com/api-reference/webhook-endpoints/create /openapi/v1/core.json post /v1/webhook_endpoints Creates a new webhook endpoint. If a webhook endpoint already exists with the same `url` then it will be updated and returned. # Delete Source: https://developer.surecart.com/api-reference/webhook-endpoints/delete /openapi/v1/core.json delete /v1/webhook_endpoints/{id} Deletes a specific webhook endpoint. # List Source: https://developer.surecart.com/api-reference/webhook-endpoints/list /openapi/v1/core.json get /v1/webhook_endpoints Returns a list of your webhook endpoints. # Retrieve Source: https://developer.surecart.com/api-reference/webhook-endpoints/retrieve /openapi/v1/core.json get /v1/webhook_endpoints/{id} Retrieves details of a specific webhook endpoint. # Test Source: https://developer.surecart.com/api-reference/webhook-endpoints/test /openapi/v1/core.json post /v1/webhook_endpoints/{id}/test Sends a test webhook for the specific webhook endpoint. # Update Source: https://developer.surecart.com/api-reference/webhook-endpoints/update /openapi/v1/core.json patch /v1/webhook_endpoints/{id} Updates a specific webhook endpoint. # Webhooks Source: https://developer.surecart.com/api-reference/webhooks SureCart uses webhooks to notify your application when an event happens in your account. Webhooks are particularly useful for asynchronous events like when a subscription is updated or a charge is refunded. You can create and manage your webhook endpoints through the API endpoints or within your dashboard. From your dashboard you can also see a log of recent events that have been sent. ### Events Webhooks are triggered based on events. Events are our way of letting you know when something interesting happens in your account. When an interesting event occurs, we create a new `Event` object. For example, when an order is created, we create a `order.created` event. The request payload of each webhook will contain the `Event` object, which is structured like the following example. ```json theme={null} { "id": "5bafe7b7-a4e3-4a7d-85e9-d8b512094b67", "object": "event", "data": { "object": { "id": "0d6edf76-98f3-441c-9c43-81a92e929988", "object": "order", "live_mode": true, "number": "0008", "order_type": "checkout", "statement_url": "https://app.surecart.com/statements/orders/0d6edf76-98f3-441c-9c43-81a92e929988", "status": "paid", "checkout": "f1a38ad4-f87d-4550-b2e0-91a128cadf06", "created_at": 1664479758, "updated_at": 1664479758 } }, "type": "order.created", "account": "b7cfbc09-371a-453e-ab29-2edf63de0dbe", "created_at": 1664479758 } ``` When listeneing for webhooks at your webhook endpoint you will want to look at the `event.type` value to determine what type of event your endpoint has received. For example, the above webhook is a `order.created` event. ### Types of Events This is a list of all the types of events we currently send. We may add more at any time, so in developing and maintaining your code, you should not assume that only these types exist. You'll notice that these events follow a pattern: `resource.event`. Our goal is to design a consistent system that makes things easier to anticipate and code against. #### Abandoned Checkouts * `abandoned_checkout.created` - Occurs when an abandoned checkout is created * `abandoned_checkout.recovered` - Occurs when an abandoned checkout is recovered #### Accounts * `account.updated` - Occurs when a account is updated #### Activations * `activation.created` - Occurs when a license activation is created * `activation.deleted` - Occurs when a license activation is deleted * `activation.updated` - Occurs when a license activation is updated ### Affiliations * `affiliation.activated` - Occurs when a affiliation is activated * `affiliation.deactivated` - Occurs when a affiliation is deactivated * `affiliation.deleted` - Occurs when a affiliation is deleted #### Affiliation Requests * `affiliation_request.approved` - Occurs when a affiliation request's status changes to `approved` * `affiliation_request.created` - Occurs when a affiliation request is created * `affiliation_request.denied` - Occurs when a affiliation status changes to `denied` * `affiliation_request.updated` - Occurs when a affiliation request is updated #### Bumps * `bump_offer.accepted` - Occurs when a bump is accepted #### Cancellation Acts * `cancellation_act.created` - Occurs when a cancellation act is created * `cancellation_act.updated` - Occurs when a cancellation act is updated #### Customers * `customer.created` - Occurs when a customer is created * `customer.updated` - Occurs when a customer is updated #### Fulfillments * `fulfillment.created` - Occurs when a fulfillment is created * `fulfillment.deleted` - Occurs when a fulfillment is deleted * `fulfillment.updated` - Occurs when a fulfillment is updated #### Invoices * `invoice.created` - Occurs when an invoice is created * `invoice.deleted` - Occurs when an invoice is deleted * `invoice.updated` - Occurs when an invoice is updated * `invoice.made_draft` - Occurs when an invoice's status changes to `draft` * `invoice.opened` - Occurs when an invoice's status changes to `open` * `invoice.paid` - Occurs when an invoice's status changes to `paid` #### Orders * `order.created` - Occurs when an order is created * `order.delivered` - Occurs when an order's shipment status changes to `delivered` * `order.fulfilled` - Occurs when an order's fulfillment status changes to `fulfilled` * `order.made_processing` - Occurs when an order's status changes to `processing` * `order.paid` - Occurs when an order's status changes to `paid` * `order.partially_fulfilled` - Occurs when an order's fulfillment status changes to `partially_fulfilled` * `order.partially_shipped` - Occurs when an order's shipment status changes to `partially_shipped` * `order.payment_failed` - Occurs when an order's status changes to `payment_failed` * `order.shipped` - Occurs when an order's shipment status changes to `shipped` * `order.unfulfilled` -Occurs when an order's fulfillment status changes to `unfulfilled` * `order.unshipped` - Occurs when an order's shipment status changes to `unshipped` * `order.voided` - Occurs when an order's status changes to `void` #### Payout Groups * `payout_group.created` - Occurs when a payout group is created #### Payouts * `payout.created` - Occurs when a payout is created * `payout.completed` - Occurs when a payout's status changes to `completed` * `payout.made_processing` - Occurs when a payout's status changes to `processing` #### Prices * `price.created` - Occurs when a price is created * `price.deleted` - Occurs when a price is deleted * `price.updated` - Occurs when a price is updated #### Products * `product.created` - Occurs when a product is created * `product.deleted` - Occurs when a product is deleted * `product.stock_adjusted` - Occurs when the `stock` amount for a product is adjusted by an order, return, etc. * `product.updated` - Occurs when a product is updated * `variant.stock_adjusted` - Occurs when the `stock` amount for a product's variant is adjusted by an order, return, etc. (If a product has variants this webhook will be sent instead of `product.stock_adjusted`.) #### Purchases * `purchase.created` - Occurs when a purchase is created * `purchase.invoked` - Occurs when a purchase is invoked * `purchase.revoked` - Occurs when a purchase is revoked * `purchase.updated` - Occurs when a purchase is updated #### Referrals * `referral.approved`- Occurs when a referral's status changes to `approved` * `referral.canceled`- Occurs when a referral's status changes to `canceled` * `referral.created`- Occurs when a referral is created * `referral.denied`- Occurs when a referral's status changes to `denied` * `referral.made_reviewing`- Occurs when a referral's status changes to `reviewing` * `referral.updated`- Occurs when a referral is updated #### Refunds * `refund.created` - Occurs when a refund is created * `refund.succeeded` - Occurs when a refund's status changes to `succeeded` #### Return Requests * `return_request.completed` - Occurs when a return request's status changes to `completed` * `return_request.created` - Occurs when a return request is created * `return_request.deleted` - Occurs when a return request is deleted * `return_request.opened` - Occurs when a return request's status changes to `open` * `return_request.updated` - Occurs when a return request is updated #### Subscriptions * `subscription.canceled` - Occurs when a subscription's status changes to `canceled` * `subscription.created` - Occurs when a subscription is created * `subscription.completed` - Occurs when a subscription's status changes to `completed` * `subscription.made_active` - Occurs when a subscription's status changes to `active` * `subscription.made_trialing` - Occurs when a subscription's status changes to `trialing` * `subscription.renewal_reminder_sent` - Occurs when a subscription's renewal reminder is sent * `subscription.renewed` - Occurs when a subscription renews * `subscription.set_to_cancel` - Occurs when a subscription is set to cancel at the end of the current billing period * `subscription.updated` - Occurs when a subscription is updated #### Upsells * `upsell_offer.accepted` - Occurs when a upsell is accepted * `upsell_offer.declined` - Occurs when a upsell is declined ### Webhook Delivery Timeouts SureCart expects webhook endpoints to acknowledge receipt of an event within **approximately 10 seconds**. If a response is not received within this time window, the delivery attempt is considered failed and will be retried based on our retry strategy. To ensure successful processing: * Your endpoint should return a `2xx` HTTP status code as quickly as possible. * Perform all time-consuming logic (e.g., database updates, third-party API calls) asynchronously in the background. * Avoid long-running synchronous operations that could cause the request to time out. Proper timeout handling helps ensure reliable event delivery and minimizes duplicate webhook attempts caused by delays. ### Expanding Webhook Events All webhooks contain the parent resource of the corresponding event and do not expand any related objects. This keeps webhook payloads small and ensures unecessary data is not being sent. If you wish to expand a resource you will need to make a subsequent retrieve request with the expansions you need. [See the Expanding Responses documentation for more detail.](https://developer.surecart.com/reference/expanding-responses) ### Webhook Signatures All webhooks include a signature in each request’s `x-webhook-signature` header. This allows you to verify that the events were sent by us, and not by a third party. We generate signatures using a hash-based message authentication code (HMAC) with SHA-256. We generate a unique signing secret key for each endpoint. If you use multiple endpoints, you must use the unique signing secret for each one you want to verify signatures on. You can view the signing secret for each endpoint from within your dashboard, or you can retrive it from the API. ### Preventing Replay Attacks A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To mitigate such attacks, we include a timestamp in the `x-webhook-timestamp` header. This timestamp is also part of the signed payload and verified by the signature, so an attacker cannot change the timestamp without invalidating the signature. If the signature is valid but the timestamp is too old, you can have your application reject the payload. We generate the timestamp and signature each time we send an event to your endpoint. If we retry an event (for example, your endpoint previously replied with a non-2xx status code), then we generate a new signature and timestamp for the new delivery attempt. ### Verify Signatures **Step 1: Extract Signature and Timestamp**\ The `signature` is sent in the `x-webhook-signature` header, and the `timestamp` is sent in the `x-webhook-timestamp` header. ``` x-webhook-signature = "287ace7f0267943970dca9e895be11a739b532b85dfed8a3d147ca2d08267f48" x-webhook-timestamp = "1641873601" ``` **Step 2: Prepare Signed Payload String**\ The signed\_payload string is created by concatenating the timestamp and the payload with the . character. **Step 3: Determine Expected Signature**\ Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed\_payload string as the message. **Step 4: Compare Signatures**\ Compare the signature in the header to the expected signature. ### Event Ordering SureCart does not guarantee that webhook events will be delivered in the exact order they were triggered. For example, when a customer completes a checkout, the following events might be sent: ``` order.created purchase.created subscription.created ``` While these events are generated in a specific sequence, they may arrive at your webhook endpoint out of order due to network latency or retries. Your webhook handler should not rely on receiving events in a strict sequence. Instead, it should be designed to handle events independently and idempotently. If necessary, use the SureCart API to retrieve related objects (such as an order, purchase, or subscription) when processing an event. This ensures that your integration remains consistent even when events arrive asynchronously or out of order. ### Handling Duplicate Events Webhook endpoints may occasionally receive the same event more than once. This can happen due to retries or network-related issues. To prevent processing duplicates, we recommend storing the unique id of each received event. Before acting on a new event, check if its ID has already been handled. In some cases, two distinct webhook events may reference the same underlying object. To identify true duplicates, compare both the `event -> type` and the `event -> data -> object -> id` fields. This helps ensure your system processes each meaningful event only once. ### Subscribe Only to Relevant Events To improve performance and reduce unnecessary load on your webhook endpoint, configure it to listen only to the events your integration actually needs. Subscribing to all available events increases overhead and may lead to unnecessary processing. You can configure which events your webhook receives directly from the SureCart Dashboard # Admin Source: https://developer.surecart.com/documentation/actions-filters/admin Customize admin menus, toolbars, and list tables These filters allow you to customize the WordPress admin experience for SureCart. ## Menu Filters ### `surecart_menu_priority` Filter the admin menu position. Lower numbers appear higher in the menu. ```php theme={null} add_filter( 'surecart_menu_priority', function( $priority ) { return 5; // Move menu higher (closer to Dashboard) } ); // Or move it lower add_filter( 'surecart_menu_priority', function( $priority ) { return 80; // Move below Settings } ); ``` ## Admin Bar Filters ### `surecart_show_admin_bar_visit_store` Control whether "Visit Store" appears in the admin bar. ```php theme={null} add_filter( 'surecart_show_admin_bar_visit_store', '__return_false' ); // Or show only for specific roles add_filter( 'surecart_show_admin_bar_visit_store', function( $show ) { return current_user_can( 'manage_options' ); } ); ``` ### `surecart_show_admin_bar_new_content` Control whether "New" content menu appears in admin bar. ```php theme={null} add_filter( 'surecart_show_admin_bar_new_content', '__return_false' ); ``` ### `surecart/help_widget/show` Control when the help widget is shown. ```php theme={null} add_filter( 'surecart/help_widget/show', function( $show ) { // Hide for non-admins return current_user_can( 'manage_options' ); } ); // Or always hide add_filter( 'surecart/help_widget/show', '__return_false' ); ``` ### `surecart/help_widget/loaded` Fired when the help widget is loaded in the admin. Use this to inject custom scripts or modify widget behavior. ```php theme={null} add_action( 'surecart/help_widget/loaded', function() { // Add custom help resources or modify widget behavior ?> Hook into admin and template actions. Modify API requests and responses. # Cart Source: https://developer.surecart.com/documentation/actions-filters/cart Customize cart icon, visibility, and behavior These filters allow you to customize the cart experience. ## `sc_cart_menu_icon` Filter the cart menu icon. The icon name/identifier. The icon type or position context. ```php theme={null} add_filter( 'sc_cart_menu_icon', function( $icon, $type ) { return 'shopping-bag'; // Use a different icon }, 10, 2 ); ``` ## `sc_cart_disabled` Disable the cart functionality entirely on specific pages or conditions. ```php theme={null} add_filter( 'sc_cart_disabled', function( $disabled ) { // Disable cart on specific pages if ( is_page( 'landing-page' ) ) { return true; } return $disabled; } ); // Or disable during maintenance add_filter( 'sc_cart_disabled', function( $disabled ) { if ( get_option( 'maintenance_mode' ) ) { return true; } return $disabled; } ); ``` ## Use Cases ### Hide Cart on Landing Pages ```php theme={null} add_filter( 'sc_cart_disabled', function( $disabled ) { // Hide cart on specific landing pages $landing_pages = [ 'promo', 'special-offer', 'webinar' ]; foreach ( $landing_pages as $slug ) { if ( is_page( $slug ) ) { return true; } } return $disabled; } ); ``` ### Disable Cart for Logged-Out Users ```php theme={null} add_filter( 'sc_cart_disabled', function( $disabled ) { // Only show cart to logged-in users return ! is_user_logged_in(); } ); ``` ## Modifying Templates You can customize the HTML output of SureCart blocks using WordPress's `render_block` filter and the HTML Tag Processor. Learn how to modify block HTML, add custom attributes, wrap content, and inject elements into templates. ## Related Customize checkout validation and behavior. Modify how content is displayed. # Checkout Source: https://developer.surecart.com/documentation/actions-filters/checkout Hook into checkout events and customize validation These hooks allow you to respond to checkout events and customize the checkout experience. ## Actions Actions are triggered during the checkout process and when orders are confirmed. This is at the end, after payment is successuflly confirmed by the processor. ### `surecart/checkout_confirmed` Fired after an order is confirmed and all purchases have been processed. Use this for post-checkout operations like analytics tracking, external notifications, or custom logging. The checkout model object containing order details. The REST API request object. ```php theme={null} add_action( 'surecart/checkout_confirmed', function( $checkout, $request ) { // Fetch the checkout with customer relation loaded. $checkout = \SureCart\Models\Checkout::with(['customer'])->find( $checkout->id ); // Access order details $order_id = $checkout->id; $total = $checkout->total_amount; // Track conversion if ( function_exists( 'track_conversion' ) ) { track_conversion( $order_id, $total ); } // Send to external system wp_remote_post( 'https://api.example.com/orders', [ 'body' => [ 'order_id' => $order_id, 'total' => $total, 'customer_email' => $checkout->customer->email, ] ]); }, 10, 2 ); ``` ## Filters ### Form Validation These filters run during the finalize step of checkout, before the order is submitted. Use them to validate form data and prevent checkout if validation fails. #### `surecart/checkout/validate` Add custom server-side validation to checkout forms. This filter runs during the finalize step, after client-side validation passes but before the order is submitted to the payment processor. Error object to add validation errors to. Add errors using `$errors->add( $code, $message )`. All checkout form data including `email`, `name`, `billing_address`, `shipping_address`, `metadata`, `line_items`, and custom fields. The REST API request object. Use `$request->get_param( 'key' )` to access specific parameters. ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { // Require a custom field if ( empty( $args['metadata']['company_name'] ) ) { $errors->add( 'company_required', 'Company name is required.' ); } return $errors; }, 10, 3 ); ``` ##### Validate Email Domain Block specific email domains from purchasing: ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $blocked_domains = [ 'tempmail.com', 'throwaway.com', 'mailinator.com' ]; $email = $args['email'] ?? ''; $domain = substr( strrchr( $email, '@' ), 1 ); if ( in_array( $domain, $blocked_domains, true ) ) { $errors->add( 'blocked_email', 'Please use a valid email address. Temporary email addresses are not allowed.' ); } return $errors; }, 10, 3 ); ``` ##### Validate Custom Fields Validate custom form fields added to your checkout: ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { // Get custom fields from metadata $metadata = $args['metadata'] ?? []; // Validate age requirement if ( isset( $metadata['your_age'] ) ) { if ( $metadata['your_age'] < 18 ) { $errors->add( 'age_restriction', 'You must be 18 or older to purchase.' ); } } return $errors; }, 10, 3 ); ``` ##### Validate Based on Form ID Apply validation only to specific checkout forms: ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $form_id = $request->get_param( 'form_id' ); // Only validate on specific form if ( $form_id !== 123 ) { return $errors; } // Form-specific validation if ( empty( $args['metadata']['license_number'] ) ) { $errors->add( 'license_required', 'Professional license number is required.' ); } return $errors; }, 10, 3 ); ``` ### User Creation #### `surecart/checkout/auto-login-new-user` Control whether newly created users are automatically logged in after checkout. ```php theme={null} // Disable auto-login for new users add_filter( 'surecart/checkout/auto-login-new-user', '__return_false' ); ``` ### Display #### `surecart_checkout_show_converted_total` Control whether converted currency totals are shown when using currency conversion. ```php theme={null} add_filter( 'surecart_checkout_show_converted_total', function( $show, $checkout ) { // Don't show converted total for small orders if ( $checkout->total_amount < 1000 ) { // Less than $10 return false; } return $show; }, 10, 2 ); ``` #### `sc_checkout_price_selector_first_price_as_default` Control whether the first price is selected by default in price selectors. ```php theme={null} add_filter( 'sc_checkout_price_selector_first_price_as_default', '__return_false' ); ``` ### Payment Mode #### `surecart/payments/mode` Filter the payment mode (live/test). Useful for testing or staging environments. ```php theme={null} add_filter( 'surecart/payments/mode', function( $mode ) { // Force test mode for admins if ( current_user_can( 'manage_options' ) ) { return 'test'; } return $mode; } ); // Or force test mode on staging add_filter( 'surecart/payments/mode', function( $mode ) { if ( wp_get_environment_type() === 'staging' ) { return 'test'; } return $mode; } ); ``` ## JavaScript Filters SureCart provides JavaScript filters using the WordPress hooks system (`wp.hooks`) to customize the Stripe Payment Element. These filters allow you to modify payment method order, wallet visibility, legal terms display, and billing fields. These filters use the [@wordpress/hooks](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-hooks/) package, which is automatically available on pages with SureCart checkout. ### Payment Method Order Use `surecart_stripe_payment_element_payment_method_order` to reorder the payment methods displayed in Stripe's Payment Element. ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_payment_method_order", "my-customization", (paymentMethodOrder, checkout) => { // Return an array of payment method types in your preferred order return ["card", "us_bank_account", "klarna"]; } ); ``` See the [Stripe Payment Element documentation](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-business) for available payment method types. ### Wallet Visibility Use `surecart_stripe_payment_element_wallets` to control the visibility of digital wallets like Apple Pay, Google Pay, and Link within the Payment Element. ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_wallets", "my-customization", (wallets, checkout) => { return { applePay: "auto", // 'auto' | 'never' googlePay: "auto", // 'auto' | 'never' link: "never", // 'auto' | 'never' }; } ); ``` See the [Stripe wallets documentation](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-wallets) for more options. ### Legal Terms Display Use `surecart_stripe_payment_element_terms` to manage the display of mandates and other legal agreements within the Payment Element. By default, these are shown only when necessary. ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_terms", "my-customization", (terms, checkout) => { return { card: "never", // Hide card terms usBankAccount: "always", // Always show bank account terms }; } ); ``` See the [Stripe terms documentation](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-terms) for available options. ### Billing Fields Use `surecart_stripe_payment_element_fields` to control which billing address fields are displayed within the Stripe Payment Element. This is useful when you're already collecting billing information elsewhere in your checkout form. ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_fields", "my-customization", (fields) => { return { billingDetails: { name: "never", email: "never", address: { line1: "never", line2: "never", city: "never", state: "never", postalCode: "never", country: "never", }, }, }; } ); ``` To show specific fields, simply remove them from the object or set them to `'auto'`. For example, to hide all fields except country: ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_fields", "my-customization", (fields) => { return { billingDetails: { address: { line1: "never", line2: "never", city: "never", state: "never", postalCode: "never", // country is not set, so it will display }, }, }; } ); ``` See the [Stripe fields documentation](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-fields) for all available options. ### Address Countries Use `surecart_address_countries` to customize the list of countries available in address fields. You can add, remove, reorder, or translate country names. To add custom JavaScript filters to your site, you can use plugins like [Simple Custom CSS and JS](https://wordpress.org/plugins/custom-css-js/). Be sure to load scripts in the footer for checkout page compatibility. ```javascript theme={null} wp.hooks.addFilter( "surecart_address_countries", "my-customization", (countries) => { // Return only specific countries return [ { value: "US", label: "United States" }, { value: "CA", label: "Canada" }, { value: "GB", label: "United Kingdom" }, ]; } ); ``` Each country object must include both `value` (ISO country code) and `label` (display name) properties. ### Address Regions Use `surecart_address_regions` to customize the regions (states, provinces, etc.) available for specific countries. You can add, remove, or translate region names. ```javascript theme={null} wp.hooks.addFilter( "surecart_address_regions", "my-customization", (regions, country) => { // Add custom regions for Taiwan if (country === "TW") { regions.push( { value: "test-region-one", label: "Test Region 1" }, { value: "test-region-two", label: "Test Region 2" } ); } return regions; } ); ``` The filter receives the current `regions` array and the `country` code. Each region object must include both `value` and `label` properties. ## Use Cases ### Analytics & Conversion Tracking ```php theme={null} add_action( 'surecart/checkout_confirmed', function( $checkout, $request ) { // Fetch the checkout with customer relation loaded. $checkout = \SureCart\Models\Checkout::with(['customer'])->find( $checkout->id ); // Google Analytics 4 - Server-side tracking $measurement_id = 'G-XXXXXXXXXX'; $api_secret = 'your-api-secret'; wp_remote_post( "https://www.google-analytics.com/mp/collect?measurement_id={$measurement_id}&api_secret={$api_secret}", [ 'body' => json_encode([ 'client_id' => $checkout->customer->id, 'events' => [[ 'name' => 'purchase', 'params' => [ 'transaction_id' => $checkout->id, 'value' => $checkout->total_amount / 100, 'currency' => $checkout->currency, ] ]] ]) ]); }, 10, 2 ); ``` ### Send to Slack ```php theme={null} add_action( 'surecart/checkout_confirmed', function( $checkout, $request ) { // Fetch the checkout with customer relation loaded. $checkout = \SureCart\Models\Checkout::with(['customer'])->find( $checkout->id ); $webhook_url = 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'; wp_remote_post( $webhook_url, [ 'body' => json_encode([ 'text' => sprintf( '🎉 New order! %s just purchased for %s', $checkout->customer->email, sc_format_amount( $checkout->total_amount, $checkout->currency ) ) ]), 'headers' => [ 'Content-Type' => 'application/json' ] ]); }, 10, 2 ); ``` ### Validate Minimum Order Amount ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $checkout = $request->get_param( 'checkout' ); if ( isset( $checkout['total_amount'] ) && $checkout['total_amount'] < 500 ) { $errors->add( 'minimum_order', 'Minimum order amount is $5.00.' ); } return $errors; }, 10, 3 ); ``` ### Restrict Purchases by Country ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $blocked_countries = [ 'XX', 'YY' ]; // Country codes to block $billing_address = $args['billing_address'] ?? []; $country = $billing_address['country'] ?? ''; if ( in_array( $country, $blocked_countries, true ) ) { $errors->add( 'country_blocked', 'Sorry, we cannot ship to your country.' ); } return $errors; }, 10, 3 ); ``` ### Require Terms Acceptance ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $metadata = $args['metadata'] ?? []; if ( empty( $metadata['accept_terms'] ) || $metadata['accept_terms'] !== 'yes' ) { $errors->add( 'terms_required', 'You must accept the terms and conditions to continue.' ); } return $errors; }, 10, 3 ); ``` ### Validate Tax Identifier Use the built-in `tax_identifier` field to validate VAT/tax ID numbers: ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { $tax_identifier = $args['tax_identifier'] ?? []; $billing_address = $args['billing_address'] ?? []; // Require tax ID for EU business customers $eu_countries = [ 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE' ]; $country = $billing_address['country'] ?? ''; if ( in_array( $country, $eu_countries, true ) ) { // Check if tax identifier number is provided if ( empty( $tax_identifier['number'] ) ) { $errors->add( 'tax_id_required', 'A VAT number is required for EU business purchases.' ); } } return $errors; }, 10, 3 ); ``` ### Force Test Mode for Non-Production ```php theme={null} add_filter( 'surecart/payments/mode', function( $mode ) { // Always use test mode unless on production $allowed_hosts = [ 'www.example.com', 'example.com' ]; if ( ! in_array( $_SERVER['HTTP_HOST'], $allowed_hosts ) ) { return 'test'; } return $mode; } ); ``` ## JavaScript Filter Use Cases ### Sell Only to Specific Countries Restrict your checkout to only allow purchases from certain countries: ```javascript theme={null} wp.hooks.addFilter( "surecart_address_countries", "my-customization", (countries) => { // Only sell to North American countries const allowedCountries = ["US", "CA", "MX"]; return countries.filter((country) => allowedCountries.includes(country.value) ); } ); ``` ### Exclude Specific Countries Remove certain countries from the dropdown while keeping all others: ```javascript theme={null} wp.hooks.addFilter( "surecart_address_countries", "my-customization", (countries) => { // Exclude countries you don't ship to const excludedCountries = ["RU", "BY", "KP"]; return countries.filter( (country) => !excludedCountries.includes(country.value) ); } ); ``` ### Change County Name Translations Change the transled country names to something different. ```javascript theme={null} wp.hooks.addFilter( "surecart_address_countries", "my-customization", (countries) => { // Spanish translations for common countries const translations = { US: "Estados Unidos", CA: "Canadá", MX: "México", ES: "España", GB: "Reino Unido", FR: "Francia", DE: "Alemania", }; return countries.map((country) => ({ value: country.value, label: translations[country.value] || country.label, })); } ); ``` ### Prioritize Common Countries Move your most common customer countries to the top of the list: ```javascript theme={null} wp.hooks.addFilter( "surecart_address_countries", "my-customization", (countries) => { const priorityCountries = ["US", "CA", "GB", "AU"]; // Separate priority and other countries const priority = countries.filter((c) => priorityCountries.includes(c.value) ); const others = countries.filter( (c) => !priorityCountries.includes(c.value) ); // Sort priority countries in specified order priority.sort( (a, b) => priorityCountries.indexOf(a.value) - priorityCountries.indexOf(b.value) ); return [...priority, ...others]; } ); ``` ### Prioritize Card Payments Show card payment first for faster checkout: ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_payment_method_order", "my-customization", (paymentMethodOrder, checkout) => { return ["card", "apple_pay", "google_pay", "klarna", "afterpay_clearpay"]; } ); ``` ### Disable Link Wallet for Subscriptions Hide Stripe Link for recurring payments: ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_wallets", "my-customization", (wallets, checkout) => { // Check if checkout contains a subscription const hasSubscription = checkout?.line_items?.data?.some( (item) => item.price?.recurring_interval ); if (hasSubscription) { return { ...wallets, link: "never", }; } return wallets; } ); ``` ### Show Bank Terms for High-Value Orders Always display ACH terms for orders over a certain amount: ```javascript theme={null} wp.hooks.addFilter( "surecart_stripe_payment_element_terms", "my-customization", (terms, checkout) => { // Show bank account terms for orders over $500 if (checkout?.total_amount > 50000) { return { ...terms, usBankAccount: "always", }; } return terms; } ); ``` ## Modifying Templates You can customize the HTML output of SureCart blocks using WordPress's `render_block` filter and the HTML Tag Processor. Learn how to modify block HTML, add custom attributes, wrap content, and inject elements into templates. ## Related Customize cart icon and visibility. Customize login redirects and authentication. Hook into individual purchase events. Hook into order and payment events. Modify blocks, shortcodes, and inject content. # Currency Source: https://developer.surecart.com/documentation/actions-filters/currency Customize currency formatting, locales, and display These filters allow you to customize how currency amounts are formatted and displayed throughout SureCart. ## `surecart/currency/format` Filter the formatted currency string. This is the final output that users see. The formatted currency string (e.g., "\$19.99"). The amount in cents. The currency code (e.g., 'USD', 'EUR'). ```php theme={null} add_filter( 'surecart/currency/format', function( $formatted, $amount, $currency_code ) { // Add custom prefix return 'Price: ' . $formatted; }, 10, 3 ); ``` ## `surecart/currency/locale` Filter the locale used for currency formatting. This affects number formatting, currency symbol placement, and decimal separators. ```php theme={null} add_filter( 'surecart/currency/locale', function( $locale ) { // Force a specific locale return 'en_US'; } ); // Or use WordPress locale add_filter( 'surecart/currency/locale', function( $locale ) { return get_locale(); } ); ``` ## `surecart/currency/max_cents` Filter the maximum number of decimal places shown. By default we do not show for whole amounts ().00 cents), but you could modify so it always shows 2 cents. Number of decimal places to display. The original amount in cents. The converted amount after currency conversion. ```php theme={null} add_filter( 'surecart/currency/max_cents', function( $decimals, $amount, $converted ) { // Always show 2 decimal places return 2; }, 10, 3 ); // This is our default functionality. add_filter( 'surecart/currency/max_cents', function( $decimals, $amount, $converted ) { // If the amount is a whole number, show no decimals return ( $converted == floor( $converted ) ) ? 0 : 2; }, 10, 3 ); ``` ## `surecart/currency/filter_url` To be able to run multi-currency while still maintaining full-page caching, we use a URL parameter to keep track of the user's chosen currency. To disable URL-based currency switching, you can use this filter. ```php theme={null} add_filter( 'surecart/currency/filter_url', '__return_false' ); // Or disable only for specific pages add_filter( 'surecart/currency/filter_url', function( $filter, $permalink ) { // Don't add currency params to checkout pages if ( strpos( $permalink, 'checkout' ) !== false ) { return false; } return $filter; }, 10, 2 ); ``` ## `surecart/display_amount/free` Filter the text displayed for \$0 prices. ```php theme={null} add_filter( 'surecart/display_amount/free', function( $text ) { return 'No Cost'; } ); // Or with context add_filter( 'surecart/display_amount/free', function( $text ) { return __( 'Complimentary', 'my-theme' ); } ); ``` ## `surecart/currency_switcher/label` Filter the currency switcher label text. ```php theme={null} add_filter( 'surecart/currency_switcher/label', function( $label ) { // Lowercase currency code return strtolower( $label ); } ); // Or add currency name add_filter( 'surecart/currency_switcher/label', function( $label ) { $currencies = [ 'USD' => 'US Dollar', 'EUR' => 'Euro', 'GBP' => 'British Pound', ]; return $currencies[ $label ] ?? $label; } ); ``` ## Related Modify API requests and responses. Customize product display and pricing. # Customers Source: https://developer.surecart.com/documentation/actions-filters/customers Hook into customer lifecycle events These actions fire when customer records are updated. ## `surecart/customer_updated` Fires when a customer's information is updated. The customer model object. The raw event data. ```php theme={null} add_action( 'surecart/customer_updated', function( $customer, $data ) { // Sync customer to CRM sync_customer_to_crm( $customer ); }, 10, 2 ); ``` ## Use Cases ### Sync to CRM ```php theme={null} add_action( 'surecart/customer_updated', function( $customer, $data ) { // Sync to HubSpot, Salesforce, etc. wp_remote_post( 'https://api.hubspot.com/contacts/v1/contact', [ 'body' => json_encode([ 'properties' => [ [ 'property' => 'email', 'value' => $customer->email ], [ 'property' => 'firstname', 'value' => $customer->first_name ?? '' ], [ 'property' => 'lastname', 'value' => $customer->last_name ?? '' ], [ 'property' => 'phone', 'value' => $customer->phone ?? '' ], ] ]), 'headers' => [ 'Authorization' => 'Bearer ' . HUBSPOT_API_KEY, 'Content-Type' => 'application/json', ], ]); }, 10, 2 ); ``` ### Sync WordPress User Profile SureCart automatically syncs customer updates to WordPress users, but you can add additional sync logic: ```php theme={null} add_action( 'surecart/customer_updated', function( $customer, $data ) { // Get the linked WordPress user via the customer model $user = $customer->getUser(); if ( $user ) { // Access WP_User properties directly via __get magic method update_user_meta( $user->ID, 'billing_phone', $customer->phone ?? '' ); // Update display name if changed if ( ! empty( $customer->name ) && $user->display_name !== $customer->name ) { wp_update_user([ 'ID' => $user->ID, 'display_name' => $customer->name, ]); } } }, 10, 2 ); ``` ### Send to Email Marketing Platform ```php theme={null} add_action( 'surecart/customer_updated', function( $customer, $data ) { // Update subscriber in Mailchimp $list_id = MAILCHIMP_LIST_ID; $subscriber_hash = md5( strtolower( $customer->email ) ); wp_remote_request( "https://us1.api.mailchimp.com/3.0/lists/{$list_id}/members/{$subscriber_hash}", [ 'method' => 'PATCH', 'body' => json_encode([ 'email_address' => $customer->email, 'merge_fields' => [ 'FNAME' => $customer->first_name ?? '', 'LNAME' => $customer->last_name ?? '', ], ]), 'headers' => [ 'Authorization' => 'Basic ' . base64_encode( 'anystring:' . MAILCHIMP_API_KEY ), 'Content-Type' => 'application/json', ], ] ); }, 10, 2 ); ``` # Errors Source: https://developer.surecart.com/documentation/actions-filters/errors Customize error messages and validation feedback These filters allow you to customize how error messages are displayed to customers throughout SureCart. ## Error Message Filters ### `surecart/translated_error` Filter individual translated error messages. The `$response` object contains the error details including `code`, `attribute`, `type`, and `options`. The translated error message. The original error response with `code`, `attribute`, `type`, and `options` keys. ```php theme={null} add_filter( 'surecart/translated_error', function( $translated, $response ) { // Customize specific error messages by code if ( ( $response['code'] ?? '' ) === 'checkout.discount.promotion_code.invalid_code' ) { return 'Sorry, that promo code is not valid. Please check and try again.'; } return $translated; }, 10, 2 ); ``` ### `surecart/translated_errors` Filter the WP\_Error object containing all translated error messages. ```php theme={null} add_filter( 'surecart/translated_errors', function( $wp_error ) { // Add a generic help message to all errors foreach ( $wp_error->get_error_codes() as $code ) { $message = $wp_error->get_error_message( $code ); $wp_error->remove( $code ); $wp_error->add( $code, $message . ' Need help? Contact support.' ); } return $wp_error; } ); ``` ## Common Error Codes Here are some frequently customized error codes: | Code | Default Message | | ----------------------------------------------- | ---------------------------------------------------------- | | `checkout.discount.promotion_code.invalid_code` | Invalid promotion code. | | `checkout.discount.coupon.expired` | This coupon has expired. | | `checkout.line_items.not_purchasable` | Some items in your cart have reached their purchase limit. | | `checkout.product.out_of_stock` | This product is out of stock. | | `checkout.price.exceeds_purchase_limit` | You have exceeded the purchase limit for this product. | | `checkout.shipping_address.postal_code.invalid` | Your postal code is not valid. | To find error codes for specific scenarios, open your browser's Developer Tools (F12), go to the **Network** tab, and trigger the error on your checkout. Look at the XHR/Fetch request response—the `code` field in the JSON response is what you'll use in your filter. ## Use Cases ### Custom Promotion Code Messages ```php theme={null} add_filter( 'surecart/translated_error', function( $translated, $response ) { $code = $response['code'] ?? ''; $custom_messages = [ 'checkout.discount.promotion_code.invalid_code' => 'That code didn\'t work. Double-check the spelling or try another.', 'checkout.discount.coupon.expired' => 'This promotion has ended. Check our website for current offers!', 'checkout.discount.coupon.currency_mismatch' => 'This code only works with USD purchases.', ]; return $custom_messages[ $code ] ?? $translated; }, 10, 2 ); ``` ### Custom Stock Error Messages ```php theme={null} add_filter( 'surecart/translated_error', function( $translated, $response ) { $code = $response['code'] ?? ''; if ( $code === 'checkout.product.out_of_stock' ) { return 'This item just sold out! Join our waitlist to be notified when it\'s back.'; } if ( $code === 'checkout.price.exceeds_purchase_limit' ) { return 'This item is limited to one per customer.'; } return $translated; }, 10, 2 ); ``` ### Log Errors for Debugging ```php theme={null} add_filter( 'surecart/translated_error', function( $translated, $response ) { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( sprintf( '[SureCart Error] Code: %s | Type: %s | Message: %s', $response['code'] ?? 'unknown', $response['type'] ?? 'unknown', $translated ) ); } return $translated; }, 10, 2 ); ``` ### Custom Shipping Address Errors ```php theme={null} add_filter( 'surecart/translated_error', function( $translated, $response ) { $code = $response['code'] ?? ''; $shipping_messages = [ 'checkout.shipping_address.postal_code.invalid' => 'Please enter a valid ZIP/postal code for your country.', 'checkout.shipping_address.inaccurate' => 'We need a bit more detail—please add your street address or apartment number.', 'checkout.selected_shipping_choice.blank' => 'Sorry, we can\'t ship to your location yet. Contact us for alternatives.', ]; return $shipping_messages[ $code ] ?? $translated; }, 10, 2 ); ``` ## Related Customize the checkout process and validation. Modify API requests and responses. # Integrations Source: https://developer.surecart.com/documentation/actions-filters/integrations Hook into integration lifecycle events **These are low-level actions for integration configuration changes.**

If you are wanting to create a full purchase integration that handles granting access, refunds, upgrades, downgrades and more, please follow the [Purchase Integration Guide](/documentation/orders-and-purchases).
These actions fire when a merchant configures or removes product integrations in the SureCart admin. Product integrations are the automated actions that occur when a product is purchased—such as changing a user's WordPress role, enrolling them in a course, or adding them to a membership group. ## `surecart/integrations/create` Fired when a merchant **adds** an integration to a product. For example, adding a "Change User Role" integration on the Edit Product page. The integration parameters including provider, model, and configuration. ```php theme={null} add_action( 'surecart/integrations/create', function( $params ) { // Log when integrations are added error_log( 'Integration created: ' . print_r( $params, true ) ); // Notify admin when a new integration is configured if ( ! empty( $params['provider'] ) ) { wp_mail( get_option( 'admin_email' ), 'New Product Integration Added', sprintf( 'A %s integration was added to a product.', $params['provider'] ) ); } } ); ``` ## `surecart/integrations/delete` Fired when a merchant **removes** an integration from a product. The integration parameters that were removed. ```php theme={null} add_action( 'surecart/integrations/delete', function( $params ) { // Clean up any custom data when integration is removed error_log( 'Integration deleted: ' . print_r( $params, true ) ); } ); ``` ## Related Build full integrations using the Integration class that handles purchases, refunds, upgrades, and more. Hook into purchase lifecycle events like created, invoked, and revoked. # Login Source: https://developer.surecart.com/documentation/actions-filters/login Customize login redirects and user authentication behavior These filters allow you to customize the login and authentication experience. ## `sc_login_redirect_url` Filter the redirect URL after login. ```php theme={null} add_filter( 'sc_login_redirect_url', function( $url ) { // Redirect to custom dashboard return home_url( '/my-account/' ); } ); // Or redirect based on user role add_filter( 'sc_login_redirect_url', function( $url ) { $user = wp_get_current_user(); if ( in_array( 'subscriber', $user->roles ) ) { return home_url( '/member-dashboard/' ); } return $url; } ); ``` ## Disable Password Nag Control whether new users see the password change nag after their account is created with a random, temporary password. SureCart uses default WordPress functionality for best compatibility, so you can use the `get_user_metadata` filter to intercept the `default_password_nag` user meta check. ```php theme={null} add_filter( 'get_user_metadata', function( $value, $object_id, $meta_key, $single ) { if ( 'default_password_nag' === $meta_key ) { return ''; // Return empty to prevent password nag from showing } return $value; }, 10, 4 ); ``` ## Use Cases ### Redirect to Download After Purchase ```php theme={null} add_filter( 'sc_login_redirect_url', function( $url ) { // If there's a pending download, redirect to downloads page if ( isset( $_COOKIE['sc_pending_download'] ) ) { return home_url( '/downloads/' ); } return $url; } ); ``` ### Role-Based Redirects ```php theme={null} add_filter( 'sc_login_redirect_url', function( $url ) { $user = wp_get_current_user(); // Redirect admins to WordPress dashboard if ( in_array( 'administrator', $user->roles ) ) { return admin_url(); } // Redirect members to member area if ( in_array( 'sc_member', $user->roles ) ) { return home_url( '/members/' ); } // Redirect customers to their account return home_url( '/my-account/' ); } ); ``` ### Redirect to Original Page ```php theme={null} add_filter( 'sc_login_redirect_url', function( $url ) { // Check for stored redirect URL if ( isset( $_GET['redirect_to'] ) ) { $redirect = wp_validate_redirect( $_GET['redirect_to'], false ); if ( $redirect ) { return esc_url( $redirect ); } } // Check session/cookie for original page if ( isset( $_COOKIE['sc_original_page'] ) ) { $redirect = esc_url( $_COOKIE['sc_original_page'] ); setcookie( 'sc_original_page', '', time() - 3600, '/' ); return $redirect; } return $url; } ); ``` ### Disable Password Nag for Specific Users ```php theme={null} add_filter( 'get_user_metadata', function( $value, $object_id, $meta_key, $single ) { if ( 'default_password_nag' !== $meta_key ) { return $value; } // Don't nag users who signed up via social login if ( get_user_meta( $object_id, 'social_login', true ) ) { return ''; // Return empty to prevent password nag from showing } return $value; }, 10, 4 ); ``` ## Related Customize checkout user creation and auto-login. Hook into customer lifecycle events. # Media Source: https://developer.surecart.com/documentation/actions-filters/media Customize video playback, image galleries, and media display These filters allow you to customize how media elements like videos and image galleries are displayed throughout SureCart. ## Video Filters ### `surecart/product-video-poster/size` Filter the video poster image size. ```php theme={null} add_filter( 'surecart/product-video-poster/size', function( $size ) { return 'full'; } ); ``` ### `surecart/product-video-poster/fallback_src` Filter the fallback video poster image. ```php theme={null} add_filter( 'surecart/product-video-poster/fallback_src', function( $src ) { return get_template_directory_uri() . '/images/video-placeholder.jpg'; } ); ``` ### `surecart_video_html` Filter the video HTML output for complete customization. The video HTML markup. Video attributes including src, poster, dimensions. The media object from the gallery. Video metadata including duration, codec, etc. ```php theme={null} add_filter( 'surecart_video_html', function( $html, $video, $media, $metadata ) { // Use custom video player return sprintf( '
', esc_url( $video['src'] ), esc_url( $video['poster'] ?? '' ) ); }, 10, 4 ); ``` ## Image Gallery Filters ### `surecart/image-slider/active-breakpoint` Filter the breakpoint for gallery slider activation. ```php theme={null} add_filter( 'surecart/image-slider/active-breakpoint', function( $breakpoint ) { return 768; // Change breakpoint pixel value } ); // Or disable slider on desktop add_filter( 'surecart/image-slider/active-breakpoint', function( $breakpoint ) { return 1024; // Only activate slider below 1024px } ); ``` ## Use Cases ### Custom Video Player Integration ```php theme={null} add_filter( 'surecart_video_html', function( $html, $video, $media, $metadata ) { // Use Plyr video player wp_enqueue_script( 'plyr' ); wp_enqueue_style( 'plyr' ); return sprintf( '', esc_url( $video['poster'] ?? '' ), esc_url( $video['src'] ) ); }, 10, 4 ); ``` ### Add Video Analytics Tracking ```php theme={null} add_filter( 'surecart_video_html', function( $html, $video, $media, $metadata ) { $processor = new WP_HTML_Tag_Processor( $html ); if ( $processor->next_tag( 'video' ) ) { // Add tracking attributes for analytics $processor->set_attribute( 'data-track', 'product-video' ); $processor->set_attribute( 'data-video-id', esc_attr( $media->id ?? '' ) ); $processor->set_attribute( 'data-duration', esc_attr( $metadata['duration'] ?? '' ) ); } return $processor->get_updated_html(); }, 10, 4 ); ``` ## Related Customize product display and images. Modify block output and inject content. # Models Source: https://developer.surecart.com/documentation/actions-filters/models Hook into model hydration events SureCart fires filters and actions when models are hydrated with data. These hooks allow you to modify model properties, add dynamic computed properties, or transform data as it's being populated into the model. ## `surecart/{object_name}/attributes_set` Fired after all attributes are set on a model. Useful for adding computed properties or modifying model data after it's been fully populated. ```php theme={null} add_action( 'surecart/checkout/attributes_set', function( $checkout ) { // Add computed properties after checkout is hydrated $checkout->custom_total = $checkout->amount_due + $checkout->tax_amount; } ); add_action( 'surecart/product/attributes_set', function( $product ) { // Add custom computed attributes $product->is_featured = in_array( $product->id, get_option( 'featured_products', [] ) ); } ); add_action( 'surecart/subscription/attributes_set', function( $subscription ) { // Add dynamic properties based on subscription state $subscription->days_until_renewal = $subscription->current_period_end ? ceil( ( $subscription->current_period_end - time() ) / DAY_IN_SECONDS ) : null; } ); ``` ## `surecart/{object_name}/attributes/{key}` Filter individual attribute values as they are being set on a model during hydration. This allows you to transform, validate, or modify any attribute before it's stored on the model. **Parameters:** * `$value` *(mixed)* – The value being set for the attribute * `$model` *(Model)* – The model instance **Returns:** The filtered value to be stored ```php theme={null} // Transform subscription status for display add_filter( 'surecart/subscription/attributes/status', function( $value, $subscription ) { // Store original and add formatted version $subscription->status_label = ucfirst( str_replace( '_', ' ', $value ) ); return $value; }, 10, 2 ); // Modify product name during hydration add_filter( 'surecart/product/attributes/name', function( $value, $product ) { // Append badge for certain products if ( ! empty( $product->metadata->is_new ) ) { return $value . ' (New!)'; } return $value; }, 10, 2 ); // Convert timestamps to Carbon instances add_filter( 'surecart/order/attributes/created_at', function( $value, $order ) { $order->created_date = wp_date( 'F j, Y', $value ); return $value; }, 10, 2 ); ``` Use this filter to create dynamic computed properties, normalize data formats, or add display-ready versions of raw values. ## `surecart/{object_name}/set_meta_data` Filter metadata before it's set on a model during hydration. Useful for ensuring metadata structure, adding defaults, or transforming metadata values. **Parameters:** * `$meta_data` *(array|object)* – The metadata being set **Returns:** The filtered metadata ```php theme={null} // Ensure subscription metadata has defaults add_filter( 'surecart/subscription/set_meta_data', function( $meta_data ) { $meta_data = (array) $meta_data; // Add default values if not present $meta_data['notification_preferences'] = $meta_data['notification_preferences'] ?? [ 'renewal_reminder' => true, 'payment_failed' => true, ]; return (object) $meta_data; } ); // Parse and expand product metadata add_filter( 'surecart/product/set_meta_data', function( $meta_data ) { $meta_data = (array) $meta_data; // Parse JSON stored in a metadata field if ( ! empty( $meta_data['specifications'] ) && is_string( $meta_data['specifications'] ) ) { $meta_data['specifications'] = json_decode( $meta_data['specifications'], true ); } return (object) $meta_data; } ); // Add computed metadata properties add_filter( 'surecart/customer/set_meta_data', function( $meta_data ) { $meta_data = (array) $meta_data; // Check if customer has completed onboarding $meta_data['onboarding_complete'] = ! empty( $meta_data['onboarding_step'] ) && $meta_data['onboarding_step'] === 'complete'; return (object) $meta_data; } ); ``` ## Available Models You can hook into hydration events for these models: * `subscription` - Subscription data * `purchase` - Purchase data * `product` - Product data * `price` - Price data * `customer` - Customer data * `order` - Order data * `checkout` - Checkout data * `charge` - Payment charge data * `refund` - Refund data * `invoice` - Invoice data * `coupon` - Coupon data ## Related Hook into product creation, updates, and deletion events. Higher-level purchase events built on model actions. # Orders Source: https://developer.surecart.com/documentation/actions-filters/orders Hook into order, charge, refund, and invoice events These actions fire during order processing, payments, refunds, and invoicing. ## Order Actions ### `surecart/order_created` Fires when a new order is created. The order model object. The raw event data. ```php theme={null} add_action( 'surecart/order_created', function( $order, $data ) { // Log new order error_log( sprintf( 'New order created: %s', $order ) ); }, 10, 2 ); ``` ### `surecart/order_updated` Fires when an order is updated. ```php theme={null} add_action( 'surecart/order_updated', function( $order, $data ) { // Sync order status changes if ( $order->status === 'paid' ) { mark_order_complete_in_erp( $order->id ); } }, 10, 2 ); ``` ## Charge Actions ### `surecart/charge_created` Fires when a payment charge is created. The charge model object. The raw event data. ```php theme={null} add_action( 'surecart/charge_created', function( $charge, $data ) { // Log successful payment error_log( sprintf( 'Payment received: %s for %d cents', $charge->id, $charge->amount ) ); // Track revenue track_revenue( $charge->amount, $charge->currency ); }, 10, 2 ); ``` ## Refund Actions ### `surecart/refund_created` Fires when a refund is processed. The refund model object. The raw event data. ```php theme={null} add_action( 'surecart/refund_created', function( $refund, $data ) { // Send refund notification wp_mail( get_option( 'admin_email' ), 'Refund Processed', sprintf( 'A refund of %d cents has been processed.', $refund->amount ) ); }, 10, 2 ); ``` ## Invoice Actions ### `surecart/invoice_created` Fires when an invoice is manually created by a user in the admin. This does not fire for automatic subscription invoices or checkout orders—only for invoices explicitly created through the SureCart dashboard. The invoice model object. The raw event data. ```php theme={null} add_action( 'surecart/invoice_created', function( $invoice, $data ) { // Send invoice to accounting system send_to_quickbooks( $invoice ); }, 10, 2 ); ``` ## Use Cases ### Track Revenue ```php theme={null} add_action( 'surecart/charge_created', function( $charge, $data ) { global $wpdb; // Store in custom revenue table $wpdb->insert( $wpdb->prefix . 'revenue_tracking', [ 'charge_id' => $charge->id, 'amount' => $charge->amount, 'currency' => $charge->currency, 'created_at' => current_time( 'mysql' ), ] ); }, 10, 2 ); ``` ### Handle Refunds ```php theme={null} add_action( 'surecart/refund_created', function( $refund, $data ) { // Update accounting record_refund_in_books( $refund->amount, $refund->currency ); // Notify admin wp_mail( get_option( 'admin_email' ), 'Refund Processed', sprintf( 'A refund of $%s has been processed for refund ID: %s', $refund->display_amount, $refund->id ) ); }, 10, 2 ); ``` ### Sync Manual Invoices to Accounting ```php theme={null} add_action( 'surecart/invoice_created', function( $invoice, $data ) { // Note: This only fires for manually created invoices. // For syncing all revenue, use surecart/charge_created instead. // Fetch the invoice with checkout and customer relations loaded. $invoice = \SureCart\Models\Invoice::with(['checkout', 'checkout.customer'])->find( $invoice->id ); $checkout = $invoice->checkout ?? null; if ( empty( $checkout ) ) { return; } // Send to QuickBooks, Xero, FreshBooks, etc. wp_remote_post( 'https://api.quickbooks.com/v3/invoice', [ 'body' => json_encode([ 'Line' => [[ 'Amount' => ( $checkout->total_amount ?? 0 ) / 100, 'Description' => 'SureCart Invoice ' . $invoice->id, ]], 'CustomerRef' => [ 'value' => $checkout->customer->id ?? '', ], ]), 'headers' => [ 'Authorization' => 'Bearer ' . QUICKBOOKS_TOKEN, 'Content-Type' => 'application/json', ], ]); }, 10, 2 ); ``` # Prices Source: https://developer.surecart.com/documentation/actions-filters/prices Hook into price lifecycle events These actions fire when prices are created, updated, or deleted. Prices in SureCart are similar to Stripe prices—they define the cost, currency, and billing interval for a product. ## `surecart/price_created` Fires when a new price is created for a product. The price model object. The raw event data. ```php theme={null} add_action( 'surecart/price_created', function( $price, $data ) { // Notify team about new pricing option wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '💰 New price created: %s (%s)', $price->name ?? $price->id, $price->display_amount ) ]), ]); }, 10, 2 ); ``` ## `surecart/price_updated` Fires when a price is updated (e.g., amount changed, name updated, or archived). The updated price model object. The raw event data. ```php theme={null} add_action( 'surecart/price_updated', function( $price, $data ) { // Sync price change to accounting software wp_remote_patch( 'https://api.accounting.example.com/prices/' . $price->id, [ 'headers' => [ 'Authorization' => 'Bearer ' . ACCOUNTING_API_KEY ], 'body' => json_encode([ 'amount' => $price->amount, 'currency' => $price->currency, 'name' => $price->name, ]), ]); }, 10, 2 ); ``` ## `surecart/price_deleted` Fires when a price is deleted (archived). The deleted price model object. The raw event data. ```php theme={null} add_action( 'surecart/price_deleted', function( $price, $data ) { // Archive price in external billing system wp_remote_request( 'https://api.billing.example.com/prices/' . $price->id, [ 'method' => 'DELETE', 'headers' => [ 'Authorization' => 'Bearer ' . BILLING_API_KEY ], ]); }, 10, 2 ); ``` ## Use Cases ### Sync Prices to External Billing System ```php theme={null} add_action( 'surecart/price_created', 'sync_price_to_billing', 10, 2 ); add_action( 'surecart/price_updated', 'sync_price_to_billing', 10, 2 ); function sync_price_to_billing( $price, $data ) { // Fetch the associated product for context $product = \SureCart\Models\Product::find( $price->product ); wp_remote_post( 'https://api.billing.example.com/prices', [ 'headers' => [ 'Authorization' => 'Bearer ' . BILLING_API_KEY, 'Content-Type' => 'application/json', ], 'body' => json_encode([ 'external_id' => $price->id, 'product_id' => $price->product, 'product_name' => $product->name ?? '', 'amount' => $price->amount, 'currency' => $price->currency, 'recurring' => ! empty( $price->recurring_interval ), 'interval' => $price->recurring_interval ?? null, 'interval_count' => $price->recurring_interval_count ?? null, ]), ]); } ``` ### Alert on High-Value Price Changes ```php theme={null} add_action( 'surecart/price_updated', function( $price, $data ) { // Alert finance team when prices over $1000 are modified if ( $price->amount >= 100000 ) { // Amount in cents $product = \SureCart\Models\Product::find( $price->product ); wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '⚠️ High-value price modified: %s - %s is now %s', $product->name ?? 'Unknown Product', $price->name ?? $price->id, $price->display_amount ) ]), ]); } }, 10, 2 ); ``` # Products Source: https://developer.surecart.com/documentation/actions-filters/products Hook into product lifecycle events and customize display These hooks allow you to respond to product events and customize how products are displayed. ## Actions Actions fire when products are created, updated, deleted, or when stock levels change. ### `surecart/product_created` Fires when a new product is created. The product model object. The raw event data. ```php theme={null} add_action( 'surecart/product_created', function( $product, $data ) { // Send Slack notification about new product wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '🆕 New product created: %s', $product->name ) ]), ]); }, 10, 2 ); ``` ### `surecart/product_updated` Fires when a product is updated. The updated product model object. The raw event data. ```php theme={null} add_action( 'surecart/product_updated', function( $product, $data ) { // Sync updated product info to Google Sheets $sheets_api_url = 'https://sheets.googleapis.com/v4/spreadsheets/' . SHEET_ID . '/values/Products:append'; wp_remote_post( $sheets_api_url, [ 'headers' => [ 'Authorization' => 'Bearer ' . GOOGLE_API_TOKEN ], 'body' => json_encode([ 'values' => [[ $product->id, $product->name, $product->sku ?? '' ]] ]), ]); }, 10, 2 ); ``` ### `surecart/product_deleted` Fires when a product is deleted. The deleted product model object. The raw event data. ```php theme={null} add_action( 'surecart/product_deleted', function( $product, $data ) { // Remove product from external CRM wp_remote_request( 'https://api.crm.example.com/products/' . $product->id, [ 'method' => 'DELETE', 'headers' => [ 'Authorization' => 'Bearer ' . CRM_API_KEY ], ]); }, 10, 2 ); ``` ### `surecart/product_stock_adjusted` Fires when a product's stock level changes (e.g., after a purchase or manual adjustment). Products with variants will have stock tracked at both the product and variant level. The product model object with updated stock. Use `Product::with(['variants'])` to fetch variant stock levels. The raw event data. **Stock Properties:** | Property | Description | | ----------------- | --------------------------------------------------- | | `stock` | Total on-hand inventory count | | `held_stock` | Units purchased but not yet fulfilled/shipped | | `available_stock` | Units available for purchase (`stock - held_stock`) | ```php theme={null} add_action( 'surecart/product_stock_adjusted', function( $product, $data ) { // Sync all stock levels to warehouse management system wp_remote_post( 'https://wms.example.com/api/inventory', [ 'headers' => [ 'Authorization' => 'Bearer ' . WMS_API_KEY ], 'body' => [ 'sku' => $product->sku ?? $product->id, 'on_hand' => $product->stock, 'held' => $product->held_stock, 'available' => $product->available_stock, ], ]); }, 10, 2 ); ``` **Low available stock alert:** ```php theme={null} add_action( 'surecart/product_stock_adjusted', function( $product, $data ) { // Alert when available stock (not held) is low if ( $product->available_stock <= 5 && $product->available_stock > 0 ) { wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '⚠️ Low stock: %s has %d available (%d on hand, %d held)', $product->name, $product->available_stock, $product->stock, $product->held_stock ) ]), ]); } }, 10, 2 ); ``` **Sync product and variant stock levels:** ```php theme={null} add_action( 'surecart/product_stock_adjusted', function( $product, $data ) { // Fetch the product with its variants $product = \SureCart\Models\Product::with(['variants'])->find( $product->id ); // Sync product-level stock $stock_data = [ [ 'type' => 'product', 'id' => $product->id, 'sku' => $product->sku ?? '', 'stock' => $product->stock, 'available_stock' => $product->available_stock, 'held_stock' => $product->held_stock, ], ]; // Include each variant's stock levels if ( ! empty( $product->variants->data ) ) { foreach ( $product->variants->data as $variant ) { $stock_data[] = [ 'type' => 'variant', 'id' => $variant->id, 'sku' => $variant->sku ?? '', 'stock' => $variant->stock, 'available_stock' => $variant->available_stock, 'held_stock' => $variant->held_stock, ]; } } wp_remote_post( 'https://api.inventory.example.com/stock/bulk', [ 'headers' => [ 'Authorization' => 'Bearer ' . INVENTORY_API_KEY ], 'body' => json_encode( $stock_data ), ]); }, 10, 2 ); ``` ## Filters Filters allow you to customize how products are displayed, including SEO meta tags, images, and related products. ### Content Display #### `surecart/product/replace_content_with_product_info_part` Control whether product content is replaced with the product info template part. Return `false` to use custom templates. ```php theme={null} add_filter( 'surecart/product/replace_content_with_product_info_part', function( $replace ) { // Disable replacement for specific conditions if ( is_page_template( 'custom-product-template.php' ) ) { return false; } return $replace; } ); // Or disable entirely add_filter( 'surecart/product/replace_content_with_product_info_part', '__return_false' ); ``` ### Permalinks #### `sc_product_post_type_link_sc_collection` Filter which collection appears in product URLs when your permalink structure includes the collection slug. When your product permalinks are configured to include the collection (e.g., `/products/%sc_collection%/%product%/`), a product URL might look like `/products/clothing/blue-t-shirt/`. But what happens when a product belongs to multiple collections, like both "clothing" and "sale"? This filter lets you control which collection slug is used in the URL. **Example scenario:** * Product "Blue T-Shirt" belongs to collections: `clothing`, `sale`, `featured` * Without this filter, WordPress picks one (often unpredictably) * With this filter, you can ensure the URL is always `/products/clothing/blue-t-shirt/` instead of `/products/sale/blue-t-shirt/` The collection term WordPress selected for the permalink. All collection terms assigned to this product. The product post object. **Always use the first assigned collection:** ```php theme={null} add_filter( 'sc_product_post_type_link_sc_collection', function( $term, $terms, $post ) { // Use the first collection assigned to the product return $terms[0] ?? $term; }, 10, 3 ); ``` **Prioritize a specific collection when present:** ```php theme={null} add_filter( 'sc_product_post_type_link_sc_collection', function( $term, $terms, $post ) { // If product is in "clothing", always use that in the URL foreach ( $terms as $t ) { if ( $t->slug === 'clothing' ) { return $t; } } return $term; }, 10, 3 ); ``` **Exclude certain collections from URLs:** ```php theme={null} add_filter( 'sc_product_post_type_link_sc_collection', function( $term, $terms, $post ) { // Never use "sale" or "featured" in URLs - these are promotional, not categorical $excluded_slugs = [ 'sale', 'featured', 'new-arrivals' ]; // If current term is excluded, find a better one if ( in_array( $term->slug, $excluded_slugs, true ) ) { foreach ( $terms as $t ) { if ( ! in_array( $t->slug, $excluded_slugs, true ) ) { return $t; } } } return $term; }, 10, 3 ); ``` ### Images #### `surecart/product-line-item-image/fallback_src` Filter the fallback image for product line items when no image is set. ```php theme={null} add_filter( 'surecart/product-line-item-image/fallback_src', function( $src, $product ) { return get_template_directory_uri() . '/images/placeholder.png'; }, 10, 2 ); ``` #### `surecart/product-list/thumbnail-cover-size` Filter the thumbnail size for product list items. ```php theme={null} add_filter( 'surecart/product-list/thumbnail-cover-size', function( $size, $post_id ) { return 'medium_large'; }, 10, 2 ); // Or use different sizes based on context add_filter( 'surecart/product-list/thumbnail-cover-size', function( $size, $post_id ) { if ( is_archive() ) { return 'medium'; } return 'large'; }, 10, 2 ); ``` ### Related Products #### `surecart_product_related_posts_query_limit` Filter the limit for related products query. ```php theme={null} add_filter( 'surecart_product_related_posts_query_limit', function( $limit ) { return 20; // Increase related products limit } ); ``` #### `surecart_product_related_posts_query` Filter the related products SQL query for advanced customization. ```php theme={null} add_filter( 'surecart_product_related_posts_query', function( $query, $post_id ) { // Modify query parts // $query is an array with 'select', 'from', 'where', etc. return $query; }, 10, 2 ); ``` ### Product Page #### `surecart_product_page_query_args` Filter the WP\_Query arguments used to fetch the product on a product page. By default, this queries a single published product by its post ID. **Default query args:** ```php theme={null} [ 'post_type' => 'sc_product', 'posts_per_page' => 1, 'post__in' => [ $product_post_id ], 'post_status' => [ 'publish' ], ] ``` **Allow previewing draft products:** ```php theme={null} add_filter( 'surecart_product_page_query_args', function( $args ) { // Allow admins to preview unpublished products if ( current_user_can( 'manage_options' ) ) { $args['post_status'] = [ 'publish', 'draft', 'private' ]; } return $args; } ); ``` **Remove post restriction for page builders:** ```php theme={null} add_filter( 'surecart_product_page_query_args', function( $args ) { // In editor context, allow any product to be displayed for previewing if ( is_admin() || defined( 'REST_REQUEST' ) ) { unset( $args['post__in'] ); } return $args; } ); ``` ## Use Cases ### Sync Product Metadata to External System ```php theme={null} add_action( 'surecart/product_created', 'sync_product_to_erp', 10, 2 ); add_action( 'surecart/product_updated', 'sync_product_to_erp', 10, 2 ); function sync_product_to_erp( $product, $data ) { wp_remote_post( 'https://erp.example.com/api/products', [ 'body' => [ 'external_id' => $product->id, 'name' => $product->name, 'sku' => $product->sku ?? '', 'description' => $product->description ?? '', ], 'headers' => [ 'Authorization' => 'Bearer ' . ERP_API_KEY, ], ]); } // Sync stock levels separately when they change add_action( 'surecart/product_stock_adjusted', function( $product, $data ) { wp_remote_patch( 'https://erp.example.com/api/products/' . $product->id, [ 'body' => [ 'stock' => $product->stock ?? 0, 'available_stock' => $product->available_stock ?? 0, 'held_stock' => $product->held_stock ?? 0, ], 'headers' => [ 'Authorization' => 'Bearer ' . ERP_API_KEY ], ]); }, 10, 2 ); ``` ### Low Stock Notifications ```php theme={null} add_action( 'surecart/product_stock_adjusted', function( $product, $data ) { $low_stock_threshold = get_option( 'sc_low_stock_threshold', 10 ); // Use available_stock to check what's actually purchasable if ( $product->available_stock <= $low_stock_threshold && $product->available_stock > 0 ) { // Send Slack notification wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '⚠️ Low stock: %s has %d available (%d on hand, %d held)', $product->name, $product->available_stock, $product->stock, $product->held_stock ) ]), ]); } if ( $product->available_stock === 0 ) { // Send out of stock alert (no units available for purchase) wp_remote_post( SLACK_WEBHOOK_URL, [ 'body' => json_encode([ 'text' => sprintf( '🚨 Out of stock: %s (held: %d)', $product->name, $product->held_stock ) ]), ]); } }, 10, 2 ); ``` ### Use Custom Placeholder Image ```php theme={null} add_filter( 'surecart/product-line-item-image/fallback_src', function( $src, $product ) { // Check if product has a category $terms = get_the_terms( $product->post, 'sc_collection' ); if ( $terms && ! is_wp_error( $terms ) ) { $category_slug = $terms[0]->slug; $custom_placeholder = get_template_directory_uri() . '/images/placeholders/' . $category_slug . '.png'; if ( file_exists( get_template_directory() . '/images/placeholders/' . $category_slug . '.png' ) ) { return $custom_placeholder; } } return get_template_directory_uri() . '/images/default-product.png'; }, 10, 2 ); ``` ## Modifying Templates You can customize the HTML output of SureCart blocks using WordPress's `render_block` filter and the HTML Tag Processor. Learn how to modify block HTML, add custom attributes, wrap content, and inject elements into templates. ## Related Customize how prices are formatted. Modify reviews, blocks, and media display. # Purchases Source: https://developer.surecart.com/documentation/actions-filters/purchases Hook into purchase lifecycle events **Important: There are low-level filters for purchase events.**

If you are wanting to create a full purchase integration that handles refunds, upgrades, downgrades and more, please follow the [Purchase Integration Guide](/documentation/orders-and-purchases)
These actions are triggered throughout the purchase lifecycle, including: * **Checkout** — When a customer completes a purchase * **Refunds** — When a purchase is refunded and access is revoked * **Upgrades/Downgrades** — When a customer switches to a different product * **Quantity changes** — When a customer adjusts the quantity of their purchase * **Subscription cancellations** — When a subscription ends and access is revoked * **Subscription restorations** — When a canceled subscription is reactivated ## `surecart/purchase_created` Fired when a new purchase is created after a successful checkout. The purchase model object containing product, customer, quantity, and other purchase details. ```php theme={null} add_action( 'surecart/purchase_created', function( $purchase ) { // Get the product from the purchase. $product = sc_get_product( $purchase->product ); // Get the WordPress user associated with this purchase $user = $purchase->getWPUser(); if ( empty($user) || empty($product->name) ) { return; } // Send a welcome email for this specific product wp_mail( $user->user_email, 'Welcome!', sprintf( "Hi %s, thank you for purchasing %s! We're excited to have you on board.", $user->display_name, $product->name ) ); } ); ``` ## `surecart/purchase_invoked` Fired when a purchase is invoked (access is granted). This happens when a subscription is restored, or when manually invoking access. The purchase model object. ```php theme={null} add_action( 'surecart/purchase_invoked', function( $purchase ) { // Get the product from the purchase. $product = sc_get_product( $purchase->product ); // Get the WordPress user associated with this purchase $user = $purchase->getWPUser(); if ( empty($user) || empty($product->name) ) { return; } // Send a welcome email for this specific product wp_mail( $user->user_email, 'Thanks for coming back!', sprintf( "Hi %s, thank you for restoring your payment for %s!", $user->display_name, $product->name ) ); } ); ``` ## `surecart/purchase_revoked` Fired when a purchase is revoked (access is removed). This happens when a subscription is canceled or when manually revoking access. The purchase model object. ```php theme={null} add_action( 'surecart/purchase_revoked', function( $purchase ) { $user = $purchase->getWPUser(); if ( $user ) { // Notify the user wp_mail( $user->user_email, 'Access Revoked', 'Your subscription has been canceled and access has been removed.' ); } } ); ``` ## `surecart/purchase_updated` Fired when a purchase is updated, due to upgrade, downgrade, quantity change, or price change. The updated purchase model. The webhook request containing `data->object` and `data->previous_attributes`. ```php theme={null} add_action( 'surecart/purchase_updated', function( $purchase, $request ) { $user = $purchase->getWPUser(); if ( $user ) { // Notify the user wp_mail( $user->user_email, 'Purchase Updated', 'Your purchase has been successfully modified.' ); } }, 10, 2 ); ``` ## Related Build integrations using the Integration class that handles purchases, refunds, upgrades, and more. Learn about checkout-triggered actions for purchases. # Requests Source: https://developer.surecart.com/documentation/actions-filters/requests Modify model data and API requests at a low level These filters allow you to intercept and modify data before it's sent to the SureCart API, and transform responses as they come back. This is useful for adding metadata, modifying request parameters, or transforming API responses. ## `surecart/request/model` Filter the model instance before an API request is made. This is the primary way to modify data being sent to the API for any model (checkouts, orders, customers, etc.). The model instance being sent to the API. The WordPress REST request object. ```php theme={null} // Add metadata to every checkout add_filter( 'surecart/request/model', function( $model, $request ) { // Only modify checkout models if ( ! $model instanceof \SureCart\Models\Checkout ) { return $model; } // Add tracking metadata $model['metadata'] = array_merge( (array) ( $model['metadata'] ?? [] ), [ 'source' => 'wordpress', 'landing_page' => $_COOKIE['landing_page'] ?? null, 'utm_source' => $_GET['utm_source'] ?? null, 'utm_medium' => $_GET['utm_medium'] ?? null, 'utm_campaign' => $_GET['utm_campaign'] ?? null, ] ); return $model; }, 10, 2 ); ``` ### Add Affiliate Tracking ```php theme={null} // Pass affiliate data to checkout metadata add_filter( 'surecart/request/model', function( $model, $request ) { if ( ! $model instanceof \SureCart\Models\Checkout ) { return $model; } // Get affiliate ID from cookie or session $affiliate_id = $_COOKIE['affiliate_id'] ?? null; if ( $affiliate_id ) { $model['metadata'] = array_merge( (array) ( $model['metadata'] ?? [] ), [ 'affiliate_id' => sanitize_text_field( $affiliate_id ), 'referral_date' => current_time( 'mysql' ), ] ); } return $model; }, 10, 2 ); ``` ### Block Checkout Based on Conditions ```php theme={null} // Block checkout from specific countries add_filter( 'surecart/request/model', function( $model, $request ) { if ( ! $model instanceof \SureCart\Models\Checkout ) { return $model; } // Check if POST/PATCH request (creating or updating) if ( ! in_array( $request->get_method(), [ 'POST', 'PATCH' ], true ) ) { return $model; } $blocked_countries = [ 'XX', 'YY' ]; // Your blocked country codes $billing_country = $model['billing_address']['country'] ?? null; if ( $billing_country && in_array( $billing_country, $blocked_countries, true ) ) { return new \WP_Error( 'country_blocked', __( 'Orders from your country are not currently accepted.', 'your-textdomain' ), [ 'status' => 403 ] ); } return $model; }, 10, 2 ); ``` ## `surecart/request/response` Filter the API response after it's received. Use this to transform, enrich, or modify response data before it's used. The API response object or array. The HTTP request arguments that were sent. The API endpoint that was called. ```php theme={null} // Enrich customer responses with WordPress user data add_filter( 'surecart/request/response', function( $response, $args, $endpoint ) { if ( strpos( $endpoint, 'customers' ) === false ) { return $response; } if ( is_object( $response ) && ! empty( $response->email ) ) { $wp_user = get_user_by( 'email', $response->email ); if ( $wp_user ) { $response->wp_user_id = $wp_user->ID; $response->wp_roles = $wp_user->roles; } } return $response; }, 10, 3 ); ``` ## `surecart/request/args` Filter the HTTP request arguments before sending. This allows you to modify headers, timeouts, or other HTTP-level settings. The HTTP request arguments including headers, body, method, and timeout. The API endpoint being called. ```php theme={null} // Increase timeout for export endpoints add_filter( 'surecart/request/args', function( $args, $endpoint ) { if ( strpos( $endpoint, 'exports' ) !== false ) { $args['timeout'] = 120; // 2 minutes for large exports } return $args; }, 10, 2 ); ``` ## `surecart/request/endpoint` Filter the API endpoint URL before the request is made. ```php theme={null} add_filter( 'surecart/request/endpoint', function( $endpoint, $args ) { // Log endpoints in development if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( 'SureCart API: ' . $endpoint ); } return $endpoint; }, 10, 2 ); ``` ## Related Hook into model hydration to modify data after it's received. Higher-level checkout actions and filters. # SEO Source: https://developer.surecart.com/documentation/actions-filters/seo Customize SEO behavior and meta tags These filters allow you to customize SEO-related behavior in SureCart, including meta tags, Open Graph data, and structured data (JSON-LD schema). ## Meta Tags SureCart automatically outputs SEO meta tags for product pages, including title, description, Open Graph tags, and Twitter Card data. These filters let you customize or disable this behavior. ### `surecart/noindex_query_vars` Filter the query variables that trigger a `noindex` meta tag on product pages. When a URL contains any of these query parameters, SureCart adds `` to prevent search engines from indexing that page variation. This is useful for preventing duplicate content issues. For example, URLs with tracking parameters, filter states, or session data should typically not be indexed separately from the canonical product page. Array of query variable names that trigger noindex. Default includes common tracking and session parameters. **Add custom query vars to noindex:** ```php theme={null} add_filter( 'surecart/noindex_query_vars', function( $vars ) { // Prevent indexing of URLs with affiliate tracking $vars[] = 'ref'; $vars[] = 'affiliate_id'; // Prevent indexing of filtered product views $vars[] = 'sort_by'; $vars[] = 'filter_color'; return $vars; } ); ``` **Remove a query var from noindex (allow indexing):** ```php theme={null} add_filter( 'surecart/noindex_query_vars', function( $vars ) { // Allow pages with 'campaign' parameter to be indexed $vars = array_diff( $vars, [ 'campaign' ] ); return $vars; } ); ``` ### `sc_display_product_seo_meta` Control whether SureCart outputs its built-in SEO meta tags for product pages. SureCart generates meta tags including: * `` and `<meta name="description">` * Open Graph tags (`og:title`, `og:description`, `og:image`, `og:url`, `og:type`) * Twitter Card tags (`twitter:card`, `twitter:title`, `twitter:description`, `twitter:image`) Return `false` to disable SureCart's meta tag output, which is recommended when using a dedicated SEO plugin that generates its own meta tags. <ResponseField name="Parameters" type="Filter Parameters"> <Expandable title="properties"> <ResponseField name="$display" type="bool"> Whether to display the SEO meta tags. Default: `true`. </ResponseField> <ResponseField name="$product" type="\SureCart\Models\Product"> The product model object for the current page. </ResponseField> </Expandable> </ResponseField> **Disable when using Yoast SEO:** ```php theme={null} add_filter( 'sc_display_product_seo_meta', function( $display, $product ) { // Let Yoast SEO handle all meta tags if ( class_exists( 'WPSEO_Frontend' ) || defined( 'WPSEO_VERSION' ) ) { return false; } return $display; }, 10, 2 ); ``` **Disable when using Rank Math:** ```php theme={null} add_filter( 'sc_display_product_seo_meta', function( $display, $product ) { // Let Rank Math handle all meta tags if ( class_exists( 'RankMath' ) ) { return false; } return $display; }, 10, 2 ); ``` **Disable when using All in One SEO:** ```php theme={null} add_filter( 'sc_display_product_seo_meta', function( $display, $product ) { // Let AIOSEO handle all meta tags if ( class_exists( 'AIOSEO\\Plugin\\AIOSEO' ) || defined( 'AIOSEO_VERSION' ) ) { return false; } return $display; }, 10, 2 ); ``` **Disable for any SEO plugin:** ```php theme={null} // Completely disable SureCart's SEO meta tag output add_filter( 'sc_display_product_seo_meta', '__return_false' ); ``` ### `surecart/og:image/size` Filter the WordPress image size used for Open Graph (`og:image`) and Twitter Card (`twitter:image`) meta tags. The Open Graph image is the preview image shown when your product pages are shared on social media platforms like Facebook, LinkedIn, and Twitter. <ResponseField name="Parameters" type="Filter Parameters"> <Expandable title="properties"> <ResponseField name="$size" type="string"> The WordPress image size name. Default: `'full'`. Can be any registered image size: `'thumbnail'`, `'medium'`, `'medium_large'`, `'large'`, `'full'`, or custom sizes. </ResponseField> </Expandable> </ResponseField> <Note> Facebook recommends images at least 1200×630 pixels for optimal display. The `'large'` or `'full'` sizes typically work best, but if your product images are very high resolution, you may want to use a smaller size to reduce page load time. </Note> **Use a specific image size:** ```php theme={null} add_filter( 'surecart/og:image/size', function( $size ) { return 'large'; // 1024px wide by default } ); ``` **Use a custom registered image size:** ```php theme={null} // First, register a custom image size optimized for social sharing add_action( 'after_setup_theme', function() { add_image_size( 'social-share', 1200, 630, true ); } ); // Then use it for Open Graph images add_filter( 'surecart/og:image/size', function( $size ) { return 'social-share'; } ); ``` ## Product Schema ### `sc_display_product_json_ld_schema` Control whether JSON-LD schema markup is output for products. <Warning> If you're using a third-party SEO plugin (like Yoast SEO, Rank Math, or All in One SEO) that generates product schema, you should disable SureCart's schema output to avoid duplicate structured data. Duplicate schema can confuse search engines and negatively impact your SEO. </Warning> <ResponseField name="Parameters" type="Filter Parameters"> <Expandable title="properties"> <ResponseField name="$display" type="bool"> Whether to display the schema markup. </ResponseField> <ResponseField name="$product" type="\SureCart\Models\Product"> The product model object. </ResponseField> </Expandable> </ResponseField> **Disable when using Yoast SEO:** ```php theme={null} add_filter( 'sc_display_product_json_ld_schema', function( $display, $product ) { // Disable SureCart schema when Yoast SEO is active if ( class_exists( 'WPSEO_Frontend' ) || defined( 'WPSEO_VERSION' ) ) { return false; } return $display; }, 10, 2 ); ``` **Disable when using Rank Math:** ```php theme={null} add_filter( 'sc_display_product_json_ld_schema', function( $display, $product ) { // Disable SureCart schema when Rank Math is active if ( class_exists( 'RankMath' ) ) { return false; } return $display; }, 10, 2 ); ``` **Disable for any SEO plugin:** ```php theme={null} // Completely disable SureCart's product schema output add_filter( 'sc_display_product_json_ld_schema', '__return_false' ); ``` ## Yoast SEO Integration SureCart integrates with Yoast SEO to provide proper SEO meta data for product pages. These filters allow you to customize how SureCart interacts with Yoast SEO's presenter system. ### `sc_wpseo_frontend_presenters` Filter the Yoast SEO "presenters" that SureCart uses on product pages. Presenters are Yoast's system for outputting different types of SEO meta tags (title, description, Open Graph, etc.). By default, SureCart uses a subset of Yoast's presenters optimized for product pages. This filter lets you modify which presenters are used, allowing you to add custom meta tags or remove ones you don't need. <ResponseField name="Parameters" type="Filter Parameters"> <Expandable title="properties"> <ResponseField name="$title_presenters" type="array"> Array of presenter class names that SureCart will use for the current page. These are fully qualified Yoast SEO presenter class names. </ResponseField> <ResponseField name="$presenters" type="array"> The full array of all available Yoast SEO presenters, for reference. </ResponseField> </Expandable> </ResponseField> **Add additional Yoast presenters:** ```php theme={null} add_filter( 'sc_wpseo_frontend_presenters', function( $title_presenters, $presenters ) { // Add the robots presenter for custom robot meta handling $title_presenters[] = 'Yoast\\WP\\SEO\\Presenters\\Meta\\Robots_Presenter'; return $title_presenters; }, 10, 2 ); ``` **Remove specific presenters:** ```php theme={null} add_filter( 'sc_wpseo_frontend_presenters', function( $title_presenters, $presenters ) { // Remove Twitter Card presenters if you don't use Twitter $title_presenters = array_filter( $title_presenters, function( $presenter ) { return strpos( $presenter, 'Twitter' ) === false; } ); return array_values( $title_presenters ); }, 10, 2 ); ``` **Use the full set of Yoast presenters:** ```php theme={null} add_filter( 'sc_wpseo_frontend_presenters', function( $title_presenters, $presenters ) { // Use all available Yoast presenters instead of SureCart's subset return $presenters; }, 10, 2 ); ``` ## Use Cases ### Disable Schema for Free Products Free products may not benefit from rich product snippets in search results. You can disable schema output for products with a \$0 price: ```php theme={null} add_filter( 'sc_display_product_json_ld_schema', function( $display, $product ) { // Fetch product with prices relation loaded. $product = \SureCart\Models\Product::with(['prices'])->find( $product->id ); // Don't output schema for free products if ( ! empty( $product->prices->data ) ) { foreach ( $product->prices->data as $price ) { if ( $price->amount === 0 ) { return false; } } } return $display; }, 10, 2 ); ``` ### Disable All SureCart SEO for Third-Party Plugin If you're using an SEO plugin that fully supports custom post types, you may want to disable all of SureCart's SEO output and let your plugin handle everything: ```php theme={null} // Disable meta tags add_filter( 'sc_display_product_seo_meta', '__return_false' ); // Disable JSON-LD schema add_filter( 'sc_display_product_json_ld_schema', '__return_false' ); ``` ### Prevent Indexing of Sale/Promotion URLs If you use query parameters to show promotional pricing or limited-time offers, prevent these variations from being indexed as separate pages: ```php theme={null} add_filter( 'surecart/noindex_query_vars', function( $vars ) { // Promotional and campaign tracking parameters $vars[] = 'promo'; $vars[] = 'sale'; $vars[] = 'coupon'; $vars[] = 'discount'; // UTM tracking parameters (if not already included) $vars[] = 'utm_source'; $vars[] = 'utm_medium'; $vars[] = 'utm_campaign'; $vars[] = 'utm_content'; $vars[] = 'utm_term'; return $vars; } ); ``` ### Disable Schema for Specific Product Types If certain products (like services or digital downloads) shouldn't have Product schema, you can conditionally disable it: ```php theme={null} add_filter( 'sc_display_product_json_ld_schema', function( $display, $product ) { // Fetch product with product_collections relation loaded. $product = \SureCart\Models\Product::with(['product_collections'])->find( $product->id ); // Check if product is in a "services" collection if ( ! empty( $product->product_collections->data ) ) { foreach ( $product->product_collections->data as $collection ) { if ( $collection->slug === 'services' ) { return false; } } } return $display; }, 10, 2 ); ``` ### Use Different OG Image Sizes Based on Product Customize the Open Graph image size based on the product's image dimensions or category: ```php theme={null} add_filter( 'surecart/og:image/size', function( $size ) { $post_id = get_the_ID(); if ( ! $post_id ) { return $size; } // Get the featured image dimensions $image_id = get_post_thumbnail_id( $post_id ); if ( $image_id ) { $image_data = wp_get_attachment_image_src( $image_id, 'full' ); if ( $image_data ) { $width = $image_data[1]; // Use medium_large for very large images to reduce load time if ( $width > 2000 ) { return 'medium_large'; } } } return 'large'; } ); ``` ### Detect and Disable Duplicate SEO Plugins Automatically detect common SEO plugins and disable SureCart's SEO output accordingly: ```php theme={null} add_filter( 'sc_display_product_seo_meta', function( $display, $product ) { // Check for common SEO plugins $seo_plugins_active = ( defined( 'WPSEO_VERSION' ) || // Yoast SEO class_exists( 'RankMath' ) || // Rank Math defined( 'AIOSEO_VERSION' ) || // All in One SEO class_exists( 'SeoPress' ) || // SEOPress defined( 'JEENGINE_VERSION' ) // Jepack SEO ); if ( $seo_plugins_active ) { return false; } return $display; }, 10, 2 ); // Apply the same logic to schema output add_filter( 'sc_display_product_json_ld_schema', function( $display, $product ) { $seo_plugins_active = ( defined( 'WPSEO_VERSION' ) || class_exists( 'RankMath' ) || defined( 'AIOSEO_VERSION' ) || class_exists( 'SeoPress' ) ); if ( $seo_plugins_active ) { return false; } return $display; }, 10, 2 ); ``` ## Related <CardGroup> <Card title="Products" icon="box" href="/documentation/actions-filters/products"> Hook into product lifecycle events. </Card> <Card title="Templates" icon="code" href="/documentation/actions-filters/templates"> Hook into admin and template actions. </Card> </CardGroup> # Subscriptions Source: https://developer.surecart.com/documentation/actions-filters/subscriptions Hook into subscription lifecycle events These actions fire during subscription lifecycle events like renewals. <Note> For handling subscription cancellations and restorations that affect purchase access, see [Purchases](/documentation/actions-filters/purchases). The `surecart/purchase_revoked` and `surecart/purchase_invoked` actions fire when subscriptions are canceled or restored. </Note> ## `surecart/subscription_renewed` Fires when a subscription successfully renews. <ResponseField name="Parameters" type="Action Parameters"> <Expandable title="properties"> <ResponseField name="$subscription" type="\SureCart\Models\Subscription"> The subscription model object. </ResponseField> <ResponseField name="$data" type="object"> The raw event data. </ResponseField> </Expandable> </ResponseField> ```php theme={null} add_action( 'surecart/subscription_renewed', function( $subscription, $data ) { // Fetch the subscription with customer relation loaded. $subscription = \SureCart\Models\Subscription::with(['customer'])->find( $subscription->id ); // Send renewal confirmation. wp_mail( $subscription->customer->email, 'Subscription Renewed', 'Thank you! Your subscription has been renewed.' ); }, 10, 2 ); ``` ## Use Cases ### Send Renewal Thank You Email ```php theme={null} add_action( 'surecart/subscription_renewed', function( $subscription, $data ) { // Fetch subscription with customer, price, and product relations loaded. $subscription = \SureCart\Models\Subscription::with(['customer', 'price', 'price.product'])->find( $subscription->id ); $customer = $subscription->customer; $product = $subscription->price->product ?? null; $product_name = is_object( $product ) ? $product->name : 'your subscription'; $subject = 'Thank you for renewing!'; $message = sprintf( "Hi %s,\n\nThank you for your continued support! Your subscription to %s has been renewed.\n\nNext renewal date: %s\n\nBest regards,\nThe Team", $customer->first_name ?? 'there', $product_name, ! empty( $subscription->current_period_end_at ) ? gmdate( 'F j, Y', $subscription->current_period_end_at ) : 'N/A' ); wp_mail( $customer->email, $subject, $message ); }, 10, 2 ); ``` ### Track Renewals for Analytics ```php theme={null} add_action( 'surecart/subscription_renewed', function( $subscription, $data ) { // Fetch subscription with customer and price relations loaded. $subscription = \SureCart\Models\Subscription::with(['customer', 'price'])->find( $subscription->id ); // Track in Google Analytics if ( function_exists( 'gtag' ) ) { // Server-side tracking wp_remote_post( 'https://www.google-analytics.com/mp/collect', [ 'body' => json_encode([ 'client_id' => $subscription->customer->id, 'events' => [[ 'name' => 'subscription_renewal', 'params' => [ 'subscription_id' => $subscription->id, 'value' => $subscription->price->amount / 100, 'currency' => $subscription->price->currency, ] ]] ]) ]); } }, 10, 2 ); ``` ### Notify Team of High-Value Renewals ```php theme={null} add_action( 'surecart/subscription_renewed', function( $subscription, $data ) { // Fetch subscription with customer and price relations loaded. $subscription = \SureCart\Models\Subscription::with(['customer', 'price'])->find( $subscription->id ); $amount = $subscription->price->amount ?? 0; // Notify for renewals over $500 if ( $amount >= 50000 ) { wp_mail( 'sales@example.com', 'High-Value Renewal', sprintf( 'Customer %s just renewed for $%s!', $subscription->customer->email, number_format( $amount / 100, 2 ) ) ); } }, 10, 2 ); ``` ## Related <CardGroup> <Card title="Purchases" href="/documentation/actions-filters/purchases"> Handle subscription cancellations and restorations via purchase events. </Card> <Card title="Models" href="/documentation/actions-filters/models"> Hook into subscription model events like `canceled` and `restored`. </Card> </CardGroup> # Templates Source: https://developer.surecart.com/documentation/actions-filters/templates Modify blocks, shortcodes, reviews, and inject content into templates ## Modifying Block and Front-End HTML You can modify the HTML output of any SureCart block using WordPress's [`render_block`](https://developer.wordpress.org/reference/hooks/render_block/) filter combined with the [HTML Tag Processor](https://developer.wordpress.org/reference/classes/wp_html_tag_processor/)—a safe, performant way to manipulate HTML without regex or string replacement. ### Finding a Block's Name To target a specific block, you need its name. SureCart blocks use the `surecart/` namespace (e.g., `surecart/product-title`). Here are ways to find a block's name: #### Browser Inspector Inspect the block on the frontend. The wrapper element's class follows the pattern `wp-block-{namespace}-{block-name}`. For example, `wp-block-surecart-product-title` means the block name is `surecart/product-title`. #### Code editor In the block editor, switch to the Code Editor view (⇧⌘⌥M or via Options menu). Block names appear in HTML comments like `<!-- wp:surecart/product-title -->`. #### PHP Use [`get_dynamic_block_names()`](https://developer.wordpress.org/reference/functions/get_dynamic_block_names/) to list all registered dynamic blocks: ```php theme={null} // Log all registered dynamic block names add_action( 'init', function() { error_log( print_r( get_dynamic_block_names(), true ) ); }, 99 ); ``` <Tip> Common SureCart blocks include `surecart/product-title`, `surecart/product-price`, `surecart/buy-button`, `surecart/product-image`, `surecart/product-description`, and `surecart/product-collection`. </Tip> ### Using `render_block` The [`render_block`](https://developer.wordpress.org/reference/hooks/render_block/) filter runs after a block is rendered, giving you access to the final HTML output. You can target specific blocks by checking `$block['blockName']`. ```php theme={null} add_filter( 'render_block', function( $block_content, $block ) { // Only modify SureCart product title blocks if ( 'surecart/product-title' !== $block['blockName'] ) { return $block_content; } // Modify the block content return $block_content; }, 10, 2 ); ``` #### Block-Specific Shorthand For cleaner code, use the [`render_block_{$this->name}`](https://developer.wordpress.org/reference/hooks/render_block_this-name/) filter which only fires for a specific block type—no conditional check needed: ```php theme={null} // This filter ONLY runs for the product-title block add_filter( 'render_block_surecart/product-title', function( $block_content, $block, $instance ) { // Modify the block content directly return $block_content; }, 10, 3 ); ``` ### Using the HTML Tag Processor The [`WP_HTML_Tag_Processor`](https://developer.wordpress.org/reference/classes/wp_html_tag_processor/) class provides a safe way to traverse and modify HTML. It's the recommended approach over regex or string manipulation. ```php theme={null} add_filter( 'render_block_surecart/product-title', function( $block_content, $block, $instance ) { // Create a new processor instance $processor = new WP_HTML_Tag_Processor( $block_content ); // Find the first heading tag and add a custom class if ( $processor->next_tag( 'h2' ) ) { $processor->add_class( 'my-custom-title-class' ); $processor->set_attribute( 'data-custom', 'value' ); } return $processor->get_updated_html(); }, 10, 3 ); ``` ### Block Examples #### Add Custom Data Attributes to Buy Buttons ```php theme={null} add_filter( 'render_block_surecart/buy-button', function( $block_content, $block, $instance ) { $processor = new WP_HTML_Tag_Processor( $block_content ); if ( $processor->next_tag( 'a' ) ) { // Add tracking attributes $processor->set_attribute( 'data-track', 'buy-button-click' ); $processor->set_attribute( 'data-product-id', $block['attrs']['id'] ?? '' ); } return $processor->get_updated_html(); }, 10, 3 ); ``` #### Wrap Product Prices with Custom Markup ```php theme={null} add_filter( 'render_block_surecart/product-price', function( $block_content, $block, $instance ) { // Wrap the entire block output return '<div class="price-wrapper">' . $block_content . '</div>'; }, 10, 3 ); ``` #### Add Low Stock Warning Badge Append a warning badge next to the product title when stock is low. This uses SureCart's built-in `.sc-tag` component classes for consistent styling. ```php theme={null} add_filter( 'render_block_surecart/product-title', function( $block_content, $block, $instance ) { $product = sc_get_product(); // this product does not use stock. if ( empty( $product->stock_enabled ) ) { return $block_content; } // Check if stock is low (e.g., less than 5 remaining) if ( $product->available_stock >= 5 ) { return $block_content; } // Create the warning badge using SureCart's tag component classes $badge = sprintf( '<span class="sc-tag sc-tag--warning sc-tag--small sc-tag--pill">Only %d left!</span>', $product->available_stock ); // Append the badge after the title content return $block_content . $badge; }, 10, 3 ); ``` <Tip> SureCart's `.sc-tag` component supports variants like `--warning`, `--success`, `--danger`, `--info`, and `--primary`, plus sizes `--small`, `--medium`, `--large`, and a `--pill` modifier for rounded corners. </Tip> <Note> The HTML Tag Processor is available in WordPress 6.2+. For older versions, consider using [DOMDocument](https://www.php.net/manual/en/class.domdocument.php) or carefully crafted string replacements. </Note> ## Block Pattern Filters ### `surecart/blocks/pattern_categories` Filter the available block pattern categories. ```php theme={null} add_filter( 'surecart/blocks/pattern_categories', function( $categories ) { $categories['my-category'] = [ 'label' => 'My Custom Category', ]; return $categories; } ); ``` ### `surecart/blocks/patterns` Filter the registered block patterns. ```php theme={null} add_filter( 'surecart/blocks/patterns', function( $patterns ) { // Add custom pattern $patterns[] = 'my-custom-pattern'; // Or remove a pattern $patterns = array_diff( $patterns, [ 'pattern-to-remove' ] ); return $patterns; } ); ``` ### `surecart_block_output` Filter the rendered output of SureCart blocks. ```php theme={null} add_filter( 'surecart_block_output', function( $output ) { // Wrap all blocks in a custom container return '<div class="my-block-wrapper">' . $output . '</div>'; } ); ``` ## Page Builder Filters ### `sc_elementor_templates` Filter available Elementor templates. ```php theme={null} add_filter( 'sc_elementor_templates', function( $templates ) { // Add or remove templates return $templates; } ); ``` ## Shortcode Filters ### `surecart/shortcode/render` Filter the rendered shortcode output. <ResponseField name="Parameters" type="Filter Parameters"> <Expandable title="properties"> <ResponseField name="$content" type="string"> The rendered shortcode HTML content. </ResponseField> <ResponseField name="$atts" type="array"> Shortcode attributes passed by the user. </ResponseField> <ResponseField name="$name" type="string"> The shortcode name. </ResponseField> <ResponseField name="$form" type="\WP_Post"> The form post object being rendered. </ResponseField> </Expandable> </ResponseField> ```php theme={null} add_filter( 'surecart/shortcode/render', function( $content, $atts, $name, $form ) { // Wrap output in custom container return '<div class="my-wrapper">' . $content . '</div>'; }, 10, 4 ); ``` ## Review Filters ### `surecart/review_count/enabled` Control whether review counts are displayed. ```php theme={null} add_filter( 'surecart/review_count/enabled', function( $enabled ) { // Disable review counts return false; } ); ``` ### `surecart/review_form/enabled` Control whether the review form is displayed. ```php theme={null} add_filter( 'surecart/review_form/enabled', function( $enabled ) { // Disable reviews for guests return is_user_logged_in(); } ); // Or require purchase to leave review add_filter( 'surecart/review_form/enabled', function( $enabled ) { if ( ! is_user_logged_in() ) { return false; } // Check if user has purchased this product // Add your purchase check logic here return $enabled; } ); ``` ### `surecart/review_average/enabled` Control whether average rating is displayed. ```php theme={null} add_filter( 'surecart/review_average/enabled', function( $enabled ) { return $enabled; } ); ``` ### `surecart/review_stars/enabled` Control whether star ratings are displayed. ```php theme={null} add_filter( 'surecart/review_stars/enabled', function( $enabled ) { // Use numbers instead of stars return false; } ); ``` ### `sc_anonymous_reviewer_name` Filter the display name for anonymous reviewers. ```php theme={null} add_filter( 'sc_anonymous_reviewer_name', function( $name ) { return 'Verified Buyer'; } ); // Or with localization add_filter( 'sc_anonymous_reviewer_name', function( $name ) { return __( 'Verified Customer', 'my-theme' ); } ); ``` ### Require Purchase for Reviews ```php theme={null} add_filter( 'surecart/review_form/enabled', function( $enabled ) { if ( ! is_user_logged_in() ) { return false; } global $post; $user_id = get_current_user_id(); $customer_id = get_user_meta( $user_id, 'sc_customer_id', true ); if ( ! $customer_id ) { return false; } // Check if user has purchased this product $purchases = \SureCart\Models\Purchase::where([ 'customer_ids' => [ $customer_id ], 'product_ids' => [ get_post_meta( $post->ID, 'sc_id', true ) ], ])->get(); return ! empty( $purchases ); } ); ``` ## Template Actions These actions allow you to inject content into SureCart templates and pages. ### `surecart_buy_page_body_open` Fired at the start of the buy page body. Use this to add announcements, banners, or tracking scripts. ```php theme={null} add_action( 'surecart_buy_page_body_open', function() { echo '<div class="announcement-bar">Special offer: 20% off!</div>'; } ); ``` ### `surecart_template_dashboard_body_open` Fired at the start of the customer dashboard template body. ```php theme={null} add_action( 'surecart_template_dashboard_body_open', function() { if ( is_user_logged_in() ) { $user = wp_get_current_user(); echo '<div class="welcome-message">Welcome back, ' . esc_html( $user->display_name ) . '!</div>'; } } ); ``` ### `surecart_template_blank_body_open` Fired at the start of the blank template body. ```php theme={null} add_action( 'surecart_template_blank_body_open', function() { // Add custom tracking scripts ?> <script> // Your tracking code here </script> <?php } ); ``` ## Page & Post Actions ### `surecart/post_created` Fired when SureCart seeds pages (checkout page, shop page, dashboard page, checkout forms) during installation. <ResponseField name="Parameters" type="Action Parameters"> <Expandable title="properties"> <ResponseField name="$page_id" type="int"> The WordPress page ID. </ResponseField> <ResponseField name="$page_data" type="array"> The page data used to create the page including title, content, and template. </ResponseField> </Expandable> </ResponseField> ```php theme={null} add_action( 'surecart/post_created', function( $page_id, $page_data ) { // Add custom meta to the page update_post_meta( $page_id, '_custom_template', 'full-width' ); // Set page to full-width if using a theme that supports it update_post_meta( $page_id, '_genesis_layout', 'full-width-content' ); }, 10, 2 ); ``` ## Use Cases ### Add Tracking Pixels ```php theme={null} add_action( 'surecart_buy_page_body_open', function() { ?> <!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', 'YOUR_PIXEL_ID'); fbq('track', 'PageView'); </script> <?php } ); ``` ### Custom Dashboard Header ```php theme={null} add_action( 'surecart_template_dashboard_body_open', function() { $user = wp_get_current_user(); $purchases_count = count( \SureCart::purchases()->where( 'customer_ids' => [ get_user_meta( $user->ID, 'sc_customer_id', true ) ] )->get() ); ?> <div class="dashboard-stats"> <p>You have <?php echo esc_html( $purchases_count ); ?> active purchases.</p> </div> <?php } ); ``` ## Related <CardGroup> <Card title="Media" icon="photo-film" href="/documentation/actions-filters/media"> Customize video and image display. </Card> <Card title="Admin" icon="gear" href="/documentation/actions-filters/admin"> Customize admin menus and toolbars. </Card> </CardGroup> # Overview Source: https://developer.surecart.com/documentation/actions-reference Extend and customize SureCart with WordPress hooks SureCart provides extensive WordPress hooks (actions and filters) that allow you to extend and customize its functionality. Use these hooks to build integrations, modify behavior, and customize the shopping experience. ## Actions & Filters by Topic <CardGroup> <Card title="Purchases" icon="bag-shopping" href="/documentation/actions-filters/purchases"> Hook into purchase lifecycle events like creation, access grants, and revocations. </Card> <Card title="Checkout" icon="credit-card" href="/documentation/actions-filters/checkout"> Validate checkout forms, customize payment modes, and track conversions. </Card> <Card title="Cart" icon="cart-shopping" href="/documentation/actions-filters/cart"> Customize cart icon visibility and behavior. </Card> <Card title="Login" icon="right-to-bracket" href="/documentation/actions-filters/login"> Customize login redirects and authentication behavior. </Card> <Card title="Products" icon="box" href="/documentation/actions-filters/products"> Respond to product creation, updates, deletion, and stock changes. </Card> <Card title="Prices" icon="tag" href="/documentation/actions-filters/prices"> Hook into price creation, updates, and deletion events. </Card> <Card title="Customers" icon="user" href="/documentation/actions-filters/customers"> Respond to customer profile updates and sync with external systems. </Card> <Card title="Subscriptions" icon="repeat" href="/documentation/actions-filters/subscriptions"> Hook into subscription renewals and lifecycle events. </Card> <Card title="Orders" icon="receipt" href="/documentation/actions-filters/orders"> Respond to orders, charges, refunds, and invoices. </Card> <Card title="Models" icon="database" href="/documentation/actions-filters/models"> Hook into model lifecycle events like create, update, and delete. </Card> <Card title="Integrations" icon="puzzle-piece" href="/documentation/actions-filters/integrations"> Build integrations that respond to purchases and refunds. </Card> <Card title="Templates" icon="code" href="/documentation/actions-filters/templates"> Inject content into SureCart templates and admin pages. </Card> <Card title="Requests" icon="arrow-right-arrow-left" href="/documentation/actions-filters/requests"> Modify API requests, endpoints, and responses. </Card> <Card title="Currency" icon="dollar-sign" href="/documentation/actions-filters/currency"> Customize currency formatting, locales, and display. </Card> <Card title="Media" icon="image" href="/documentation/actions-filters/media"> Customize media handling and image display. </Card> <Card title="Errors" icon="triangle-exclamation" href="/documentation/actions-filters/errors"> Customize error handling and messages. </Card> <Card title="Admin" icon="gear" href="/documentation/actions-filters/admin"> Customize admin menus, toolbars, and list tables. </Card> <Card title="SEO" icon="magnifying-glass" href="/documentation/actions-filters/seo"> Customize SEO metadata and structured data. </Card> </CardGroup> ## Building Integrations <Card title="Orders & Purchases Guide" icon="book" href="/documentation/orders-and-purchases"> Build full-featured integrations using SureCart's Integration class. Handles purchases, refunds, upgrades, downgrades, and quantity changes automatically. </Card> # Cart & Checkout Source: https://developer.surecart.com/documentation/add-to-cart Add products to cart programmatically and customize checkout forms SureCart provides multiple ways to add items to the cart programmatically: 1. **URL Parameters** - Redirect users to checkout with pre-filled line items 2. **Shortcodes** - Use built-in shortcodes for add-to-cart buttons 3. **Checkout Form Customization** - Add custom fields, checkboxes, or content <Info> For a complete reference of available hooks, see the [Cart Hooks](/documentation/actions-filters/cart) and [Checkout Hooks](/documentation/actions-filters/checkout) documentation. </Info> *** ## URL Parameters The most straightforward way to add items to cart is by redirecting users to the checkout page with `line_items` query parameters. ### Basic Example ```php theme={null} <?php $checkout_url = add_query_arg( [ 'line_items' => [ [ 'price_id' => 'price_xxxxxxxxxxxxx', // Your SureCart price ID 'quantity' => 1, ], ], ], \SureCart::pages()->url( 'checkout' ) ); ?> <a href="<?php echo esc_url( $checkout_url ); ?>"> Add to Cart </a> ``` ### Multiple Items ```php theme={null} <?php $checkout_url = add_query_arg( [ 'line_items' => [ [ 'price_id' => 'price_product_one', 'quantity' => 1, ], [ 'price_id' => 'price_product_two', 'quantity' => 2, ], ], ], \SureCart::pages()->url( 'checkout' ) ); ?> ``` ### With Coupon Code ```php theme={null} <?php $checkout_url = add_query_arg( [ 'line_items' => [ [ 'price_id' => 'price_xxxxxxxxxxxxx', 'quantity' => 1, ], ], 'coupon' => 'SAVE10', // Promotion code ], \SureCart::pages()->url( 'checkout' ) ); ?> ``` ### With Product Variant ```php theme={null} <?php $checkout_url = add_query_arg( [ 'line_items' => [ [ 'price_id' => 'price_xxxxxxxxxxxxx', 'quantity' => 1, 'variant_id' => 'variant_xxxxxxxxxxxxx', // Optional variant ], ], ], \SureCart::pages()->url( 'checkout' ) ); ?> ``` *** ## Shortcodes SureCart provides built-in shortcodes for adding products to cart. ### Add to Cart Button ``` [sc_product_cart_button id="prod_xxxxxxxxxxxxx" text="Add To Cart"] ``` <ResponseField name="Parameters" type="Shortcode Parameters"> <Expandable title="properties"> <ResponseField name="id" type="string"> Product ID. </ResponseField> <ResponseField name="text" type="string"> Button text. Default: "Add To Cart" </ResponseField> <ResponseField name="width" type="integer"> Button width in pixels. </ResponseField> <ResponseField name="add_to_cart" type="boolean"> Whether to add to cart or go directly to checkout. </ResponseField> </Expandable> </ResponseField> ### Buy Button with Line Items ``` [sc_buy_button] [sc_line_item price_id="price_xxxxxxxxxxxxx" quantity="1"] [/sc_buy_button] ``` ### Multiple Line Items ``` [sc_buy_button] [sc_line_item price_id="price_product_one" quantity="1"] [sc_line_item price_id="price_product_two" quantity="2"] [/sc_buy_button] ``` ### Using Shortcodes in PHP You can render shortcodes programmatically in PHP using WordPress's `do_shortcode` function. ```php theme={null} <?php echo do_shortcode( '[sc_product_cart_button id="prod_xxxxxxxxxxxxx" text="Buy Now"]' ); ?> ``` For buy buttons with multiple line items: ```php theme={null} <?php echo do_shortcode( ' [sc_buy_button] [sc_line_item price_id="price_product_one" quantity="1"] [sc_line_item price_id="price_product_two" quantity="2"] [/sc_buy_button] ' ); ?> ``` *** ## Checkout Form Customization Add custom fields, checkboxes, or content to checkout forms using the `render_block` filter. This example walks you through adding a terms checkbox with server-side validation. <Steps> <Step title="Add custom content before the submit button"> Use the `render_block` filter to inject HTML before any checkout block. Target the block by checking `$block['blockName']`. ```php theme={null} add_filter( 'render_block', function( $block_content, $block ) { if ( 'surecart/submit' !== $block['blockName'] ) { return $block_content; } $checkbox = '<div class="my-terms-checkbox" style="margin-bottom: 1em;"> <label style="display: flex; align-items: start; gap: 0.5em; cursor: pointer;"> <input type="checkbox" name="accept_terms" value="yes" required /> <span>I agree to the <a href="/terms" target="_blank">terms and conditions</a></span> </label> </div>'; return $checkbox . $block_content; }, 10, 2 ); ``` </Step> <Step title="Add server-side validation"> Validate custom fields using the `surecart/checkout/validate` filter. Return errors to prevent checkout submission. ```php theme={null} add_filter( 'surecart/checkout/validate', function( $errors, $args, $request ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing $accept_terms = isset( $_POST['accept_terms'] ) ? sanitize_text_field( wp_unslash( $_POST['accept_terms'] ) ) : ''; if ( 'yes' !== $accept_terms ) { $errors->add( 'terms_required', 'You must accept the terms and conditions.' ); } return $errors; }, 10, 3 ); ``` See [Checkout Hooks](/documentation/actions-filters/checkout#form-validation) for more validation examples. </Step> </Steps> ### Checkout Block Names | Block Name | Description | | --------------------- | ------------------------ | | `surecart/submit` | Submit/Pay button | | `surecart/email` | Email field | | `surecart/name` | Full name field | | `surecart/first-name` | First name field | | `surecart/last-name` | Last name field | | `surecart/phone` | Phone number field | | `surecart/address` | Address fields | | `surecart/payment` | Payment method selection | | `surecart/coupon` | Coupon code field | | `surecart/line-items` | Order line items | | `surecart/totals` | Order totals summary | *** ## Related <CardGroup> <Card title="Cart Hooks" icon="cart-shopping" href="/documentation/actions-filters/cart"> Customize cart icon, visibility, and behavior. </Card> <Card title="Checkout Hooks" icon="credit-card" href="/documentation/actions-filters/checkout"> Hook into checkout events and customize validation. </Card> </CardGroup> # Admin UI Source: https://developer.surecart.com/documentation/admin-ui If you want to add custom UI elements to admin pages of SureCart like Order, Product, Customer, Affiliate pages etc. you can use this API to add either in the Main or the Sidebar area. # Page Metaboxes To add metaboxes to individual pages, you will need to register an addon, client-side using react. This lets you render whatever you want in the metabox, hook into page content, or display whatever you want in the sidebar. ### Registering an Addon To add a custom addon, you need to call the `registerAddon` function. This function can be accessed from the `window.surecart` object. It accepts 2 parameters, `name` & `settings`. ```javascript theme={null} import SidebarComponent from "./SidebarComponent"; window.surecart.registerAddon("custom-sidebar", { render: () => <SidebarComponent />, scope: "sidebar", title: "Custom Sidebar Box", }); ``` #### registerAddon(name, settings) <ParamField type="string"> The name of the addon. </ParamField> <ResponseField name="settings" type="object"> <Expandable title="properties"> <ParamField type="HTML"> Pass what needs to be rendered. It can be HTML or a React component. </ParamField> <ParamField type="string"> Context where you want to render the addon. It can be `main` or `sidebar`. </ParamField> <ParamField type="string"> Title for your addon Box, if not passed this defaults to the name of your addon </ParamField> </Expandable> </ResponseField> ### Getting Page Data SureCart uses [WordPress Core Data](https://developer.wordpress.org/block-editor/reference-guides/data/data-core/) (WordPress' flavor of Redux) to store data. This means you can use familiar WordPress redux functions to get SureCart data. #### Get The Current Page ID In order to query page data, you need to get the current page id. This function is available in the global `window.surecart` object. ```javascript theme={null} const id = window.surecart.getCurrentPageId(); ``` #### Query Page Data You can use the `useSelect` function to query page data. If we are on the order page, we can get the order data from the id. #### Querying an Order ```javascript theme={null} import { useSelect } from "@wordpress/data"; import { store } from "@wordpress/core-data"; // fetch or get the order data from redux. const order = useSelect( (select) => select(store).getEntityRecord("surecart", "order", id, { // expand any nested resources you need. expand: ["checkout"], }), // the id from the previous function [id] ); ``` #### Querying A Product ```javascript theme={null} import { useSelect } from "@wordpress/data"; import { store } from "@wordpress/core-data"; // fetch or get the order data from redux. const product = useSelect( (select) => select(store).getEntityRecord("surecart", "product", id, { // expand any nested resources you need. expand: ["prices", "variants"], }), // the id from the previous function [id] ); // get nested prices. const prices = product?.prices; ``` ### Order Page Example In this example we are adding a custom order display. We are using some WordPress redux functions to query orders and display them in a custom way. ```javascript expandable theme={null} import { useSelect } from "@wordpress/data"; import { store as coreStore } from "@wordpress/core-data"; export default () => { const getCurrentPage = window.surecart.getCurrentPage; const getCurrentPageId = window.surecart.getCurrentPageId; const id = getCurrentPageId(); const page = getCurrentPage(); if (page !== "sc-orders") { return null; } const { order, hasLoadedOrder, orderError } = useSelect( (select) => { const queryArgs = [ "surecart", "order", id, { expand: [ "checkout", "checkout.charge", "checkout.customer", "checkout.tax_identifier", "checkout.payment_failures", "checkout.shipping_address", "checkout.billing_address", "checkout.discount", "checkout.line_items", "checkout.selected_shipping_choice", "checkout.invoice", "shipping_choice.shipping_method", "discount.promotion", "line_item.price", "line_item.fees", "line_item.variant", "customer.balances", "price.product", "product.featured_product_media", "product.product_medias", "product_media.media", "variant.image", ], }, ]; return { order: select(coreStore)?.getEntityRecord?.(...queryArgs), hasLoadedOrder: select(coreStore)?.hasFinishedResolution?.( "getEntityRecord", [...queryArgs] ), orderError: select(coreStore)?.getResolutionError?.( "getEntityRecord", ...queryArgs ), }; }, [id] ); return ( <div> <h1>Orders - Stats</h1> {/* Use the order to display stats. */} </div> ); }; ``` # Admin List Tables SureCart provides the ability to customize the list table views in its admin pages—like Orders, Products, Invoices, and more—by adding custom columns. This can help you display additional information relevant to your store’s workflow, at-a-glance, without needing to open individual records. ### Adding Custom Columns Since we are using WordPress tables, you can use the `manage_{$post_type}_posts_columns` functions [WordPress provides](https://developer.wordpress.org/reference/hooks/manage_post_type_posts_columns/) to add custom columns. The `page` is the page query parameter found in the url. <Steps> <Step title="Add the column"> First we need to add our column to the list of columns. ```php theme={null} // sc-orders, sc-products, etc. which are found in the url. add_filter( 'manage_sc-products_columns', 'my_custom_column' ); // Add a new column labeled "Metabox." function my_custom_column( $columns ) { $columns['metabox'] = 'Metabox'; return $columns; } ``` </Step> <Step title="Add the column content"> Next we need to add the content for our column. ```php theme={null} // sc-orders, sc-products, etc. which are found in the url. add_action( 'manage_sc-products_custom_column', 'my_custom_column_content', 10, 2 ); function my_custom_column_content( $column_name, $data ) { // $data is the model object for the current row in the table. if ( 'metabox' === $column_name ) { // Replace this with whatever you want to display from $data. echo esc_html( $data->id ); } } ``` </Step> </Steps> This lets you add any custom content to the admin list tables, while still providing access to the underlying data. # Shop Loops Source: https://developer.surecart.com/documentation/custom-loops Querying products utilizes the "WordPress Loop". This makes things nice and familiar if you are already familiar with WordPress queries. In order to get products, you will want to to specify the `sc_product` post type in the query. ## Simple Query Example Here is a query example. To query the posts, you will need to specify `sc_product` as the post type. ```php php theme={null} $products = new WP_Query( array( 'post_type' => 'sc_product', 'posts_per_page' => 10, ) ); ``` ### Querying Product Posts This will return a posts query. You can show the the title (the product name) and the excerpt (the product description) for example. ```php php theme={null} $products = new WP_Query( array( 'post_type' => 'sc_product', 'posts_per_page' => 10, ) ); if ( $products->have_posts() ) : while ( $products->have_posts() ) : $products->the_post(); // this is a very important line! the_title(); // the product name. the_excerpt(); // the product description. endwhile; endif; ``` ## Getting Product Data From The Post However, you will likely want to display the product data, such as the price amount, whether it is out of stock, and more. You can do that in several ways. ### In the loop Since we are already in the loop, and have called `$products->the_post()`, you can use `sc_get_product()` to fetch the current posts' product: ```php php theme={null} $products = new WP_Query( array( 'post_type' => 'sc_product', 'posts_per_page' => 10, ) ); if ( $products->have_posts() ) : while ( $products->have_posts() ) : $products->the_post(); // this is a very important line! $product = sc_get_product(); echo esc_html( $product->display_amount ); endwhile; endif; ``` ### Outside the loop However, if you are not in the loop, you can still use the sc\_get\_product function, and pass a post or post id: ```php theme={null} $posts = get_posts( array( 'post_type' => 'sc_product', 'posts_per_page' => 10, ) ); foreach($posts as $post) { $product = sc_get_product( $post ); echo esc_html( $product->display_amount ); } ``` ### Full Example ```php php theme={null} // query products by "sc_product" post type. $products = new WP_Query( array( 'post_type' => 'sc_product', 'posts_per_page' => 10, ) ); // loop through products. if ( $products->have_posts() ) : while ( $products->have_posts() ) : // this sets up post data for the_title(), the_content(), etc. // it also prepares the global $sc_product object. $products->the_post(); // display the title. the_title(); // display the product description. the_excerpt(); // get the current post's product (e.g. display_amount, prices, variations, etc.). $product = sc_get_product(); // display the amount. echo esc_html( $product->display_amount ); // show if out of stock. if ( $product->is_out_of_stock ) { echo 'Out of stock!'; } // show if low stock. if ( $product->is_low_stock ) { echo 'Only ' . (int) $product->available_stock . ' left!'; } endwhile; endif; ``` <br /> ## Querying Variant Options You can also query by a variant option or multiple variant options by using the `variant_options` parameter. ### Querying a single variant option Querying products by option: ```php theme={null} $products = new WP_Query( [ 'post_type' => 'sc_product', 'posts_per_page' => 10, 'variant_options' => [ [ 'name' => 'Color', 'values' => 'Orange' ] ] ] ); ``` ### Querying multiple variant options When querying multiple variant options, you will want to pass a `relation` argument, to let the query know if these options are inclusive or exclusive. Here's an example to get products that are small and orange. ```php theme={null} $products = new WP_Query( [ 'post_type' => 'sc_product', 'posts_per_page' => 10, 'variant_options' => [ 'relation' => 'AND' [ 'name' => 'Color', 'values' => 'Orange' ], [ 'name' => 'Size', 'values' => 'Small' ] ] ] ); ``` Whereas here is an example to get products that are small, medium **OR** orange: ```php theme={null} $products = new WP_Query( [ 'post_type' => 'sc_product', 'posts_per_page' => 10, 'variant_options' => [ 'relation' => 'OR' [ 'name' => 'Color', 'values' => 'Orange' ], [ 'name' => 'Size', 'values' => ['Small', 'Medium'] ] ] ] ); ``` # Orders & Purchases Source: https://developer.surecart.com/documentation/orders-and-purchases Integrating with sophisticated pricing structures can be complex. SureCart abstracts away many of the complexities of integrating with a purchase. This is done by extending our integration PHP class and providing the necessary functionality for a purchase's life-cycle events. In short, you do not need to know or even understand how the entire SureCart system works. Instead, you can use a declarative approach and implement what you want to do when a purchase is created, invoked, or revoked. ## Purchases A purchase is the state of what a customer currently should have "access" to. This includes one-time prices, subscriptions or installment plans. A purchase is directly tied 1:1 to a product, price and optionally a variant. ```mermaid theme={null} flowchart TD A[Order] -->B(Checkout) B -->|Purchase| D[Product A] B -->|Purchase| E[Product B] B -->|Purchase| F[Product C] ``` # Purchase Lifecycle A purchase has 3 lifecycle events: created, invoked, and revoked. Each event has a corresponding action that can be implemented in your integration. ### Purchase Created A purchase is created the first time a customer completes an order, or when a person upgrades or downgrades a subscription. A purchase can also be created when a customer makes a one-time purchase. Typically, this is when an integration provides "access" to something. ### Purchase Revoked A purchase can be revoked either manually by the Merchant or automatically. A purchase can be manually revoked if it is a one-time purchase. The merchant will see a "Revoke" button next to the purchase in the Merchant's admin panel. A purchase can also be automatically revoked. This can happen when a subscription is canceled or expired, but it can also occur when a customer changes their subscription plan, through an upgrade or downgrade, for instance. While a new purchase will be created, the old purchase will be revoked. ```mermaid theme={null} flowchart TD A[Order] -->|Refunded|B(Checkout) B -->|Product A| D[Purchase Revoked] B -->|Product B| E[Purchase Revoked] B -->|Product C| F[Purchase Revoked] ``` <Note> When a merchant revokes a purchase that is tied to a subscription, the subscription will be canceled when the purchase is revoked. </Note> ### Purchase Invoked A purchase is 'invoked' when a purchase has been previously revoked and then un-revoked. This is useful when a merchant wants to trigger a specific action when a purchase is reinstated, but not necessarily when it is first created. A great example of this is a welcome email. Typically, you only want to send a welcome email the first time someone purchases a product, not when it is reinstated after being revoked. Merchants cannot manually invoke a purchase tied to a canceled subscription. Instead, they must have the customer make a new purchase to create a new subscription. To simplify, standardize, and ensure reliability in integrating with purchases, we offer a base class that you can extend for your integration. This class and the associated interfaces require you to provide essential details and methods to override for handling various purchase model lifecycle events. In most cases, you can complete the entire integration within a single class or file. Extending this class also enables SureCart to display your integration in different user interfaces, allowing merchants to select it from a list of available integrations. ## Example: Creating A User Role Switcher In this example, we will create a user role switcher integration. In this integration, when a purchase is created or invoked, we will assign a specific role to the customer. When a purchase is revoked, we will remove that role. <Note title="Example Only"> SureCart already includes this integration by default. We're providing this as an example so you can understand how to build your own integrations if needed. </Note> <Steps> <Step title="Extend IntegrationService"> First, let's extend the IntegrationService class. ```php theme={null} <?php namespace MyPlugin\Integrations; use SureCart\Integrations\Contracts\IntegrationInterface; use SureCart\Integrations\Contracts\PurchaseSyncInterface; use SureCart\Integrations\IntegrationService; class UserRoleChangeIntegration extends IntegrationService implements IntegrationInterface, PurchaseSyncInterface { } ``` </Step> <Step title=" Set the integration details"> Next, let's provide the details of our integration. ```php theme={null} /** * The name for the integration. * Names have to be structured as namespace/integration-name, where namespace is the name of your plugin or theme. * * @return string */ public function getName() { return 'my-plugin/user-role-change'; } /** * Get the SureCart model used for the integration. * Only 'product' is supported at this time. * * @return string */ public function getModel() { return 'product'; } /** * Get the integration logo url. * This url needs to be an absolute url to png, jpg, webp or svg. * * @return string */ public function getLogo() { return esc_url_raw( trailingslashit( plugin_dir_url( __FILE__ ) ) . 'icon.svg' ); } /** * The display name for the integration in the dropdown. * This is displayed in a dropdown menu when a merchant selects an integration. * * @return string */ public function getLabel() { return __( 'Change WordPress User Role', 'surecart' ); } /** * The label for the integration item that will be chosen. * This is displayed in the second dropdown after a person selects your integration. * * @return string */ public function getItemLabel() { return __( 'Change User Role', 'surecart' ); } /** * Help text for the integration item chooser. * Additional help text for the integration item chooser. * * @return string */ public function getItemHelp() { return __( 'Change the user role of the user who purchased the product.', 'surecart' ); } ``` </Step> <Step title="Populate the integration item chooser"> To ensure that the integration is displayed in the integration chooser, two functions must be provided: `getItems` and `getItem`. These functions are essential for populating the integration item chooser and enabling SureCart to retrieve individual items. Items can be thought of as individual records. In this example, an item represents a role. If you were to build an integration with a specific post type, for example, the item would be a list of your post type posts. Individual items are expected to be in this format: ```php theme={null} [ 'id' => 'item_id', // this is stored as the integration model's integration_id property. 'label' => 'Item Label', // this is shown as a display name for the user for the item. ] ``` #### GetItems Let's create a `getItems` method and map all user roles to an array of item choices. As with the above, we want the savable `id` to be the role name, and the label to be the role display name. The search term is also passed, so you can make sure you are querying relevant results. Since we return all roles, we do not need this term, but it would be helpful for querying posts, for example. ```php theme={null} ... /** * Get item listing for the integration. * These are a list of item the merchant can choose from when adding an integration. * * @param array $items The integration items. * @param string $search The search term. * * @return array The items for the integration. */ public function getItems( $items = [], $search = '' ) { $roles = []; $editable_roles = wp_roles()->roles; foreach ( $editable_roles as $role => $details ) { $sub['id'] = esc_attr( $role ); $sub['label'] = translate_user_role( $details['name'] ); $roles[ $role ] = $sub; } return $roles; } ... ``` #### GetItem The IntegrationInterface requires a `getItem` function. This function should return a single item choice, which is a single array in the item format noted above. In our case, we expect the `id` to be the role name, as that is what we defined in the `getItems` method. ```php theme={null} /** * Get the individual item. * * @param string $id The item role. * * @return array The item for the integration. */ public function getItem( $id ) { return [ 'id' => $id, 'label' => wp_roles()->get_names()[ $id ], ]; } ``` </Step> <Step title="Change the role on Purchase lifecycle events"> Next, we'll implement the required functions for the `PurchaseSyncInterface`. These functions are run when a purchase lifecycle event takes place and will allow us to modify the user's role. The parameter `$integration` contains an `integration_id` attribute. This is the same `id` that you've set above in the `getItem` and `getItems` methods. ```php theme={null} ... /** * Add the role when the purchase is created. * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseCreated( $integration, $wp_user ) { // make sure the role exists. $role_object = get_role( $integration->integration_id ); if ( ! $role_object ) { return; } // add the role return $wp_user->add_role( $integration->integration_id ); } /** * Add the role when the purchase is invoked * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseInvoked( $integration, $wp_user ) { // make sure the role exists. $role_object = get_role( $integration->integration_id ); if ( ! $role_object ) { return; } // add the role return $wp_user->add_role( $integration->integration_id ); } /** * Remove a user role when the purchase is revoked. * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseRevoked( $integration, $wp_user ) { // make sure the role exists. $role_object = get_role( $integration->integration_id ); if ( ! $role_object ) { return; } // add the role return $wp_user->remove_role( $integration->integration_id ); } ... ``` This code can be further simplified for better readability and maintainability, as shown in the complete example below. However, the provided code gives you a basic idea of how to implement purchase syncing. There are also other optional methods for handling specific purchase changes. For instance, if you want to modify something when the purchase quantity changes, you can use the `onPurchaseQuantityUpdated` method: #### Quantity Changed ```php theme={null} /** * Method to run when the quantity updates. * * @param integer $quantity The new quantity. * @param integer $previous_quantity The previous quantity. * @param Purchase $purchase The purchase. * @param array $request The request. * * @return void */ public function onPurchaseQuantityUpdated( $quantity, $previous_quantity, $purchase, $request ) { // we are not using this, but you could if the purchase quantity is updated. } ``` If you want to perform specific actions when a purchase's product changes, such as when a subscription plan changes, you can utilize the `onPurchaseProductAdded` and `onPurchaseProductRemoved` methods. If you don't define these methods, by default, the `onPurchaseCreated` function and `onPurchaseRevoked` function will be called when a purchase is added or removed, respectively. #### Product Added or Removed ```php theme={null} /** * When a product is added to a purchase. This can happen if a purchase is updated with a new product. * THIS IS OPTIONAL. If you don't implement this method, the onPurchaseCreated method will be called. * * @param integer $quantity The new quantity. * @param integer $previous The previous quantity. * @param Purchase $purchase The purchase. * @param array $request The request. * * @return void */ public function onPurchaseProductAdded( $quantity, $previous, $purchase, $request ) { // if you do not add this, it will default to onPurchaseCreated } /** * When a product is removed from purchase. This can happen if a purchase is updated with a new product. * THIS IS OPTIONAL. If you don't implement this method, the onPurchaseRevoked method will be called. * * @param integer $quantity The new quantity. * @param integer $previous The previous quantity. * @param Purchase $purchase The purchase. * @param array $request The request. * * @return void */ public function onPurchaseProductRemoved( $quantity, $previous, $purchase, $request ) { // if you do not add this, it will default to onPurchaseRevoked } ``` </Step> <Step title="Bootstrap the integration"> The final step in integrating your custom purchase syncing logic is to bootstrap your integration. This involves creating a new instance of your integration class and calling the bootstrap function to initialize it. ```php theme={null} (new \MyPlugin\Integrations\UserRoleChangeIntegration())->bootstrap(); ``` </Step> </Steps> ## Full Example Below is the complete example with some refactoring to provide you with a comprehensive idea of how to implement a complete integration: ```php expandable theme={null} <?php namespace MyPlugin\Integrations; use SureCart\Integrations\Contracts\IntegrationInterface; use SureCart\Integrations\Contracts\PurchaseSyncInterface; use SureCart\Integrations\IntegrationService; /** * Controls the LearnDash integration. */ class UserRoleChangeIntegration extends IntegrationService implements IntegrationInterface, PurchaseSyncInterface { /** * Get the slug for the integration. * * @return string */ public function getName() { return 'my-plugin/user-role-change'; } /** * Get the SureCart model used for the integration. * Only 'product' is supported at this time. * * @return string */ public function getModel() { return 'product'; } /** * Get the integration logo url. * This can be to a png, jpg, or svg for example. * * @return string */ public function getLogo() { return esc_url_raw( trailingslashit( plugin_dir_url( __FILE__ ) ) . 'icon.svg' ); } /** * The display name for the integration in the dropdown. * * @return string */ public function getLabel() { return __( 'Change WordPress User Role', 'surecart' ); } /** * The label for the integration item that will be chosen. * * @return string */ public function getItemLabel() { return __( 'Change User Role', 'surecart' ); } /** * Help text for the integration item chooser. * * @return string */ public function getItemHelp() { return __( 'Change the user role of the user who purchased the product.', 'surecart' ); } /** * Get item listing for the integration. * These are a list of item the merchant can choose from when adding an integration. * * @param array $items The integration items. * @param string $search The search term. * * @return array The items for the integration. */ public function getItems( $items = [], $search = '' ) { $roles = []; $editable_roles = wp_roles()->roles; foreach ( $editable_roles as $role => $details ) { $sub['id'] = esc_attr( $role ); $sub['label'] = translate_user_role( $details['name'] ); $roles[ $role ] = $sub; } return $roles; } /** * Get the individual item. * * @param string $role The item role. * * @return array The item for the integration. */ public function getItem( $role ) { return [ 'id' => $role, 'label' => wp_roles()->get_names()[ $role ], ]; } /** * Add the role when the purchase is created. * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseCreated( $integration, $wp_user ) { $this->toggleRole( $integration->integration_id, $wp_user, true ); } /** * Add the role when the purchase is invoked * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseInvoked( $integration, $wp_user ) { $this->onPurchaseCreated( $integration, $wp_user ); } /** * Remove a user role when the purchase is revoked. * * @param \SureCart\Models\Integration $integration The integrations. * @param \WP_User $wp_user The user. * * @return boolean|void Returns true if the user course access updation was successful otherwise false. */ public function onPurchaseRevoked( $integration, $wp_user ) { $this->toggleRole( $integration->integration_id, $wp_user, false ); } /** * Toggle the role * * @param string $role The role. * @param \WP_User $wp_user The user object. * @param boolean $add True to add the role, false to remove. * * @return \WP_Role|false */ public function toggleRole( $role, $wp_user, $add = true ) { // make sure the role exists. $role_object = get_role( $role ); if ( ! $role_object ) { return; } // add or remove the role. return $add ? $wp_user->add_role( $role ) : $wp_user->remove_role( $role ); } } // bootstrap the integration. (new \MyPlugin\Integrations\UserRoleChangeIntegration())->bootstrap(); ``` ``` ``` # PHP Models Source: https://developer.surecart.com/documentation/php-models <Info> **PHP Models = API Interface** — The PHP models provide a fluent, Laravel-like interface to the [SureCart REST API](/api-reference/introduction). Each model corresponds directly to an API resource. For complete details on available properties, query parameters, and expandable relations, refer to the [API Reference](/api-reference/introduction). </Info> The PHP models provide a fluent syntax for querying the database through the API. In this document, we will demonstrate various methods for retrieving models. <br /> <Note> **Blocking HTTP requests** — Each model query makes a synchronous HTTP request to the SureCart API. This means PHP execution will wait for the response before continuing. Use these methods in contexts where blocking is acceptable: * AJAX/REST handlers. * Admin dashboard pages and requests. * WP-CLI commands. * Cron jobs and background tasks. **Avoid** using model queries directly in front-end page rendering, as they will slow down page load times and negatively impact user experience. </Note> # Retrieving SureCart's PHP models allow you to fetch data from the SureCart API using a familiar, Laravel-like syntax. You can retrieve single records by ID, query collections with filters, paginate results, and refresh stale data — all with clean, expressive methods. ### Retrieving a model by id The model's `all` method will retrieve a record with a specific ID. ```php theme={null} use SureCart\Models\Product; $product = Product::find('8ba8d60f-5277-4e6b-807c-dee8166446d5'); ``` ### Retrieving several models. The model's `all` method will retrieve the first 10 records from the model's associated database table: ```php theme={null} use SureCart\Models\Product; $products = Product::get(); foreach ($products as $product) { echo $product->name; } ``` ### Building queries To query by specific parameters, you can use the `where` method. This method sends query parameters over the API and returns the matching records. <Tip> The query parameters available in the `where()` method match the API endpoint's query parameters. See each model's API Reference (e.g., [Products API](/api-reference/products/list-all-products)) for all available filters. </Tip> ```php theme={null} use SureCart\Models\Product; $archived_products = Product::where([ 'archived' => false ])->get(); ``` ### Pagination You can paginate and get subsquent pages of results by using the `paginate` method. This method takes 2 parameters, `page` and `per_page`. The default pagination `per_page` limit is `100`. ```php theme={null} use SureCart\Models\Product; $archived_products = Product::where([ 'archived' => false ])->paginate([ 'per_page' => 20, 'page' => 2 ]); ``` Result: ```php theme={null} [ 'object' => 'product', 'pagination' => [ 'count' => 100, 'limit' => 20, 'page' => 2 ], 'data' => [ // 20 products [ 'id' => '8ba8d60f-5277-4e6b-807c-dee8166446d5', ... ] ... ] ] ``` ### Refreshing Models If you already have an instance of a model that was retrieved, you can "refresh" the model using the `fresh` method. The `fresh` method will re-retrieve the model from the database. The existing model instance will not be affected: ```php theme={null} $product = Product::where([ 'ids' => [ '8ba8d60f-5277-4e6b-807c-dee8166446d5', '07fd28e0-e735-4acf-86d8-4d7855055e0b' ] ])->first(); $freshProduct = $product->fresh(); ``` The `refresh` method will re-hydrate the existing model using fresh data from the database: ```php theme={null} $product = Product::create([ 'name' => 'New Product', ]); $product->name = 'Updated Product'; $product->refresh(); $flight->name; // "New Product" ``` # Expanding Relations Many models allow you to request additional information from relational models by using the `with` method. This parameter is available on all models and applies to the response of that model only. Model relations can be expanded in two ways. <Tip> Each model's expandable fields are documented in the [API Reference](/api-reference/introduction). Look for properties marked as "expandable" in the response schemas. </Tip> ### Expanding a single relation In many cases, an object contains the ID of a related object in its response properties. For example, a price has an associated product ID. Those models can be queried together in one call. ID fields that can be expanded into models are noted in this documentation with the "expandable" label. Here's an example: ```php theme={null} $prices = \SureCart\Models\Price::with([ 'product' ])->paginate(['page'=> 1]); ``` ```php theme={null} $promo = \SureCart\Models\Promotion::with([ 'coupon' ])->find('8ba8d60f-5277-4e6b-807c-dee8166446d5'); ``` ### Expanding list relations In some cases, such as a list of all prices for a product, there are available fields that are not included in responses by default. You can request these fields as an expanded response by using the `with` method. Fields that can be included in an expanded response are noted in this documentation with the "expandable" label. ```php theme={null} $products = \SureCart\Models\Product::with([ 'prices' ])->paginate(['page'=> 1]); ``` ### Recursively expanding relations You can expand recursively by specifying nested fields after a dot (.). For example, requesting `customer` and `customer.billing_address` on an order will expand the customer and the customer's billing address. ```php theme={null} $orders = \SureCart\Models\Order::with([ 'customer', 'customer.billing_address' ])->paginate(['page'=> 1]); ``` You can use the `with` method on any endpoint that returns expandable fields, including list, create, and update endpoints. Expanding list requests are plural, but expanding objects within a list is singular. For example, if you wanted to retrieve an order's line items and each line item's price, you would pass `checkout`, `checkout.line_items` and `line_item.price` as expand parameters. Example: ```php theme={null} $orders = \SureCart\Models\Order::with( [ 'checkout', 'checkout.line_items', 'line_item.price', 'price.product' ] )->paginate( [ 'page' => 1 ] ); ``` Then you can access expanded relations: ```php theme={null} foreach ( $orders['data'] as $order ) { $checkout = $order->checkout; $line_items = $checkout->line_items->data; foreach ( $line_items as $line_item ) { $price = $line_item->price; $product = $price->product; echo $product->name . ' - ' . $price->amount; } } ``` You can expand multiple objects at once by identifying multiple items in the `with` array. Expansions have a maximum depth of two levels, and you can expand up to 10 objects. This is not only limited to `get` or `paginate`. You can use this on `create` or `update` requests as well. This will allow you to create or update a model and fetch its relations all in one request. ```php theme={null} $price = \SureCart\Models\Price::create([ 'name' => 'New Price', 'amount' => 5000, // $50.00 'currency' => 'usd', 'product' => '8ba8d60f-5277-4e6b-807c-dee8166446d5', ])->with([ 'product' ])->save(); $product_name = $price->product->nname; ``` # Inserting, Updating, and Deleting ### Creating a Model To create a new model, instantiate it with attributes and call the `save` method: <Tip> For the full list of required and optional attributes when creating a model, see the corresponding "Create" endpoint in the [API Reference](/api-reference/introduction). </Tip> ```php theme={null} use SureCart\Models\Product; $product = Product::create([ 'name' => 'iPhone', 'description' => 'iPhone is a smartphone' ]); ``` Or set individual attributes and call `save`: ```php theme={null} use SureCart\Models\Product; // create ths instance. $product = new Product([ 'name' => 'iPhone', 'description' => 'iPhone is a smartphone' ]); // do some other logic with product. // save the product. $product->save(); ``` ### Updating a Model Use the static `update` method directly by passing an `id` in the attributes: ```php theme={null} use SureCart\Models\Product; Product::update([ 'id' => $product_id, 'name' => 'iPhone Pro', 'description' => 'The latest iPhone' ]); ``` Or retrieve the model first, then call `update` with the new attributes: ```php theme={null} use SureCart\Models\Product; $product = Product::find( $product_id ); $product->update([ 'name' => 'iPhone Pro', 'description' => 'The latest iPhone' ]); ``` Or modify individual attributes and call `save`: ```php theme={null} use SureCart\Models\Product; $product = Product::find( $product_id ); $product->name = 'iPhone Pro'; $product->description = 'The latest iPhone'; $product->save(); ``` ### Deleting a Model Use the `delete` method to remove a model: ```php theme={null} use SureCart\Models\Product; $product = Product::find( $product_id ); $product->delete(); ``` You can also delete directly by passing an ID: ```php theme={null} use SureCart\Models\Product; Product::delete( $product_id ); ``` # Error Handling All model methods can return a `\WP_Error` object if the API request fails. Always check for errors when working with models: ```php theme={null} use SureCart\Models\Product; $product = Product::find('invalid-id'); if (is_wp_error($product)) { // Handle the error $error_message = $product->get_error_message(); $error_code = $product->get_error_code(); error_log("Failed to find product: $error_message"); return; } // Safe to use $product here echo $product->name; ``` This applies to all model operations including `find`, `get`, `save`, and `delete`: ```php theme={null} $product = new Product(['name' => 'Test']); $result = $product->save(); if (is_wp_error($result)) { // Handle validation or API errors foreach ($result->get_error_messages() as $message) { echo $message; } } ``` # Utility Methods ### Getting the First Result Use the `first` method to retrieve a single record from a query: ```php theme={null} $product = Product::where(['archived' => false])->first(); ``` ### Converting to Array or Object Models can be converted to arrays or standard objects: ```php theme={null} $product = Product::find($id); // Convert to array $array = $product->toArray(); // Convert to stdClass object $object = $product->toObject(); ``` ### Array Access Models implement `ArrayAccess`, so you can access attributes using array syntax: ```php theme={null} $product = Product::find($id); // These are equivalent echo $product->name; echo $product['name']; ``` ### Dirty Checking You can check if a model's attributes have been modified since it was retrieved: ```php theme={null} $product = Product::find($id); $product->isDirty(); // false - no changes yet $product->name = 'New Name'; $product->isDirty(); // true - has unsaved changes $product->isDirty('name'); // true - specific attribute changed $dirty = $product->getDirty(); // ['name' => 'New Name'] ``` # Available Models SureCart provides PHP models for interacting with the following resources. Each model maps directly to an API resource — see the [API Reference](/api-reference/introduction) for full property details, query parameters, and expandable fields. ### Products | Model | API Reference | Description | | ------------------- | -------------------------------------------------------------- | ------------------------------ | | `Product` | [Products](/api-reference/products/list) | Physical or digital products | | `Price` | [Prices](/api-reference/prices/list) | Pricing options for products | | `ProductCollection` | [Product Collections](/api-reference/product-collections/list) | Product collections/categories | | `ProductGroup` | [Product Groups](/api-reference/product-groups/list) | Product groupings | | `ProductMedia` | [Product Medias](/api-reference/product-medias/list) | Media attached to products | | `Variant` | [Variants](/api-reference/variants/list) | Product variants | | `VariantOption` | [Variant Options](/api-reference/variant-options/list) | Variant option definitions | | `Bump` | [Bumps](/api-reference/bumps/list) | Order bumps | | `Upsell` | [Upsells](/api-reference/upsells/list) | Upsell offers | | `UpsellFunnel` | [Upsell Funnels](/api-reference/upsell-funnels/list) | Upsell funnel configurations | | `Swap` | [Swaps](/api-reference/swaps/list) | Product swap configurations | | `Download` | [Downloads](/api-reference/downloads/list) | Downloadable files | | `Coupon` | [Coupons](/api-reference/coupons/list) | Discount coupons | | `Promotion` | [Promotions](/api-reference/promotions/list) | Applied promotions | ### Customers | Model | API Reference | Description | | -------------------- | ---------------------------------------------------------------- | --------------------------- | | `Customer` | [Customers](/api-reference/customers/list) | Customer records | | `BalanceTransaction` | [Balance Transactions](/api-reference/balance-transactions/list) | Balance transaction records | ### Orders & Payments | Model | API Reference | Description | | --------------------- | -------------------------------------------------------------------- | ----------------------------- | | `Order` | [Orders](/api-reference/orders/list) | Completed orders | | `Checkout` | [Checkouts](/api-reference/checkouts/list) | Checkout sessions | | `AbandonedCheckout` | [Abandoned Checkouts](/api-reference/abandoned-checkouts/list) | Abandoned checkout recovery | | `LineItem` | [Line Items](/api-reference/line-items/list) | Order line items | | `Purchase` | [Purchases](/api-reference/purchases/list) | Individual purchase records | | `Charge` | [Charges](/api-reference/charges/list) | Payment charges | | `Invoice` | [Invoices](/api-reference/invoices/list) | Invoices for orders | | `Refund` | [Refunds](/api-reference/refunds/list) | Refund records | | `PaymentIntent` | [Payment Intents](/api-reference/payment-intents/list) | Payment intent records | | `PaymentMethod` | [Payment Methods](/api-reference/payment-methods/list) | Stored payment methods | | `ManualPaymentMethod` | [Manual Payment Methods](/api-reference/manual-payment-methods/list) | Manual payment method configs | | `Processor` | [Processors](/api-reference/processors/list) | Payment processors | | `Fee` | [Fees](/api-reference/fees/list) | Order fees | | `Dispute` | [Disputes](/api-reference/disputes/list) | Payment disputes | ### Subscriptions | Model | API Reference | Description | | -------------------- | ---------------------------------------------------------------- | ---------------------------- | | `Subscription` | [Subscriptions](/api-reference/subscriptions/list) | Recurring subscriptions | | `Period` | [Periods](/api-reference/periods/list) | Subscription billing periods | | `CancellationAct` | [Cancellation Acts](/api-reference/cancellation-acts/list) | Subscription cancellations | | `CancellationReason` | [Cancellation Reasons](/api-reference/cancellation-reasons/list) | Cancellation reason options | ### Shipping & Fulfillment | Model | API Reference | Description | | ----------------- | ---------------------------------------------------------- | ------------------------------ | | `Fulfillment` | [Fulfillments](/api-reference/fulfillments/list) | Order fulfillments | | `FulfillmentItem` | [Fulfillment Items](/api-reference/fulfillment-items/list) | Fulfillment line items | | `ShippingMethod` | [Shipping Methods](/api-reference/shipping-methods/list) | Shipping method configurations | | `ShippingProfile` | [Shipping Profiles](/api-reference/shipping-profiles/list) | Shipping profile settings | | `ShippingRate` | [Shipping Rates](/api-reference/shipping-rates/list) | Shipping rate definitions | | `ShippingZone` | [Shipping Zones](/api-reference/shipping-zones/list) | Shipping zone configurations | | `ReturnRequest` | [Return Requests](/api-reference/return-requests/list) | Return request records | | `ReturnItem` | [Return Items](/api-reference/return-items/list) | Return request items | ### Tax | Model | API Reference | Description | | ----------------- | ---------------------------------------------------------- | ------------------------ | | `TaxRegistration` | [Tax Registrations](/api-reference/tax-registrations/list) | Tax registration records | | `TaxZone` | [Tax Zones](/api-reference/tax-zones/list) | Tax zone configurations | ### Licensing | Model | API Reference | Description | | ------------ | ---------------------------------------------- | ------------------- | | `License` | [Licenses](/api-reference/licenses/list) | Software licenses | | `Activation` | [Activations](/api-reference/activations/list) | License activations | ### Affiliates | Model | API Reference | Description | | -------------------- | ---------------------------------------------------------------- | ------------------------------ | | `Affiliation` | [Affiliations](/api-reference/affiliations/list) | Affiliate accounts | | `AffiliationRequest` | [Affiliation Requests](/api-reference/affiliation-requests/list) | Affiliate application requests | | `AffiliationProduct` | [Affiliation Products](/api-reference/affiliation-products/list) | Affiliate product associations | | `Referral` | [Referrals](/api-reference/referrals/list) | Affiliate referral records | | `ReferralItem` | [Referral Items](/api-reference/referral-items/list) | Referral line items | | `Payout` | [Payouts](/api-reference/payouts/list) | Affiliate payouts | | `PayoutGroup` | [Payout Groups](/api-reference/payout-groups/list) | Grouped payout batches | | `Click` | [Clicks](/api-reference/clicks/list) | Affiliate click tracking | ### Media | Model | API Reference | Description | | ------- | ------------------------------------ | ----------- | | `Media` | [Medias](/api-reference/medias/list) | Media files | ### Account & Settings | Model | API Reference | Description | | --------- | ---------------------------------------------------------- | ------------------------------- | | `Account` | [Account](/api-reference/account/retrieve) | Store account settings | | `Brand` | [Brand](/api-reference/brands/retrieve) | Branding configurations | | `Webhook` | [Webhook Endpoints](/api-reference/webhook-endpoints/list) | Webhook endpoint configurations | ### Reviews | Model | API Reference | Description | | -------- | -------------------------------------- | --------------- | | `Review` | [Reviews](/api-reference/reviews/list) | Product reviews | ### Other | Model | API Reference | Description | | -------- | -------------------------------------- | ----------------- | | `Event` | [Events](/api-reference/events/list) | Event log records | | `Export` | [Exports](/api-reference/exports/list) | Data exports | All models are located in the `SureCart\Models` namespace: ```php theme={null} use SureCart\Models\Product; use SureCart\Models\Customer; use SureCart\Models\Order; // etc. ``` # Checkout Source: https://developer.surecart.com/documentation/styling/checkout Extend and customize SureCart with WordPress hooks SureCart checkout components use a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) to encapsulate their styles. This approach offers several advantages: * Styles are protected from any potential style conflicts. This means you don't have to worry about theme or plugin styles conflicting with the SureCart UI. * If the internal HTML structure of any components changes, you won't need to update any custom CSS. There are two ways to customize SureCart components: using CSS custom properties ("CSS variables") and using CSS parts ("parts"). For styling the order summary line items specifically, see [Checkout Line Items](/documentation/styling/checkout-line-items). ## CSS Variables CSS variables are ideal for making global style changes that are shared across components. For instance, you can use a CSS variable like `--sc-border-radius` to easily change the border radius for various elements like form elements, inputs, cards, and buttons, ensuring a consistent design across your site. Example: ```css theme={null} :root:root { /** Remove all border radiuses */ --sc-border-radius-small: 0; --sc-border-radius-medium: 0; --sc-border-radius-large: 0; --sc-border-radius-x-large: 0; } ``` Here's a list of commonly used available CSS variables. ### Colors ```css expandable theme={null} /** Primary Color */ --sc-color-primary-500: #000; --sc-color-primary-text: var(--sc-color-white); /** Colors */ --sc-color-black: #000; --sc-color-white: #fff; --sc-color-gray-50: #f9fafb; --sc-color-gray-100: #f3f4f6; --sc-color-gray-200: #e5e7eb; --sc-color-gray-300: #dce0e6; --sc-color-gray-400: #9ca3af; --sc-color-gray-500: #6b7280; --sc-color-gray-600: #4b5563; --sc-color-gray-700: #374151; --sc-color-gray-800: #1f2937; --sc-color-gray-900: #111827; --sc-color-gray-950: #0d131e; /** Neutral Colors */ --sc-color-neutral-50: #fafafa; --sc-color-neutral-100: whitesmoke; --sc-color-neutral-200: #e5e5e5; --sc-color-neutral-300: #d4d4d4; --sc-color-neutral-400: #a3a3a3; --sc-color-neutral-500: #737373; --sc-color-neutral-600: #525252; --sc-color-neutral-700: #404040; --sc-color-neutral-800: #262626; --sc-color-neutral-900: #171717; --sc-color-neutral-950: #0f0f0f; /** Success */ --sc-color-success-50: #f0fdf4; --sc-color-success-100: #dcfce7; --sc-color-success-200: #bbf7d0; --sc-color-success-300: #86efac; --sc-color-success-400: #4ade80; --sc-color-success-500: #22c55e; --sc-color-success-600: #16a34a; --sc-color-success-700: #15803d; --sc-color-success-800: #166534; --sc-color-success-900: #14532d; --sc-color-success-950: #0d381e; --sc-color-success-text: var(--sc-color-white); /** Info */ --sc-color-info-50: #eff6ff; --sc-color-info-100: #dbeafe; --sc-color-info-200: #bfdbfe; --sc-color-info-300: #93c5fd; --sc-color-info-400: #60a5fa; --sc-color-info-500: #3b82f6; --sc-color-info-600: #2563eb; --sc-color-info-700: #1d4ed8; --sc-color-info-800: #1e40af; --sc-color-info-900: #1e3a8a; --sc-color-info-text: var(--sc-color-white); /** Warning */ --sc-color-warning-50: #fffbeb; --sc-color-warning-100: #fef3c7; --sc-color-warning-200: #fde68a; --sc-color-warning-300: #fcd34d; --sc-color-warning-400: #fbbf24; --sc-color-warning-500: #f59e0b; --sc-color-warning-600: #d97706; --sc-color-warning-700: #b45309; --sc-color-warning-800: #92400e; --sc-color-warning-900: #78350f; --sc-color-warning-950: #4d220a; --sc-color-warning-text: var(--sc-color-white); /** Danger */ --sc-color-danger-50: #fef2f2; --sc-color-danger-100: #fee2e2; --sc-color-danger-200: #fecaca; --sc-color-danger-300: #fca5a5; --sc-color-danger-400: #f87171; --sc-color-danger-500: #ef4444; --sc-color-danger-600: #dc2626; --sc-color-danger-700: #b91c1c; --sc-color-danger-800: #991b1b; --sc-color-danger-900: #7f1d1d; --sc-color-danger-950: #481111; --sc-color-danger-text: var(--sc-color-white); ``` ### Border Radius ```css expandable theme={null} --sc-border-radius-small: 0.15em; --sc-border-radius-medium: 0.25em; --sc-border-radius-large: 0.5em; --sc-border-radius-x-large: 0.75em; --sc-border-radius-circle: 50%; --sc-border-radius-pill: 9999px; ``` ### Shadow ```css expandable theme={null} --sc-shadow-x-small: 0 1px 0 #0d131e0d; --sc-shadow-small: 0 1px 2px #0d131e1a; --sc-shadow-medium: 0 0 #000, 0 0 #000, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); --sc-shadow-large: 0 2px 8px #0d131e1a; --sc-shadow-x-large: 0 4px 16px #0d131e1a; ``` ### Spacing ```css expandable theme={null} --sc-spacing-xxx-small: 0.125em; --sc-spacing-xx-small: 0.25em; --sc-spacing-x-small: 0.5em; --sc-spacing-small: 0.75em; --sc-spacing-medium: 1em; --sc-spacing-large: 1.25em; --sc-spacing-x-large: 1.75em; --sc-spacing-xx-large: 2.25em; --sc-spacing-xxx-large: 3em; --sc-spacing-xxxx-large: 4.5em; ``` ### Transition ```css expandable theme={null} --sc-transition-x-slow: 1000ms; --sc-transition-slow: 500ms; --sc-transition-medium: 250ms; --sc-transition-fast: 150ms; --sc-transition-x-fast: 50ms; ``` ### Fonts / Typography ```css expandable theme={null} --sc-font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; --sc-font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --sc-font-serif: Georgia, "Times New Roman", serif; --sc-font-size-xx-small: 0.625em; --sc-font-size-x-small: 0.75em; --sc-font-size-small: 0.875em; --sc-font-size-medium: 1em; --sc-font-size-large: 1.15em; --sc-font-size-x-large: 1.25em; --sc-font-size-xx-large: 1.45em; --sc-font-size-xxx-large: 3em; --sc-font-size-xxxx-large: 4.5em; --sc-font-weight-light: 300; --sc-font-weight-normal: 400; --sc-font-weight-semibold: 500; --sc-font-weight-bold: 600; --sc-letter-spacing-dense: -0.015em; --sc-letter-spacing-normal: normal; --sc-letter-spacing-loose: 0.075em; --sc-line-height-dense: 1.4; --sc-line-height-normal: 1.8; --sc-line-height-loose: 2.2; --sc-button-font-size-small: var(--sc-font-size-x-small); --sc-button-font-size-medium: var(--sc-font-size-medium); --sc-button-font-size-large: var(--sc-font-size-large); ``` ### Focus Ring ```css expandable theme={null} --sc-focus-ring-color-primary: var(--sc-color-primary-500); --sc-focus-ring-color-success: #22c55e54; --sc-focus-ring-color-info: #6b728054; --sc-focus-ring-color-warning: #f59e0b54; --sc-focus-ring-color-danger: #ef444454; --sc-focus-ring-width: 1px; ``` ### Inputs ```css expandable theme={null} --sc-input-box-shadow: rgba(0, 0, 0, 0.05) 0px 1px 2px 0px; --sc-input-height-small: 2.25em; --sc-input-height-medium: 2.8em; --sc-input-height-large: 3em; --sc-input-background-color: var(--sc-color-white); --sc-input-background-color-hover: var(--sc-color-white); --sc-input-background-color-focus: var(--sc-color-white); --sc-input-background-color-disabled: var(--sc-color-gray-100); --sc-input-border: solid var(--sc-input-border-width) var( --sc-input-border-color ); --sc-input-border-color: var(--sc-color-gray-300); --sc-input-border-color-hover: var(--sc-color-gray-400); --sc-input-border-color-focus: var(--sc-color-primary-500); --sc-input-border-color-disabled: var(--sc-color-gray-300); --sc-input-border-color-invalid: var(--sc-color-danger-500); --sc-input-border-width: 1px; --sc-input-border-radius-small: var(--sc-border-radius-small); --sc-input-border-radius-medium: var(--sc-border-radius-medium); --sc-input-border-radius-large: var(--sc-border-radius-medium); --sc-input-font-family: var(--sc-font-sans); --sc-input-font-weight: var(--sc-font-weight-normal); --sc-input-font-size-small: var(--sc-font-size-small); --sc-input-font-size-medium: var(--sc-font-size-medium); --sc-input-font-size-large: var(--sc-font-size-large); --sc-input-label-font-weight: var(--sc-font-weight-semibold); --sc-input-label-margin: var(--sc-spacing-xx-small); --sc-input-letter-spacing: var(--sc-letter-spacing-normal); --sc-input-color: var(--sc-color-gray-700); --sc-input-color-hover: var(--sc-color-gray-700); --sc-input-color-focus: var(--sc-color-gray-700); --sc-input-color-disabled: var(--sc-color-gray-900); --sc-input-icon-color: var(--sc-color-gray-400); --sc-input-icon-color-hover: var(--sc-color-gray-600); --sc-input-icon-color-focus: var(--sc-color-gray-600); --sc-input-placeholder-color: var(--sc-color-gray-400); --sc-input-placeholder-color-disabled: var(--sc-color-gray-600); --sc-input-spacing-small: var(--sc-spacing-small); --sc-input-spacing-medium: var(--sc-spacing-medium); --sc-input-spacing-large: var(--sc-spacing-large); --sc-input-label-font-size-small: var(--sc-font-size-small); --sc-input-label-font-size-medium: var(--sc-font-size-medium); --sc-input-label-font-size-large: var(--sc-font-size-large); --sc-input-label-color: var(--sc-color-gray-600); --sc-input-help-text-font-size-small: var(--sc-font-size-x-small); --sc-input-help-text-font-size-medium: var(--sc-font-size-small); --sc-input-help-text-font-size-large: var(--sc-font-size-medium); --sc-input-help-text-color: var(--sc-color-gray-500); --sc-input-error-text-font-size-small: var( --sc-input-help-text-font-size-small ); --sc-input-error-text-font-size-medium: var( --sc-input-help-text-font-size-small ); --sc-input-error-text-font-size-large: var( --sc-input-help-text-font-size-small ); --sc-input-error-text-color: var(--sc-color-danger-500); ``` ## CSS Parts CSS Parts offer a low-level way to customize individual components within SureCart. Unlike CSS Variables, which provide high-level customizations for multiple components, CSS Parts allow you to target specific parts of a component's internal structure for fine-grained customization. This can be achieved using pure CSS, without the need for additional tools or methods. SureCart components use a shadow DOM to encapsulate their styles, which means that their internal structure isn't directly accessible using standard CSS selectors. Instead, components expose "parts" that can be targeted using the CSS part selector, `::part()`. This allows you to style specific elements within a component without affecting its overall structure. For example, if you want to customize the appearance of a specific button within a SureCart component, you can use CSS Parts to target that button and apply custom styles to it, all while leaving the rest of the component's styling intact. This provides a powerful way to tailor the look and feel of individual components to match your design preferences. ### Finding CSS Parts To discover the specific CSS parts available for styling within SureCart components, you can refer to our [Components Documentation](https://components.surecart.com). In this documentation, you will find a dedicated section for each component labeled "Shadow Parts." This section provides a comprehensive list of the available shadow parts that you can target for customization. ### Some Examples Here are some examples that modify various components to achieve a more techy or brutalist style. #### Input/Text Field To restyle the input field, we will refer to the [input component codex](https://components.surecart.com/components/input#component-codex). This will provide us with information about the various CSS parts that can be used for styling. ```css css theme={null} <style> sc-input { --sc-font-sans: monospace; --sc-color-primary-500: #2dd4bf; } sc-input::part(base) { border: 1px solid black; box-shadow: 2px 2px #2dd4bf; border-radius: 0; font-family: monospace; } sc-input::part(label) { color: black; font-size: 14px; letter-spacing: 2px; text-transform: uppercase; } sc-input::part(base):hover { box-shadow: 5px 5px #2dd4bf; } </style> ``` **Component** ```javascript ja theme={null} <sc-input label="Your Name" placeholder="Enter your name"></sc-input> <sc-input label="Your Name" class="sc-input-style-example" placeholder="Enter your name"></sc-input> ``` #### Customer Email To restyle the customer email field, we will refer to the [input component codex](https://components.surecart.com/components/input#component-codex). This will provide us with information about the various CSS parts that can be used for styling. ```css theme={null} <style> sc-customer-email { --sc-font-sans: monospace; --sc-color-primary-500: #2dd4bf; } sc-customer-email::part(label) { color: black; font-size: 14px; letter-spacing: 2px; text-transform: uppercase; } sc-customer-email::part(base) { border: 1px solid black; box-shadow: 2px 2px #2dd4bf; border-radius: 0; font-family: monospace; } sc-customer-email::part(base):hover { box-shadow: 5px 5px #2dd4bf; } </style> ``` **Component** ```javascript theme={null} <sc-customer-email label="Email" placeholder="Enter your name"></sc-customer-email> <sc-customer-email label="Email" class="sc-customer-email-style-example" placeholder="Enter your name"></sc-customer-email> ``` #### Order Shipping Address To restyle the customer email field, we will refer to the [address component codex](https://components.surecart.com/components/address#component-codex). This will provide us with information about the various CSS parts that can be used for styling. Additionally, we are applying some CSS variables scoped to this component. However, you can scope it to any parent component, and the styles will cascade into the children. ```css theme={null} <style> sc-order-shipping-address { --sc-font-sans: monospace; --sc-address-column-spacing: 1em; --sc-color-primary-500: #2dd4bf; font-size: 14px; } sc-order-shipping-address::part(label) { color: black; letter-spacing: 2px; text-transform: uppercase; } sc-order-shipping-address::part(input__base), sc-order-shipping-address::part(select__base), sc-order-shipping-address::part(search__base) { border: 1px solid black; border-radius: 0; font-family: monospace; box-shadow: 2px 2px #2dd4bf; transition: box-shadow 0.25s ease; } sc-order-shipping-address::part(input__base):hover, sc-order-shipping-address::part(select__base):hover, sc-order-shipping-address::part(search__base):hover { box-shadow: 5px 5px #2dd4bf; } </style> ``` **Component** ```javascript theme={null} <sc-order-shipping-address full></sc-order-shipping-address> <sc-order-shipping-address class="sc-shipping-address-style-example" full></sc-order-shipping-address> ``` #### Button ```css theme={null} <style> sc-button { --sc-font-sans: monospace; --sc-color-primary-500: #2dd4bf; } sc-button::part(base) { border-radius:0; background: white; font-family: monospace; border: 1px solid black; box-shadow: 2px 2px #2dd4bf; color: black; } sc-button::part(base):hover { background: #2dd4bf; } </style> ``` **Component** ```javascript theme={null} <sc-button type="primary" submit full>Purchase</sc-button> <sc-button class="sc-button-example" type="primary" submit full>Purchase</sc-button> ``` # Checkout Line Items Source: https://developer.surecart.com/documentation/styling/checkout-line-items Customize checkout order summary line items with CSS variables and CSS parts The checkout order summary renders each line item with a web component (`sc-line-items`). Unlike the [Slide-Out Cart](https://surecart.com/docs/slide-out-cart/), it doesn't have per-element blocks in the editor — you customize it with CSS instead, using the two mechanisms described in [Styling the Checkout](/documentation/styling/checkout): CSS variables and CSS parts. <Note> Internal class names inside the component's shadow DOM aren't reachable from your CSS. Only the variables and parts documented below are supported hooks. </Note> Add your CSS under **Appearance → Customize → Additional CSS**, or in your theme's stylesheet. Scope it to the checkout so the cart and other forms aren't affected: ```css theme={null} /* Line items inside the checkout form only */ sc-checkout sc-line-items { --sc-line-item-title-color: #1a1a1a; } ``` To apply a variable globally instead, use the `:root:root` selector shown in [Styling the Checkout](/documentation/styling/checkout#css-variables). Scoping to `sc-line-items` doesn't need that trick — a variable set on a closer element always wins over the global default — and it keeps shared variables (like `--sc-input-*`) from affecting the rest of the page. ## CSS Variables ### Layout & image | Variable | Default | Controls | | --------------------------------------------- | ------- | ----------------------------------------------------------------------------- | | `--sc-product-line-item-line-gap` | `6px` | Vertical gap between text lines (title, description, details) | | `--sc-product-line-item-image-size` | `65px` | Product image width and height | | `--sc-product-line-item-mobile-image-display` | `none` | Set to `block` to keep the image visible on narrow layouts (under 380px wide) | ### Text colors Defaults reference the global palette from [Styling the Checkout](/documentation/styling/checkout) (for example, `--sc-input-help-text-color` resolves to `--sc-color-gray-500`). | Variable | Controls | | ----------------------------- | ---------------------------------------------------------------------------- | | `--sc-line-item-title-color` | Product title (falls back to `--sc-input-label-color`) | | `--sc-input-label-color` | Titles, prices, bundle item names and quantities | | `--sc-input-help-text-color` | Muted text: compare-at (strikethrough) price, remove link, price description | | `--sc-price-label-color` | Description line under the title (falls back to the help text color) | | `--sc-color-gray-500` | Variant options, line item note, "+N more" toggle | | `--sc-color-gray-700` | Toggle hover color | | `--sc-input-error-text-color` | Purchasable status message | <Warning> `--sc-font-size-*` and `--sc-input-*` variables are shared with other checkout elements such as inputs and labels. Scope them to `sc-line-items` — not `:root` — unless you intend a global change. </Warning> ### Typography | Variable | Controls | | ---------------------------- | -------------------------------------------- | | `--sc-font-sans` | Font family for the whole line item | | `--sc-font-size-medium` | Title and price size | | `--sc-font-size-small` | Details, compare-at price, price description | | `--sc-price-label-font-size` | Description line size | | `--sc-font-weight-semibold` | Title and price weight | ### Bundle details | Variable | Default | Controls | | --------------------------------------- | ------- | -------------------------------------------------------------------------------- | | `--sc-line-item-details-collapse-lines` | `2` | Lines shown before the bundle details region collapses behind a "+N more" toggle | ### Borders & shadows | Variable | Controls | | ------------------------- | ------------------------------------------ | | `--sc-input-border-color` | Image border, image placeholder background | | `--sc-input-box-shadow` | Image shadow | ## CSS Parts `sc-line-items` exposes each element of a line item as a [CSS part](/documentation/styling/checkout#css-parts), so you can target them directly with `::part()`. The full list is also available under "Shadow Parts" in the [Components Documentation](https://components.surecart.com). | Part | Element | | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | | `line-item` | The whole line item row | | `line-item__image` / `line-item__placeholder-image` | Product image / placeholder | | `line-item__text` | Text column (title and description) | | `line-item__title` | Product title | | `line-item__description` | Description line (price name, interval) | | `line-item__price` / `line-item__price-amount` | Price column / amount | | `line-item__price-scratch` | Compare-at (strikethrough) price | | `line-item__price-description` | Text under the price | | `line-item__static-quantity` | Read-only quantity ("× 2") | | `line-item__quantity`, `line-item__quantity-plus`, `line-item__quantity-minus`, `line-item__quantity-input` | Quantity selector | | `line-item__remove-icon` | Remove icon | | `line-item__trial-fees` | Trial and fees line | | `line-item__details` | Collapsible details region (bundle components) | | `line-item__details-component` | A single bundle component row | | `line-item__details-variant` | Variant options within a bundle component row | | `line-item__details-toggle` | "+N more" / "Show less" toggle | | `line-item__note` | Line item note | Example: ```css theme={null} sc-line-items::part(line-item__title) { color: #111827; text-transform: uppercase; letter-spacing: 1px; } sc-line-items::part(line-item__image) { border-radius: 8px; } sc-line-items::part(line-item__details-variant) { color: #6b7280; } ``` ## Example: match your cart styling ```css theme={null} sc-checkout sc-line-items { /* Variant text color (the same variable family the cart uses) */ --sc-color-gray-500: #6b7280; /* Darker product titles */ --sc-line-item-title-color: #111827; /* Bigger image, kept visible on mobile */ --sc-product-line-item-image-size: 80px; --sc-product-line-item-mobile-image-display: block; /* Show 3 detail lines before collapsing */ --sc-line-item-details-collapse-lines: 3; } ``` ## Notes * Bundle row quantity and name text has no dedicated part — style it through `line-item__details-component` (color is inherited), or with the variables above. * Behavior settings (removable, editable, show all bundle items, separator character) are block settings on the **Line Items** block in the checkout editor, not CSS. * The order confirmation and customer dashboard render line items with the same component but don't expose its parts — use CSS variables on those surfaces. # Variant Swatches Source: https://developer.surecart.com/guides/variant-swatches Display product variant options as image swatches instead of text pills This guide shows you how to transform variant option pills (like "Red", "Blue", "Green") into visual image swatches using variant images. <Info> Before starting, you need to assign images to your variants. See the [Variant Images documentation](https://surecart.com/docs/variant-images/) for setup instructions. </Info> ## How it works The code below intercepts the `surecart/product-variant-pill` block and replaces the text pill with a thumbnail from the variant's assigned image. When a customer clicks a swatch, the product image updates to show the selected variant. ## Implementation Add this code to your theme's `functions.php` file or a custom plugin. ```php theme={null} <?php $variant_option_name_for_swatch = 'color'; // Change this to match your variant option name. add_action( 'render_block', function ( $block_content, $block, $wp_block ) use ( $variant_option_name_for_swatch ) { // Only target the variant pill block for the specified option. if ( empty( $wp_block->context['name'] ) || $variant_option_name_for_swatch !== strtolower( $wp_block->context['name'] ) ) { return $block_content; } if ( 'surecart/product-variant-pill' !== $block['blockName'] ) { return $block_content; } $product = sc_get_product(); // Find images that match this variant option value. $gallery = array_values( array_filter( $product->gallery, function ( $image ) use ( $wp_block ) { return strtolower( $image->getMetadata( 'variant_option' ) ) === strtolower( $wp_block->context['value'] ); } ) ); $background = ! empty( $gallery[0] ) ? ( $gallery[0]->guid ?? null ) : null; if ( empty( $background ) ) { return $block_content; } $processor = new \WP_HTML_Tag_Processor( $block_content ); $processor->next_tag( 'div' ); if ( ! empty( $background ) ) { $processor->set_attribute( 'style', 'background: url(' . esc_url( $background ) . '); background-size: 150%; background-position: center; color:transparent;width: 56px; height: 56px; border-radius: 4px; margin: 5px auto; cursor: pointer; box-sizing: border-box; text-indent: -9999px; border-width: 2px;' ); } $processor->add_class( 'sc-variant-color-swatch' ); $processor->set_attribute( 'data-wp-class--sc-variant-color-swatch--selected', 'state.isOptionSelected' ); $processor->set_attribute( 'data-wp-class--sc-variant-color-swatch--disabled', 'state.isOptionUnavailable' ); // Wrap swatch and name in a parent div. $updated_html = '<div class="sc-variant-color-wrapper" style="display:flex; flex-direction:column; align-items:center;">'; $updated_html .= $processor->get_updated_html(); // Uncomment to show the variant option name below the image: // $variant_name = esc_html( $wp_block->context['value'] ?? '' ); // $updated_html .= '<div class="sc-variant-color-name" style="font-size: 12px; text-align: center; color:#333; text-transform: capitalize;">' . $variant_name . '</div>'; $updated_html .= '</div>'; return $updated_html; }, 10, 3 ); ``` ## Customization options ### Change the variant option name By default, this code targets the "color" variant option. To use a different option (like "Size" or "Material"), change the variable at the top: ```php theme={null} $variant_option_name_for_swatch = 'size'; // Target "Size" variants instead. ``` ### Show variant labels To display the variant name below each swatch, uncomment the label section in the code: ```php theme={null} $variant_name = esc_html( $wp_block->context['value'] ?? '' ); $updated_html .= '<div class="sc-variant-color-name" style="font-size: 12px; text-align: center; color:#333; text-transform: capitalize;">' . $variant_name . '</div>'; ``` ### Adjust swatch size Modify the `width` and `height` values in the style attribute to change the swatch dimensions: ```php theme={null} 'style', 'background: url(' . esc_url( $background ) . '); background-size: 150%; background-position: center; color:transparent;width: 72px; height: 72px; border-radius: 4px; margin: 5px auto; cursor: pointer; box-sizing: border-box; text-indent: -9999px; border-width: 2px;' ``` ## Styling the swatches Add CSS to customize the selected and disabled states: ```css theme={null} /* Selected swatch */ .sc-variant-color-swatch--selected { border-color: #00824c; box-shadow: 0 0 0 2px #00824c; } /* Disabled/unavailable swatch */ .sc-variant-color-swatch--disabled { opacity: 0.4; cursor: not-allowed; } ``` ## Related <CardGroup> <Card title="Product Hooks" icon="box" href="/documentation/actions-filters/products"> Additional hooks for customizing product display. </Card> <Card title="Checkout Customization" icon="credit-card" href="/documentation/add-to-cart"> Add custom fields and content to checkout. </Card> </CardGroup> # Introduction Source: https://developer.surecart.com/index Developer documentation for extending and customizing SureCart Welcome to the SureCart developer documentation. Here you'll find everything you need to integrate, extend, and customize SureCart for your WordPress site. ## Getting Started <CardGroup> <Card title="Working with Data" icon="database" href="/documentation/php-models"> Learn how to query and manipulate SureCart data using PHP models and Redux queries. </Card> <Card title="Orders & Purchases" icon="receipt" href="/documentation/orders-and-purchases"> Understand how orders and purchases work and how to integrate with them. </Card> <Card title="Actions & Filters" icon="code" href="/documentation/actions-reference"> Extend SureCart functionality using WordPress hooks, actions, and filters. </Card> <Card title="API Reference" icon="terminal" href="/api-reference/introduction"> Complete REST API documentation for programmatic access to SureCart. </Card> </CardGroup> ## Extending SureCart <CardGroup> <Card title="Cart & Checkout" icon="credit-card" href="/documentation/add-to-cart"> Programmatically add items to the cart and checkout. </Card> <Card title="Custom Loops" icon="arrows-rotate" href="/documentation/custom-loops"> Create custom product loops and displays. </Card> <Card title="Admin UI" icon="gauge" href="/documentation/admin-ui"> Extend and customize the admin interface. </Card> </CardGroup>