├── .gitignore ├── README.md ├── assets ├── jps-v1-2-overview.png ├── jps-v1-3-overview.png ├── sample-magic-link-email.png └── woocommerce-register-flow-chart.png ├── faq.md ├── jetpack ├── automatic-account-creation-connection.md ├── determining-connection-status.md ├── jetpack-activity-endpoints │ ├── activity-count.md │ ├── activity.md │ └── single-activity.md ├── jetpack-backup-endpoints │ ├── backups.md │ ├── downloads.md │ └── prepare-download.md ├── jetpack-restore-endpoints │ ├── restore-status.md │ └── restore.md ├── jetpack-scan-endpoints │ ├── alerts.md │ ├── enqueue_scan.md │ ├── fix.md │ ├── fix_status.md │ └── scan.md ├── jetpack-start-endpoints │ ├── README.md │ ├── authentication.md │ ├── determining-provisioning-status-v1.4.md │ ├── determining-provisioning-status.md │ ├── errors.md │ ├── mobile-magic-link.md │ ├── plan-cancellation.md │ ├── plan-provisioning.md │ ├── setting-backups-ftp-credentials.md │ ├── setting-backups-ssh-credentials.md │ └── upgrade-paths.md ├── managing-modules.md ├── method-not-found.md ├── migrate-v1-2-to-v1-3.md ├── monitor-downtime-notifications-webhook.md ├── plan-provisioning.md ├── redirect-after-authorization.md ├── reporting-endpoints │ ├── README.md │ ├── activations-list.md │ ├── activations-summary.md │ ├── invoices-past.md │ └── invoices-upcoming.md └── upgrade-redirection.md ├── users └── user-creation.md └── woocommerce ├── install.md ├── management-via-wp-cli.md ├── overview.md ├── plan-cancel.md ├── plan-register.md ├── product-info.md ├── reporting-endpoints.md ├── update-connected-site.md └── update-url.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the hosting partners program! 2 | 3 | In this directory, you'll find information on provisioning and managing plans for Automattic products as well as information on managing the products themselves. 4 | 5 | If you have any technical questions or concerns, don’t hesitate to get in touch with our team via Slack or by emailing us at `partners@jetpack.com`. 6 | 7 | ## Documentation links 8 | 9 | - Jetpack 10 | - [Jetpack Licensing API](https://github.com/Automattic/jetpack-licensing-api) 11 | - [Jetpack Coupons API](https://github.com/Automattic/jetpack-partner-api/tree/master/coupon) 12 | - Jetpack Start API: 13 | - [Authentication](jetpack/jetpack-start-endpoints/authentication.md) 14 | - Plan provisioning 15 | - ~~[Via CLI](jetpack/plan-provisioning.md)~~ (deprecated) 16 | - [Via direct API call](jetpack/jetpack-start-endpoints/plan-provisioning.md) 17 | - Checking status 18 | - [Connection status](jetpack/determining-connection-status.md) 19 | - [Provisioning status](jetpack/jetpack-start-endpoints/determining-provisioning-status-v1.4.md) 20 | - [Plan cancellation](jetpack/jetpack-start-endpoints/plan-cancellation.md) 21 | - [Controlling the redirect after a user finishes connection authorization](jetpack/redirect-after-authorization.md) 22 | - [Upgrade paths](jetpack/jetpack-start-endpoints/upgrade-paths.md) 23 | - [Managing modules](jetpack/managing-modules.md) 24 | - [Upgrade redirection](jetpack/upgrade-redirection.md) 25 | - [Monitor downtime notifications webhook](jetpack/monitor-downtime-notifications-webhook.md) 26 | - [Magic mobile links](jetpack/jetpack-start-endpoints/mobile-magic-link.md) 27 | - [Setting Backups SSH credentials](jetpack/jetpack-start-endpoints/setting-backups-ssh-credentials.md) 28 | - [Setting Backups FTP credentials](jetpack/jetpack-start-endpoints/setting-backups-ftp-credentials.md) 29 | - [Errors](jetpack/jetpack-start-endpoints/errors.md) 30 | - Activity, Backup, and Scan 31 | - [Fetch Activities](jetpack/jetpack-activity-endpoints/activity.md) 32 | - [Activity Group Counts](jetpack/jetpack-activity-endpoints/activity-count.md) 33 | - [Queue Restore](jetpack/jetpack-restore-endpoints/restore.md) 34 | - [Restore Status](jetpack/jetpack-restore-endpoints/restore-status.md) 35 | - [Fetch Backups](jetpack/jetpack-backup-endpoints/backups.md) 36 | - [Prepare Download](jetpack/jetpack-backup-endpoints/prepare-download.md) 37 | - [Download Status](jetpack/jetpack-backup-endpoints/downloads.md) 38 | - WooCommerce 39 | - [Overview](woocommerce/overview.md) 40 | - [Provison/Register plan](woocommerce/plan-register.md) 41 | - [Cancel plan](woocommerce/plan-cancel.md) 42 | - [Update URL for a site](woocommerce/update-url.md) 43 | - [Update site connected to a plan](woocommerce/update-connected-site.md) 44 | - [Install product](woocommerce/install.md) 45 | - [Product information](woocommerce/product-info.md) 46 | - [Management via WP-CLI](woocommerce/management-via-wp-cli.md) 47 | - Account creation 48 | - [Creating users via /jpphp/user endpoint](users/user-creation.md) 49 | - [Automatic account creation via Jetpack](jetpack/automatic-account-creation-connection.md) 50 | 51 | ## Become a hosting partner 52 | 53 | If you're not already a hosting partner, and you'd like some more information, head on over to [https://jetpack.com/for/hosts/](https://jetpack.com/for/hosts/) to get started! 54 | 55 | ## Change log 56 | 57 | - 2025-02-26 Added pages for install and update-connected-site endpoints. 58 | - 2020-04-27 Added change log. Added page for status endpoint v1.4. 59 | -------------------------------------------------------------------------------- /assets/jps-v1-2-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/host-partner-documentation/7dd39d058042e4bd0e67a20efac7ad5fa92d5b74/assets/jps-v1-2-overview.png -------------------------------------------------------------------------------- /assets/jps-v1-3-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/host-partner-documentation/7dd39d058042e4bd0e67a20efac7ad5fa92d5b74/assets/jps-v1-3-overview.png -------------------------------------------------------------------------------- /assets/sample-magic-link-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/host-partner-documentation/7dd39d058042e4bd0e67a20efac7ad5fa92d5b74/assets/sample-magic-link-email.png -------------------------------------------------------------------------------- /assets/woocommerce-register-flow-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/host-partner-documentation/7dd39d058042e4bd0e67a20efac7ad5fa92d5b74/assets/woocommerce-register-flow-chart.png -------------------------------------------------------------------------------- /faq.md: -------------------------------------------------------------------------------- 1 | ### What is the Jetpack Start API? ### 2 | The Jetpack Start API is a set of endpoints that allows partners the ability to set up and manage Jetpack plans and products for their own users. 3 | 4 | ### Is there Documentation for the Jetpack Start API? ### 5 | Yes. Documentation for the API is currently available here 6 | 7 | ### Is there a Sandbox or test environment available? ### 8 | There is not currently a sandbox for the Jetpack Start API however we do provide a test key which is not billed along with your production key for testing implementation of the Jetpack Start API. Note that attempting to get the status of a site provisioned with a test key will not work; only the status for sites provisioned with production keys can be retrieved. 9 | 10 | ### What can I do with the Jetpack Start API? ### 11 | The 2 major functions of the Jetpack Start API include allow for provisioning plans and cancelling provisioned plans. Ancillary functions to support the 2 main functions are also available and more information is provided in the documentation. 12 | 13 | ### Can I upgrade/downgrade plans? ### 14 | You can upgrade to a higher tier plan via the Jetpack Start API but you cannot downgrade a plan to a lower tier one. The only way to effectively downgrade a plan is to cancel the currently provisioned plan and then provisioning a new lower tier plan. 15 | 16 | ### Where are Jetpack backups and data stored? ### 17 | We have multiple data centers around the world for performance and redundancy to ensure that all data stored when using Jetpack features is safe 18 | 19 | ### Can I request that my users data be stored in a specific data center or location? ### 20 | This is currently not an option at this time. 21 | 22 | ### Is Jetpack GDPR compliant? ### 23 | We have a few great resources with information on Jetpack and the GDPR including 24 | https://jetpack.com/2018/05/25/jetpack-gdpr/ 25 | https://jetpack.com/support/privacy/ 26 | 27 | ### What kind of data does Jetpack Sync? ### 28 | Information on the data synced by Jetpack for available features can be found at https://jetpack.com/support/what-data-does-jetpack-sync/ 29 | 30 | ### Can I manage the redirect after a user connects their Jetpack account? ### 31 | The redirect can be managed to have the user sent back to their WordPress admin. Information for this can be found in the Github documentation. 32 | 33 | ### Can a user change the ownership of a Jetpack Plan? ### 34 | This can be done and information for doing this can be found at https://jetpack.com/support/transfer-your-jetpack-connection-or-plan-to-another-user/. 35 | 36 | ### Are there required whitelists for hosts using Jetpack? ### 37 | Information on system and network whitelists for Jetpack can be found at https://jetpack.com/support/hosting-faq/ 38 | 39 | ### Is Jetpack Compatible with x ? ### 40 | Jetpack is compatible with most other plugins and avilable options however we do keep a list of known issues and potential solutions to these issues at https://jetpack.com/support/getting-started-with-jetpack/known-issues/ 41 | 42 | ### Is there a way to manage my account being used with the Jetpack Start API? ### 43 | A partner portal is currently in development and will be available in the future. 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /jetpack/automatic-account-creation-connection.md: -------------------------------------------------------------------------------- 1 | # Automatic WordPress.com Account Creation and Connection 2 | 3 | As of mid-October 2018, when a hosting partner provisions a site via `https://public-api.wordpress.com/rest/v1.3/jpphp/provision`, whether by a direct API call or via the -now deprecated- `partner-provision.sh` shell script, there is logic in the API that *may* greatly simplify the provisioning and connection process. 4 | 5 | ## Automatic account creation pre-requisites 6 | 7 | There are two prerequisites which must be met in order for a WordPress.com account to be provisioned for a user and for the site to be automatically connected: 8 | 9 | - The hosting partner must be whitelisted. 10 | - There must not be an existing WordPress.com account with the same email address as the user that the site is being provisioned for. 11 | - This is based off of the email address for the user's account on the WordPress installation at the hosting partner. 12 | 13 | ## How it works 14 | 15 | When a partner makes a request to the API to provision a site, the API will first check that the above prerequisites are met. That being the case, the API will continue with the following: 16 | 17 | ### Create a WordPress.com account 18 | 19 | Based on the email address that is used by the user on the self-hosted WordPress installation, the API will attempt to create a WordPress.com account that: 20 | 21 | - Has an automatically generated username based off of the email address 22 | - Has an automatically generated password 23 | 24 | I'd like to point out that both of these values are automatically generated. This brings up a couple of things to consider when supporting these users. These topics will be covered below in [Support Considerations](#support-considerations). 25 | 26 | ### Connecting the site 27 | 28 | Once the new WordPress.com account is created, the API will then attempt to: 29 | 30 | - Generate a token that is used to sign communication between the self-hosted WordPress site and WordPress.com. 31 | - This token is specifically for requests that are signed for this user. By this point, there should already be a blog level token that has been generated and stored on both WordPress.com and the self-hosted WordPress site 32 | - Make a request from WordPress.com to the self-hosted WordPress site in order to set the token. 33 | 34 | ## Expected return 35 | 36 | If either of the above steps fails, then the API will attempt to continue provisioning disregard the automatically created account. If the API call succeeds, then the expected response would be similar to this: 37 | 38 | ```json 39 | { 40 | "success": true, 41 | "auth_required": false, 42 | "next_url": "http://example.com" 43 | } 44 | ``` 45 | 46 | The `next_url` value in this case would typically be a link for the user to login via [Secure Sign On](https://jetpack.com/support/sso/). But, since the `auth_required` value is `false`, then the host could choose to ignore the `next_url`. 47 | 48 | ## Support considerations 49 | 50 | **What happens if the user does not like the username that was automatically generated?** The user should be able to go to [WordPress.com](https://wordpress.com/me/account) and [change their username](https://en.support.wordpress.com/change-your-username/). 51 | 52 | **How does the user log in to their WordPress.com account if they don't know their password?** The user should be able to log in by: 53 | 54 | - Going to [https://wordpress.com/log-in](https://wordpress.com/log-in) 55 | - Clicking "Email me a login link" 56 | - Entering their email address 57 | - Clicking the log in link that was just emailed 58 | 59 | **What happens if the user does have a WordPress.com account with a different email address?** The user should be able to transfer the plan and ownership over to another account. Information for that functionality can be found at [https://jetpack.com/support/transfer-your-jetpack-connection-or-plan-to-another-user/](https://jetpack.com/support/transfer-your-jetpack-connection-or-plan-to-another-user/). 60 | -------------------------------------------------------------------------------- /jetpack/determining-connection-status.md: -------------------------------------------------------------------------------- 1 | # Determining Connection Status of Jetpack Sites 2 | 3 | Occasionally, hosting partners have asked for instructions on how to determine the connection status of a Jetpack site. There are a few ways to do this, some with more accuracy than others. This document will discuss the different strategies and their accuracy. 4 | 5 | ## Using WP-CLI 6 | 7 | The most accurate method for determining connection status would be to use the `wp jetpack status` command. 8 | 9 | Here's an example of running the command on a site that is connected to WordPress.com: 10 | 11 | ``` 12 | wp jetpack status 13 | Checking status for http://example.com 14 | Success: Jetpack is currently connected to WordPress.com 15 | The Jetpack Version is 6.4-alpha 16 | The WordPress.com blog_id is XXXXXX 17 | The WordPress.com account for the primary connection is username@example.com 18 | 19 | View full status with 'wp jetpack status full' 20 | ``` 21 | 22 | Here's an example of running the command on a site that is NOT connected to WordPress.com: 23 | 24 | ``` 25 | wp jetpack status 26 | Checking status for http://example.com 27 | Error: Jetpack is not currently connected to WordPress.com 28 | ``` 29 | 30 | ## Via the WordPress.com API 31 | 32 | Another, and less accurate, method of determining connection status is to call the WordPress.com API. This is considered less accurate because there is not a specific status for connected or disconnected. That being said, we are still able to tell fairly reliably whether a site is connected or not. 33 | 34 | To test the connection, we can make calls to the `/sites/%s/` endpoint. Making that request will look something like this: 35 | 36 | ``` 37 | curl https://public-api.wordpress.com/rest/v1.1/sites/eric.blog 38 | ``` 39 | 40 | When a site is connected to WordPress.com properly, the response will be something like this: 41 | 42 | ``` 43 | { 44 | "ID": 67272686, 45 | "name": "Eric Binnion", 46 | "description": "Mostly pictures of family with a healthy dose of WordPress", 47 | "URL": "https://eric.blog", 48 | "jetpack": true, 49 | "subscribers_count": 55, 50 | "icon": { 51 | "img": "https://i1.wp.com/eric.blog/wp-content/uploads/2015/08/cropped-profile.jpg?fit=512%2C512&strip=all&ssl=1", 52 | "ico": "https://i1.wp.com/eric.blog/wp-content/uploads/2015/08/cropped-profile.jpg?fit=16%2C16&strip=all&ssl=1" 53 | }, 54 | "logo": { 55 | "id": 0, 56 | "sizes": [], 57 | "url": "" 58 | }, 59 | "is_following": false, 60 | "meta": { 61 | "links": { 62 | "self": "https://public-api.wordpress.com/rest/v1.1/sites/67272686", 63 | "help": "https://public-api.wordpress.com/rest/v1.1/sites/67272686/help", 64 | "posts": "https://public-api.wordpress.com/rest/v1.1/sites/67272686/posts/", 65 | "comments": "https://public-api.wordpress.com/rest/v1.1/sites/67272686/comments/", 66 | "xmlrpc": "https://eric.blog/xmlrpc.php" 67 | } 68 | } 69 | } 70 | ``` 71 | 72 | One property that will always be present, and uniform, for connected Jetpack sites will be the `jetpack` property. So, if you decode the response from the API, if the `jetpack` key is present, and if the value is `true`, then the site is properly connected. Here's an example of how to do that in the terminal with `jq`: 73 | 74 | ``` 75 | curl -s https://public-api.wordpress.com/rest/v1.1/sites/eric.blog | jq '.jetpack' 76 | ``` 77 | 78 | There are some cases where this could fail. For example, if the site has disabled the JSON API, then the API response will not contain the `jetpack` key even though the site is connected. In practice, the JSON API is enabled on more than 83.5% of sites, and the JSON API is activated by default for new sites, so this will not occur often. 79 | -------------------------------------------------------------------------------- /jetpack/jetpack-activity-endpoints/activity-count.md: -------------------------------------------------------------------------------- 1 | # Fetch Counts of Activity Groups 2 | 3 | Returns a list of available activity groups for a site along with their counts. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//activity/count/group` 9 | - __blog_id__: Site to request groups for. 10 | 11 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 12 | 13 | ### Request Parameters 14 | 15 | - __number__: (number) Total number of activities to search. 16 | - __aggregate__ 17 | 18 | ### Successful response 19 | 20 | ``` 21 | { 22 | "groups": { 23 | "post": { 24 | "name": "Posts and Pages", 25 | "count": 69 26 | }, 27 | "attachment": { 28 | "name": "Media", 29 | "count": 5 30 | }, 31 | "user": { 32 | "name": "People", 33 | "count": 2 34 | }, 35 | "rewind": { 36 | "name": "Backups and Restores", 37 | "count": 10 38 | }, 39 | }, 40 | "totalItems": 86, 41 | "took": 0.094605 42 | } 43 | ``` 44 | 45 | ### Example 46 | 47 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity/count/groups?aggregate=1&number=1000` 48 | 49 | ### Notes 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /jetpack/jetpack-activity-endpoints/activity.md: -------------------------------------------------------------------------------- 1 | # Fetch Activity for a Site 2 | 3 | Returns a list of activities for the specified site. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//activity` 9 | - __blog_id__: Site to request activities for. 10 | 11 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 12 | 13 | ### Request Parameters 14 | 15 | - __action__ 16 | - __after__: (date) Start of date range. 17 | - __before__: (date) End of date range. 18 | - __by__ 19 | - __date_range__ 20 | - __group__: (string, array) List of activity types to filter on, examples: `plugin, theme, rewind`. See also the [group counts endpoint.](/jetpack/jetpack-activity-endpoints/activity-count.md) 21 | - __locale__ 22 | - __name__ 23 | - __not_group__ 24 | - __number__: (number) Total number of activities to return. 25 | - __on__ 26 | - __page__ 27 | - __search_after__ 28 | - __sort_order__ 29 | - __aggregate__ 30 | - __aggregate_show__ 31 | 32 | 33 | ### Successful response 34 | 35 | ``` 36 | { 37 | "@context": "https://www.w3.org/ns/activitystreams", 38 | "summary": "Activity log", 39 | "type": "OrderedCollection", 40 | "totalItems": 36, 41 | "page": 1, 42 | "totalPages": 1, 43 | "itemsPerPage": 1000, 44 | "id": "https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity?_envelope=1&aggregate=1&number=1000", 45 | "oldestItemTs": 1529570198443, 46 | "first": "https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity?_envelope=1&aggregate=1&number=1000&page=1", 47 | "last": "https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity?_envelope=1&aggregate=1&number=1000&page=1", 48 | "current": { 49 | "type": "OrderedCollectionPage", 50 | "id": "https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity?_envelope=1&aggregate=1&number=1000", 51 | "totalItems": 36, 52 | "orderedItems": [ 53 | { 54 | "summary": "User added", 55 | "content": { 56 | "text": "" 57 | }, 58 | "name": "user__added", 59 | "actor": { 60 | "type": "Person", 61 | "name": "examplename", 62 | "external_user_id": 1, 63 | "wpcom_user_id": 16623280, 64 | "icon": { 65 | "type": "Image", 66 | "url": "https://secure.gravatar.com/avatar/123456789?s=96&d=mm&r=g", 67 | "width": 96, 68 | "height": 96 69 | }, 70 | "role": "administrator" 71 | }, 72 | "type": "Add", 73 | "published": "2020-09-23T10:58:03.300+00:00", 74 | "generator": { 75 | "jetpack_version": 8.9, 76 | "blog_id": 155308227 77 | }, 78 | "is_rewindable": false, 79 | "rewind_id": "1600858683.3001", 80 | "gridicon": "user", 81 | "status": null, 82 | "activity_id": "AXS6nQl-ZME8RSzT89VO", 83 | "object": { 84 | "type": "Person", 85 | "name": null, 86 | "external_user_id": 16623280, 87 | "wpcom_user_id": 0 88 | }, 89 | "is_discarded": false 90 | } 91 | ] 92 | } 93 | } 94 | ``` 95 | 96 | ### Example 97 | 98 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity?aggregate=1&number=1000` 99 | 100 | ### Notes 101 | 102 | Full backup complete events and restore events are in group `rewind`. Events that can be restored to (full snapshots and incremental changes) have the property `is_rewindable: true`. 103 | 104 | -------------------------------------------------------------------------------- /jetpack/jetpack-activity-endpoints/single-activity.md: -------------------------------------------------------------------------------- 1 | # Fetch a Single Activity 2 | 3 | Lookup an activity by rewind id. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//activity` 9 | - __blog_id__: Site to request activities for. 10 | - __rewind_id__: ID of the activity to request, returned from the [site activity endpoint](/jetpack/jetpack-activity-endpoints/activity.md). 11 | 12 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 13 | 14 | ### Request Parameters 15 | 16 | None 17 | 18 | ### Successful response 19 | 20 | ``` 21 | { 22 | "activity_id": "AXXl1dQ8RFPhDhBzy4Be", 23 | "actor": {"type": "Application", "name": "Jetpack"}, 24 | "content": {"text": "34 plugins, 11 themes, 50 uploads, 6 posts"}, 25 | "generator": {"jetpack_version": 9.1, "blog_id": 155308227}, 26 | "gridicon": "cloud", 27 | "is_discarded": false, 28 | "is_rewindable": true, 29 | "name": "rewind__backup_complete_full", 30 | "object": {"type": "Backup", "backup_type": "full", "rewind_id": "1605878792.626", "backup_stats": "{"themes":{"count":11,"list":["bookshop","dara","g…:{"rows":0}},"prefix":"wp_","wp_version":"5.5.3"}", "backup_period": 1605878535}, 31 | "published": "2020-11-20T13:26:32.626+00:00", 32 | "rewind_id": "1605878792.626", 33 | "status": "success", 34 | "summary": "Backup and scan complete", 35 | } 36 | ``` 37 | 38 | ### Example 39 | 40 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/activity/1605878792.626` 41 | 42 | ### Notes 43 | 44 | None. 45 | -------------------------------------------------------------------------------- /jetpack/jetpack-backup-endpoints/backups.md: -------------------------------------------------------------------------------- 1 | # List Backups 2 | 3 | Return a list of the last 10 backup attempts. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//rewind/backups` 9 | - __blog_id__: (number) Site to queury. 10 | 11 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 12 | 13 | ### Request Parameters 14 | 15 | None 16 | 17 | ### Response Format 18 | 19 | Array of objects with the following fields: 20 | 21 | - __id__: (number) Backup id. 22 | - __started__: (date) Backup start time. 23 | - __last_updated__: (date) Time of the most recent event, or backup end time if complete. 24 | - __status__: (string) Backup status, one of `finished|started|no-credentials|credential-error|not-accessible|error|error-will-retry`. 25 | - __period__: (number) Unix timestamp representation of backup start time. 26 | - __is_scan__: (boolean) `true` if a security scan was performed as part of the backup (depends on plan). 27 | - __has_snapshot__: (boolean) `true` if backup was a success and a snapshot was stored. 28 | - __stats__: (object) Information about the number and types of items backed up. Object with keys `themes`, `plugins`, `uploads`, `tables`, `prefix` (table prefix), and `wp_version`. 29 | 30 | ### Successful Response 31 | 32 | ``` 33 | [{ 34 | has_snapshot: true 35 | id: "134296140" 36 | is_backup: "1" 37 | is_scan: "1" 38 | last_updated: "2020-11-05 13:23:36" 39 | percent: "100" 40 | period: "1604582319" 41 | started: "2020-11-05 13:18:40" 42 | stats: {themes: {…}, plugins: {…}, uploads: {…}, tables: {…}, prefix: "wp_", …} 43 | status: "finished" 44 | }, 45 | … 46 | ] 47 | ``` 48 | 49 | ### Example 50 | 51 | Fetch last 10 backup attempts for site `155308227`: 52 | 53 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/rewind/backups` 54 | 55 | ### Notes 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /jetpack/jetpack-backup-endpoints/downloads.md: -------------------------------------------------------------------------------- 1 | # Get Status of Downloads 2 | 3 | Returns the status of backup downloads for a site. Response contains the URL to download from once the archive has been generated. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//rewind/downloads/ 9 | - __blog_id__: (number) Site to request download status for. 10 | - __download_id__: (number) Optional, request status only for this download. Returns all downloads if omitted. 11 | 12 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 13 | 14 | ### Request Parameters 15 | 16 | None. 17 | 18 | ### Successful response 19 | 20 | ``` 21 | backupPoint: "2020-11-05T13:23:37+00:00" 22 | downloadCount: 0 23 | downloadId: 277469 24 | rewindId: "1604582617.404" 25 | startedAt: "2020-11-05T14:05:24+00:00" 26 | url: "https://public-api.wordpress.com/wpcom/v2/sites/155308227/rewind/downloads/277469/data?token=n94gJ0emrtzE1xMk12wUH6kASWlTVN3nQIqpdlfKSOjbe1exwIBfmYZ5JJd8VmIv" 27 | validUntil: "2020-11-06T14:05:33+00:00" 28 | ``` 29 | 30 | ### Example 31 | 32 | Fetch the status of all downloads for site `155308227`: 33 | 34 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/rewind/downloads` 35 | 36 | ### Notes 37 | 38 | URLs are valid for 24 hours after the archive finished packing. 39 | 40 | -------------------------------------------------------------------------------- /jetpack/jetpack-backup-endpoints/prepare-download.md: -------------------------------------------------------------------------------- 1 | # Prepare a Backup Snapshot for Download 2 | 3 | Request an archive of a backup snapshot for downloading. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//rewind/downloads` 9 | - __blog_id__: (number) Site to request the download for. 10 | 11 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 12 | 13 | ### Request Parameters 14 | 15 | - __rewindId__: (number) Optional unix timestamp of the snapshot to download. Assumes latest timestamp is not provided. 16 | - __types__: (object) Optional object with keys `themes`, `plugins`, `uploads`, `sqls`, `roots`, `contents`, `all`. Specify true for each type of data to be included in the archive. Assumes all if not provided. 17 | 18 | ### Successful Response 19 | 20 | Returns status info about the archive preperation: 21 | 22 | ``` 23 | { 24 | backupPoint: "2020-11-05T14:01:13+00:00" 25 | downloadId: 277467 26 | progress: 0 27 | rewindId: "1604584873.7525" 28 | startedAt: "2020-11-05T14:01:13+00:00" 29 | } 30 | ... 31 | ``` 32 | 33 | ### Example 34 | 35 | Prepare download of the latest backup data for site `155308227`: 36 | 37 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/rewind/downloads` 38 | 39 | ### Notes 40 | 41 | After calling this endpoint, poll for progress of the archive preparation with the the [download status endpoint](/jetpack/jetpack-backup-endpoints/download.md). 42 | 43 | -------------------------------------------------------------------------------- /jetpack/jetpack-restore-endpoints/restore-status.md: -------------------------------------------------------------------------------- 1 | # Get Restore Status 2 | 3 | Returns the current status of a given restore for the specified site. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v1.1/activity-log//rewind//restore-status` 9 | - __blog_id__: Site to request info for. 10 | - __restore_id__: The restore to request info for. 11 | 12 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 13 | 14 | ### Request Parameters 15 | 16 | None. 17 | 18 | ### Response Format 19 | 20 | The `restore_status` object contains the following fields: 21 | - __percent__: (number) current restore progress. 22 | - __status__: (string) One of `finished|fail|queued|aborted|running|killed`. 23 | - __rewind_id__: (number) the restore ID. 24 | - __is_dismissed__: (boolean) Can be used to track UI display status, refers to whether UI notice has been dismissed by the user. 25 | - __context__: (string) The credentials role, one of `main|alternate|import`. 26 | - __message__: (string) Further info about the status. 27 | - __error_code__: (number) Error code. 28 | - __failure_reason__: (string) Further information about any failure. 29 | 30 | ### Successful response 31 | 32 | ``` 33 | { 34 | "ok":true, 35 | "error":"", 36 | "restore_status":{ 37 | "percent":0, 38 | "status":"queued", 39 | "rewind_id":"1603977475", 40 | "is_dismissed":false, 41 | "context":"main", 42 | "message":"", 43 | "error_code":"", 44 | "failure_reason":"" 45 | } 46 | } 47 | ``` 48 | 49 | ### Example 50 | 51 | Fetch status for rewind `234725` on site `155308227`: 52 | 53 | `https://public-api.wordpress.com/rest/v1/activity-log/155308227/rewind/234725/restore-status` 54 | 55 | ### Notes 56 | -------------------------------------------------------------------------------- /jetpack/jetpack-restore-endpoints/restore.md: -------------------------------------------------------------------------------- 1 | # Queue a Restore 2 | 3 | Perform a restore on the given site to the specified timestamp. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v1.1/activity-log//rewind/to/` 9 | - __blog_id__: (number) Site to restore. 10 | - __timestamp__: (number) Unix timestamp to restore to. 11 | 12 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 13 | 14 | ### Request Parameters 15 | 16 | - __roleName__: (string) The credential role to restore to, one of `main|alternate|import`. 17 | - __types__: (optional string / array) Data and file types to restore, one or more of `all|themes|plugins|uploads|sqls|contents|roots`. Defaults to `all`. 18 | - __destinationSiteName__: (optional string) Title to give the site when using the `alternate` role. 19 | 20 | ### Successful response 21 | 22 | ``` 23 | { 24 | "ok":true, 25 | "error":"", 26 | "restore_id":234725, 27 | "job_id":4661184823 28 | } 29 | ``` 30 | 31 | ### Example 32 | 33 | Restore site 155308227 to 10/29/2020 12:47pm UTC: 34 | 35 | `https://public-api.wordpress.com/wpcom/v1.1/activity-log/155308227/rewind/to/1603975624` 36 | 37 | ### Notes 38 | 39 | The restore will use the closest full daily snapshot not newer than the given timestamp, and (where available) append more recent incremental updates not newer than the given timestamp PLUS any immutable incremental updates (such as WooCommerce orders) up to the current time. 40 | 41 | For a regular restore use the 'main' `roleName`. 'alternate' is for cloning to a different site and 'import' is reserved for internal use. 42 | 43 | Restore types: 44 | - `all`: Everything 45 | - `themes`: Themes folder 46 | - `plugins`: Plugins folder 47 | - `uploads`: Uploads folder 48 | - `sqls`: Database tables 49 | - `contents`: wp-content folder 50 | - `roots`: WordPress install root folder 51 | 52 | -------------------------------------------------------------------------------- /jetpack/jetpack-scan-endpoints/alerts.md: -------------------------------------------------------------------------------- 1 | # Ignore or fix a specific threat. 2 | 3 | This endpoint is used to act on a specific alert. It can be used to fix or ignore a threat. 4 | 5 | Request URL: https://public-api.wordpress.com/wpcom/v2/sites/212734736/alerts/81431083?ignore=true&_envelope=1 6 | 7 | 8 | ### Endpoint Information 9 | 10 | - __Method__: POST 11 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//alerts/` 12 | - __blog_id__: (number) Site to query. 13 | 14 | Authentication: [Bearer token](/jetpack/reporting-endpoints/README.md). 15 | 16 | ### Request Parameters 17 | 18 | #### Fixing a threat 19 | Append `?fix=true` in the query string if you want to fix the threat. 20 | 21 | #### Ignoring a threat. 22 | Append `?ignore=true` in the query string if you want to fix the threat. 23 | 24 | ### Response Format 25 | 26 | Object with the following fields encapsulated: 27 | 28 | - __alerts__: (object) An object containing information about the alerts of the site. It contains the following keys: 29 | - __threats__: (object) Same threat object as in the regular `scan` endpoint. 30 | - __credentials__: (object) Same credentials object as in the regular `scan` endpoint. 31 | - __last_updated__: (date) Timestamp when an alert was last updated. 32 | - __state__: (string) dunno yet. 33 | 34 | ### Successful Response 35 | 36 | ``` 37 | { 38 | "credentials": [{ 39 | "still_valid": true, 40 | "type": "managed", 41 | "role": "main" 42 | }], 43 | "alerts": { 44 | "threats": [{ 45 | "id": 81427324, 46 | "signature": "EICAR_AV_Test", 47 | "title": "Malicious code found in file: akismet.php", 48 | "description": "This is the standard EICAR antivirus test code, and not a real infection. If your site contains this code when you don't expect it to, contact Jetpack support for some help.", 49 | "vulnerability_description": "Threat found EICAR_AV_Test", 50 | "fix_description": "Jetpack Scan will replace the affected file or directory.", 51 | "payload_subtitle": null, 52 | "payload_description": null, 53 | "first_detected": "2022-11-27T20:06:54.000Z", 54 | "severity": 4, 55 | "fixer": { 56 | "fixer": "replace", 57 | "file": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 58 | "extensionStatus": "active" 59 | }, 60 | "status": "current", 61 | "fixable": { 62 | "fixer": "replace", 63 | "file": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 64 | "extensionStatus": "active" 65 | }, 66 | "filename": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 67 | "context": { 68 | "2": "\/**", 69 | "3": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 70 | "4": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 71 | "5": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 72 | "6": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 73 | "7": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 74 | "8": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 75 | "9": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 76 | "10": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 77 | "11": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 78 | "12": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 79 | "13": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 80 | "14": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 81 | "15": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 82 | "16": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 83 | "17": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 84 | "18": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 85 | "19": " * ", 86 | "20": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 87 | "21": " * @package Akismet", 88 | "marks": {} 89 | } 90 | }] 91 | }, 92 | "downloads": [], 93 | "state": "active", 94 | "last_updated": "2022-11-27T21:36:51.593+00:00" 95 | } 96 | ``` 97 | 98 | ### Example 99 | 100 | To ignore the threat `81427324` for the site `155308227`: 101 | 102 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/alerts/81427324?ignore=true` 103 | 104 | To fix the threat `81427324` for the site `155308227`: 105 | 106 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/alerts/81427324?ignore=true` 107 | -------------------------------------------------------------------------------- /jetpack/jetpack-scan-endpoints/enqueue_scan.md: -------------------------------------------------------------------------------- 1 | # Enqueue a scan attempt. 2 | 3 | Enqueue a scan attempt for a site. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//scan/enqueue` 9 | - __blog_id__: (number) Site to query. 10 | 11 | Authentication: [Bearer token](/jetpack/reporting-endpoints/README.md). 12 | 13 | ### Request Parameters 14 | 15 | None 16 | 17 | ### Response Format 18 | 19 | Object with the following fields encapsulated: 20 | 21 | - __success__: (boolean) A boolean indicating if the scan attempt was successfully enqueued. 22 | 23 | ### Successful Response 24 | 25 | ``` 26 | { 27 | success: true 28 | } 29 | ``` 30 | 31 | ### Example 32 | 33 | Fetch scan information for site `155308227`: 34 | 35 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/scan` 36 | -------------------------------------------------------------------------------- /jetpack/jetpack-scan-endpoints/fix.md: -------------------------------------------------------------------------------- 1 | # Fix multiple threats 2 | 3 | Fixes multiple threats at once. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//alerts/fix` 9 | - __blog_id__: (number) Site to query. 10 | 11 | Authentication: [Bearer token](/jetpack/reporting-endpoints/README.md). 12 | 13 | ### Request Parameters 14 | 15 | Request parameters can be serialized in json. 16 | 17 | - __threat_ids__: (array) An array of threat ids. 18 | 19 | ## Request body example 20 | 21 | ``` 22 | { 23 | threat_ids: [81444650, 81444645, 81444565] 24 | } 25 | ``` 26 | 27 | ### Response Format 28 | 29 | Object with the following fields encapsulated: 30 | 31 | - __ok__: (boolean) A boolean indicating if the request was successful. 32 | - __threats__: (object) An object containing a key for each threat id that was passed in the request. Each key will have it's own object with a status node indicating how the fixer for that particular threat is progressing. 33 | 34 | ### Successful Response 35 | 36 | ``` 37 | { 38 | "ok": true, 39 | "threats": { 40 | "81444650": { 41 | "status": "in_progress" 42 | }, 43 | "81444645": { 44 | "status": "in_progress" 45 | }, 46 | "81444565": { 47 | "status": "in_progress" 48 | } 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /jetpack/jetpack-scan-endpoints/fix_status.md: -------------------------------------------------------------------------------- 1 | # Get the status of a fixer job 2 | 3 | Gets the status of one or multiple fixer jobs that were started. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//alerts/fix` 9 | - __blog_id__: (number) Site to query. 10 | 11 | Authentication: [Bearer token](/jetpack/reporting-endpoints/README.md). 12 | 13 | ### Request Parameters 14 | 15 | Parameters must be passed by query string. 16 | 17 | - __threat_ids__: (array) An array of threat ids. 18 | 19 | 20 | ### Response Format 21 | 22 | Object with the following fields encapsulated: 23 | 24 | - __ok__: (boolean) A boolean indicating if the request was successful. 25 | - __threats__: (object) An object containing a key for each threat id that was passed in the request. Each key will have it's own object with a status node indicating how the fixer for that particular threat is progressing. 26 | 27 | ### Successful Response 28 | 29 | ``` 30 | { 31 | "ok": true, 32 | "threats": { 33 | "81444650": { 34 | "status": "in_progress" 35 | }, 36 | "81444645": { 37 | "status": "in_progress" 38 | }, 39 | "81444565": { 40 | "status": "in_progress" 41 | } 42 | } 43 | } 44 | ``` 45 | 46 | ### Example 47 | 48 | Request URL: https://public-api.wordpress.com/wpcom/v2/sites/212734736/alerts/fix/?_envelope=1&threat_ids%5B%5D=81444650&threat_ids%5B%5D=81444645&threat_ids%5B%5D=81444565 49 | 50 | 51 | Fetch fixer information for site `212734736` and for the threats `81444650`, `81444645` and `81444565`: 52 | 53 | `https://public-api.wordpress.com/wpcom/v2/sites/212734736/alerts/fix/?threat_ids[]=81444650&threat_ids[]=81444645&threat_ids[]=81444565` 54 | -------------------------------------------------------------------------------- /jetpack/jetpack-scan-endpoints/scan.md: -------------------------------------------------------------------------------- 1 | # List data from last Scan 2 | 3 | Return data from the last Scan. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/sites//scan` 9 | - __blog_id__: (number) Site to query. 10 | 11 | Authentication: [Access token](/jetpack/jetpack-start-endpoints/authentication.md). 12 | 13 | ### Request Parameters 14 | 15 | None 16 | 17 | ### Response Format 18 | 19 | Object with the following fields encapsulated: 20 | 21 | - __state__: (string) State of the scanner, possible states are: `idle`, `provisioning`, `unavailable`, `scanning`. 22 | - __threats__: (array) Array of threat objects. A threat object contain the following keys: 23 | - __id__: (number) The id of this particular threat. 24 | - __signature__: (string) The name of the signature that triggered the threat. 25 | - __title__: (string) A human readable title for the threat. 26 | - __description__: (string) The more detailed description of what the threat. 27 | - __vulnerability_description__: (string) tbd 28 | - __fix_description__: (string) A human readable description for what the fixer will do to fix this threat. 29 | - __payload_subtitle__: (string) tbd 30 | - __payload_description__: (string) tbd 31 | - __first_detected__: (string) The date when this threat was first detected on this site. 32 | - __severity__: (number) A number representing the severity of this threat. 1 is `suspicious`, 2 is `low`, 3 is `medium`, 4 is `high`, 5 is `critical`. 33 | - __fixer__: (object) An object with information about the fixer if applicable. The keys for the object are: 34 | - __fixer__: (string) The name of the fixer that will be used for this threat. 35 | - __file__: (string) The file that will be affected by the fixer. 36 | - __extensionStatus__: (string) The activation status for the extension this threat affects if applicable. 37 | - __status__: (string) Status of the threat, possible values are `current`, `new`, `ignored`, `fixed`. 38 | - __fixable__: (object) Same as `fixer`. 39 | - __filename__: (string) The file where this threat was found in. 40 | - __context__: (object) An object with more information about how the threat was found. It contains the lines with the malicious code if it's a file threat as keys. 41 | - __extension__: (object) If the threat was caused by a vulnerable version of an extension this node will contain information about that extension. The keys for this object are: 42 | - __isPremium__: (boolean) A boolean indicating if this is a premium extension or not. 43 | - __name__: (string) Name of the extension. 44 | - __slug__: (string) Slug of the extension. 45 | - __type__: (string) Type of the extension, could be either `plugin` or `theme`. 46 | - __version__: (string) Version of the extension. 47 | - __has_cloud__: (boolean) Whether a site has Jetpack Cloud access or not. 48 | - __credentials__: (array) Array of objects containing credentials that we have stored. The object has the following keys: 49 | - __still_valid__: (boolean) A boolean indicating if the credentials are still valid or not. 50 | - __type__: (string) The type of the credentials. 51 | - __role__: (string) The role of the credentials. 52 | - __most_recent__: (object) An object containing information about the most recent scan attempt. It contains the following keys: 53 | - __is_initial__: (boolean) A boolean indicating if this is the first scan attempt. 54 | - __timestamp__: (date) The timestamp for the scan attempt. 55 | - __duration__: (number) The duration for the scan attempt in seconds. 56 | - __progress__: (number) The percentage for the scan attempt. 57 | - __error__: (boolean) A boolean indicating if the scan attempt failed or not. 58 | 59 | ### Successful Response 60 | 61 | ``` 62 | { 63 | "state": "idle", 64 | "threats": [{ 65 | "id": 81427324, 66 | "signature": "EICAR_AV_Test", 67 | "title": "Malicious code found in file: akismet.php", 68 | "description": "This is the standard EICAR antivirus test code, and not a real infection. If your site contains this code when you don't expect it to, contact Jetpack support for some help.", 69 | "vulnerability_description": "Threat found EICAR_AV_Test", 70 | "fix_description": "Jetpack Scan will replace the affected file or directory.", 71 | "payload_subtitle": null, 72 | "payload_description": null, 73 | "first_detected": "2022-11-27T20:06:54.000Z", 74 | "severity": 4, 75 | "fixer": { 76 | "fixer": "replace", 77 | "file": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 78 | "extensionStatus": "active" 79 | }, 80 | "status": "current", 81 | "fixable": { 82 | "fixer": "replace", 83 | "file": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 84 | "extensionStatus": "active" 85 | }, 86 | "filename": "\/srv\/htdocs\/wp-content\/plugins\/akismet\/akismet.php", 87 | "context": { 88 | "2": "\/**", 89 | "3": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 90 | "4": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 91 | "5": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 92 | "6": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 93 | "7": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 94 | "8": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 95 | "9": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 96 | "10": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 97 | "11": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 98 | "12": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 99 | "13": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 100 | "14": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 101 | "15": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 102 | "16": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 103 | "17": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 104 | "18": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 105 | "19": " * ", 106 | "20": " * X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*", 107 | "21": " * @package Akismet", 108 | "marks": {} 109 | } 110 | }], 111 | "has_cloud": true, 112 | "credentials": [{ 113 | "still_valid": true, 114 | "type": "managed", 115 | "role": "main" 116 | }], 117 | "most_recent": { 118 | "is_initial": false, 119 | "timestamp": "2022-11-27T20:41:27+00:00", 120 | "duration": 41, 121 | "progress": 100, 122 | "error": false 123 | } 124 | } 125 | ``` 126 | 127 | ### Example 128 | 129 | Fetch scan information for site `155308227`: 130 | 131 | `https://public-api.wordpress.com/wpcom/v2/sites/155308227/scan` 132 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/README.md: -------------------------------------------------------------------------------- 1 | # Jetpack Start API 2 | 3 | ## [Authentication](https://github.com/Automattic/host-partner-documentation/blob/master/jetpack/jetpack-start-endpoints/authentication.md) 4 | 5 | Most of the Jetpack Start API endpoints require an OAuth 2 token to be supplied via the `Authorization` header in order to authenticate your requests. This article covers all the details on how to get that token and how to use it in requests. 6 | 7 | ## [Provisioning](https://github.com/Automattic/host-partner-documentation/blob/master/jetpack/jetpack-start-endpoints/plan-provisioning.md) 8 | 9 | This article covers the provisioning endpoints of the API which allows you to provide a Jetpack product to a site. 10 | 11 | ## [Cancelling](https://github.com/Automattic/host-partner-documentation/blob/master/jetpack/jetpack-start-endpoints/plan-cancellation.md) 12 | 13 | This article covers the cancellation endpoints of the API which allows you to stop providing a Jetpack product to a site. 14 | 15 | --- 16 | 17 | Feel free to browse through the rest of the documentation in this section as it covers a variety of endpoints and use cases. 18 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/authentication.md: -------------------------------------------------------------------------------- 1 | # Getting a Jetpack Partner access token 2 | 3 | When you become a Jetpack partner, we will provide you with your partner ID and a secret key. Previously, you would have just passed these values directly in to the `bin/partner-provision.sh` and `bin/partner_cancel.sh` scripts, but those are now deprecated, so the only option is to call the API directly. To do so, you'll first need to get an access token with for your partner ID with a scope of `jetpack-partner`. 4 | 5 | To get a token, you'll make a `POST` request to the `https://public-api.wordpress.com/oauth2/token` endpoint passing with the request parameters mentioned below. 6 | 7 | A successful response will include a JSON object with several keys. We are specifically interested in the `access_token` key, so be sure to grab that. 8 | 9 | For more detailed information about oAuth on WordPress.com, visit the [documentation on oAuth2 authentication](https://developer.wordpress.com/docs/oauth2/). 10 | 11 | ### Endpoint Information (/oauth2/token) 12 | 13 | - __Method__: POST 14 | - __URL__: `https://public-api.wordpress.com/oauth2/token` 15 | 16 | ### Request Parameters (/oauth2/token) 17 | 18 | - __grant_type__: Value should be `client_credentials` 19 | - __scope__: Value should be `jetpack-partner` 20 | - __client_id__: The partner ID that we provide you 21 | - __client_secret__: The partner secret that we provide you 22 | 23 | ### Response Parameters (/oauth2/token) 24 | 25 | - __access_token__: (string) This is the access token we'll need for the API calls below. 26 | - __token_type__: (string) This should be `bearer`. 27 | - __blog_id__: (int) This should be `0`. 28 | - __blog_url__: (int) This should be `0`. 29 | - __scope__: (string) This should be `jetpack-partner`. 30 | 31 | Note: You only need to create the `access_token` once. 32 | 33 | ### Examples (/oauth2/token) 34 | 35 | Here is an example using cURL in shell. 36 | 37 | ```shell 38 | # Note: This example uses jq to parse JSON from the API. 39 | PARTNER_ID="your_partner_id_here" 40 | PARTNER_SECRET="your_partner_secret_here" 41 | RESULT=$( curl --request POST \ 42 | --url https://public-api.wordpress.com/oauth2/token \ 43 | --header 'cache-control: no-cache' \ 44 | --header 'content-type: multipart/form-data;' \ 45 | --form client_id="$PARTNER_ID" \ 46 | --form client_secret="$PARTNER_SECRET" \ 47 | --form grant_type=client_credentials \ 48 | --form scope=jetpack-partner ) 49 | 50 | ACCESS_TOKEN=$( echo "$RESULT" | jq -r '.access_token' ) 51 | echo "Access token is: $ACCESS_TOKEN" 52 | ``` 53 | 54 | Here's an example using the request module in Node JS. 55 | 56 | ```javascript 57 | var request = require( 'request' ); 58 | var clientId = 'your_partner_id_here'; 59 | var clientSecret = 'your_partner_secret_here'; 60 | 61 | var options = { 62 | method: 'POST', 63 | url: 'https://public-api.wordpress.com/oauth2/token', 64 | headers: { 65 | 'cache-control': 'no-cache', 66 | 'content-type': 'multipart/form-data;' 67 | }, 68 | formData: { 69 | client_id: clientId, 70 | client_secret: clientSecret, 71 | grant_type: 'client_credentials', 72 | scope: 'jetpack-partner' 73 | } 74 | }; 75 | 76 | request( options, function ( error, response, body ) { 77 | if ( error ) { 78 | throw new Error( error ); 79 | } 80 | 81 | console.log( 'The access token is ' + JSON.parse( body ).access_token ); 82 | } ); 83 | 84 | ``` 85 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/determining-provisioning-status-v1.4.md: -------------------------------------------------------------------------------- 1 | # Determining Provisioning Status of a Jetpack Site 2 | 3 | At times, it may be desirable to check the provisioning status of a site to get information such as: 4 | 5 | - Does a given site have a plan/product provisioned? If so, which? 6 | - Does a given site have a pending activation? 7 | - Was provisioned made by a given partner? 8 | - Is the site connected to WordPress.com? 9 | 10 | To provide the provisioning status of a site, there is the `/1.4/jpphp/{$siteOrBlogId}/status` endpoint. 11 | 12 | ## Getting an access token 13 | 14 | To query this status endpoint, you'll first need to retrieve an access token. Information about that can be found on the [Authentication API document](../jetpack-start-endpoints/authentication.md#getting-a-jetpack-partner-access-token ). 15 | 16 | ## Endpoint Information 17 | 18 | - __Method__: GET 19 | - __URL__: `https://public-api.wordpress.com/rest/v1.4/jpphp/{$siteOrBlogId}/status` 20 | 21 | `$siteOrBlogId` can either be: 22 | 23 | - The WordPress.com blog ID. 24 | - The site's domain and path where `/` in the path is replaced with `::`. For example: 25 | 26 | | Site URL | $site Identifier | 27 | | --------------------- | ------------------- | 28 | | `example.com` | `example.com` | 29 | | `example.com/demo` | `example.com::demo` | 30 | | `example.com/demo/wp` | `example.com::demo::wp` | 31 | 32 | ## Query Parameters 33 | 34 | - __http_envelope__: Default to `false`. Sending `true` will force the HTTP status code to always be `200`. The JSON response is wrapped in an envelope containing the "real" HTTP status code and headers. 35 | - __pretty__: Defaults to `false`. Setting to `true` will output pretty JSON. 36 | 37 | ## Response Parameters 38 | 39 | - __blog__: (array) Blog specific information. 40 | - __is_connected__: (bool) Is the site connected to WordPress.com? 41 | - __has_backups_credentials__: (bool) Does the site have Jetpack Backup SSH/FTP credentials set? 42 | - __products__: (array) A list with everything that was provisioned for this site. 43 | - __slug__: (string) The slug of the provisioned product. 44 | - __is_provisioned_by_partner__: (bool) Was this product provisioned by a partner? 45 | - __is_provisioned_by_calling_partner__: (bool) Was this product provisioned by the partner making this status request? 46 | - __is_pending__: (bool) Is this product pending connection authorization before being provisioned? 47 | 48 | ## Endpoint errors 49 | 50 | | HTTP Code | Error Identifier | Error Message | 51 | | --------- | --------------------- | ------------------------------------------------------------------------- | 52 | | 400 | partner_key_disabled | This key is disabled. | 53 | | 403 | invalid_scope | This token is not authorized to provision partner sites | 54 | | 403 | invalid_blog | The blog ID %s is invalid | 55 | 56 | ## Examples 57 | 58 | Here's an example using cURL in shell. 59 | 60 | ```shell 61 | ACCESS_TOKEN="access_token_here" 62 | SITE_DOMAIN="example.com" 63 | curl --request GET \ 64 | --url https://public-api.wordpress.com/rest/v1.4/jpphp/"$SITE_DOMAIN"/status \ 65 | --header "authorization: Bearer $ACCESS_TOKEN" \ 66 | --header 'cache-control: no-cache' \ 67 | ``` 68 | 69 | Here's an example using the request module in Node JS. 70 | 71 | ```javascript 72 | var request = require( 'request '); 73 | var accessToken = 'access_token_here'; 74 | var siteDomain = 'example.com'; 75 | 76 | var options = { 77 | method: 'GET', 78 | url: 'https://public-api.wordpress.com/rest/v1.4/jpphp/' + siteDomain + '/status', 79 | headers: { 80 | 'cache-control': 'no-cache', 81 | authorization: 'Bearer ' + accessToken 82 | } 83 | }; 84 | 85 | request( options, function ( error, response, body ) { 86 | if ( error ) { 87 | throw new Error( error ); 88 | } 89 | 90 | console.log( body ); 91 | } ); 92 | ``` 93 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/determining-provisioning-status.md: -------------------------------------------------------------------------------- 1 | # Deprecation notice 2 | 3 | This version of the endpoint has been deprecated. Please use the [1.4 version of the staus endpoint](jetpack/jetpack-start-endpoints/determining-provisioning-status-v1.4.md) instead. 4 | 5 | # Determining Provisioning Status of a Jetpack Site 6 | 7 | At times, it may be desirable to check the provisioning status of a site to get information such as: 8 | 9 | - Does a given site have a plan provisioned? 10 | - Was the plan provisioned by a given partner? 11 | - Is the site connected to WordPress.com? 12 | 13 | To provide the provisioning status of a site, there is the `/jpphp/{$siteOrBlogId}/status` endpoint. 14 | 15 | ## Getting an access token 16 | 17 | To query this status endpoint, you'll first need to retrieve an access token. Information about that can be found on the [Authentication API document](../jetpack-start-endpoints/authentication.md#getting-a-jetpack-partner-access-token ). 18 | 19 | ## Endpoint Information 20 | 21 | - __Method__: GET 22 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/{$siteOrBlogId}/status` 23 | 24 | `$siteOrBlogId` can either be: 25 | 26 | - The WordPress.com blog ID. 27 | - The site's domain and path where `/` in the path is replaced with `::`. For example: 28 | 29 | | Site URL | $site Identifier | 30 | | --------------------- | ------------------- | 31 | | `example.com` | `example.com` | 32 | | `example.com/demo` | `example.com::demo` | 33 | | `example.com/demo/wp` | `example.com::demo::wp` | 34 | 35 | ## Query Parameters 36 | 37 | - __http_envelope__: Default to `false`. Sending `true` will force the HTTP status code to always be `200`. The JSON response is wrapped in an envelope containing the "real" HTTP status code and headers. 38 | - __pretty__: Defaults to `false`. Setting to `true` will output pretty JSON. 39 | 40 | ## Response Parameters 41 | 42 | - __plan__: (string) The slug of the provisioned plan or empty string when no plan. 43 | - __is_partner_plan__: (bool) Does the site have a plan that was provisioned by a partner? 44 | - __is_provisioned_by_calling_partner__: (bool) Does the site have a plan that was provisioned by the partner making this status request? 45 | - __is_connected__: (bool) Is the site connected to WordPress.com? 46 | - __has_pending_plan__: (bool) Does the site have a pending plan that requires connection authorization? 47 | - __has_backups_credentials__: (bool) Does the site have Jetpack Backup SSH/FTP credentials set? 48 | - __products__: (array) Additional product items provisioned for the site including Jetpack backups products and other items. 49 | - __product__: (string) The slug of the provisioned product. 50 | - __is_partner_product__: (bool) Was this product provisioned by a partner? 51 | - __has_pending_product__: (bool) Does this product require connection authorization? 52 | - __is_provisioned_by_calling_partner__: (bool) Was this product provisioned by the partner making this status request? 53 | 54 | ## Endpoint errors 55 | 56 | | HTTP Code | Error Identifier | Error Message | 57 | | --------- | --------------------- | ------------------------------------------------------------------------- | 58 | | 400 | partner_key_disabled | This key is disabled. | 59 | | 403 | invalid_scope | This token is not authorized to provision partner sites | 60 | | 403 | invalid_blog | The blog ID %s is invalid | 61 | 62 | ## Examples 63 | 64 | Here's an example using cURL in shell. 65 | 66 | ```shell 67 | ACCESS_TOKEN="access_token_here" 68 | SITE_DOMAIN="example.com" 69 | curl --request GET \ 70 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/"$SITE_DOMAIN"/status \ 71 | --header "authorization: Bearer $ACCESS_TOKEN" \ 72 | --header 'cache-control: no-cache' \ 73 | ``` 74 | 75 | Here's an example using the request module in Node JS. 76 | 77 | ```javascript 78 | var request = require( 'request '); 79 | var accessToken = 'access_token_here'; 80 | var siteDomain = 'example.com'; 81 | 82 | var options = { 83 | method: 'GET', 84 | url: 'https://public-api.wordpress.com/rest/v1.3/jpphp/' + siteDomain + '/status', 85 | headers: { 86 | 'cache-control': 'no-cache', 87 | authorization: 'Bearer ' + accessToken 88 | } 89 | }; 90 | 91 | request( options, function ( error, response, body ) { 92 | if ( error ) { 93 | throw new Error( error ); 94 | } 95 | 96 | console.log( body ); 97 | } ); 98 | ``` 99 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | This endpoint returns the error codes than can be returned by the API. The default response is that for each possible error, it returns an error key and a description in English. You can specify to use a verbose mode which will also include possible causes and solutions for each error. 4 | 5 | ## Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/errors` 9 | 10 | ### Query Parameters (/errors) 11 | 12 | - __verbose__: Returns a verbose response with possible causes and solutions for each error. There is no need to set it to a value; as long as it is present in the request, a verbose answer will be returned. 13 | 14 | #### Successful response 15 | 16 | - __errors__: (object) Errors list. 17 | 18 | ### Example 19 | 20 | ```shell 21 | curl --request GET \ 22 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/errors \ 23 | --header 'Accept: */*' \ 24 | --header 'Cache-Control: no-cache' 25 | ``` 26 | 27 | ### Example output (brief) 28 | 29 | Note: the output has been shortened to simplify the documentation. Please call the endpoint to get all the possible errors. 30 | 31 | ```json 32 | { 33 | "errors": { 34 | "activation_limit_reached": "This key has reached its activation limit for product %s", 35 | "could_not_load_product_class": "Could not load a product class", 36 | "error_access_token": "Failed to create access token", 37 | "failed_registration_unknown_blog": "Remote site returned an invalid site ID" 38 | } 39 | } 40 | ``` 41 | 42 | ### Example output (verbose) 43 | 44 | Note: the output has been shortened to simplify the documentation. Please call the endpoint to get all the possible errors. 45 | 46 | ```json 47 | { 48 | "errors": { 49 | "activation_limit_reached": { 50 | "description": "This key has reached its activation limit for product %s", 51 | "cause": "You're trying to provision a plan using a key that can no longer provision more of the requested plan.", 52 | "solution": "Contact the Jetpack Start team." 53 | }, 54 | "could_not_load_product_class": { 55 | "description": "Could not load a product class", 56 | "cause": "We could not find a product that matched the requested plan.", 57 | "solution": "Make sure the value of the `plan` parameter is valid." 58 | } 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/mobile-magic-link.md: -------------------------------------------------------------------------------- 1 | # Sending magic links for logging in to the WordPress mobile app 2 | 3 | Partners can request that users be sent an email with a "magic" link that will allow them to log in to the WordPress app just by following a link they receive via email. This prevents them from having to remember their username/password and streamlines the whole login process. The following API call requests such an email be sent to the specified user. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/mobile-magic-link` 9 | 10 | ### Request Parameters 11 | 12 | - __email__: The user's email to send the magic link to. 13 | 14 | ### Successful response 15 | 16 | - __success__: (bool) Was the operation successful? 17 | 18 | ### Errored response 19 | 20 | - __error__: (string) Error code, if any. 21 | - __message__: (string) Error message, if any. 22 | 23 | ### Example 24 | 25 | Here is an example using cURL in shell. Note that for this call, `$ACCESS_TOKEN` should be a `jetpack-partner` scope token. 26 | 27 | ```bash 28 | curl --request POST \ 29 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/mobile-magic-link \ 30 | --header 'cache-control: no-cache' \ 31 | --header 'content-type: multipart/form-data;' \ 32 | --header "authorization: Bearer $ACCESS_TOKEN" \ 33 | --form email="$EMAIL" 34 | ``` 35 | 36 | Here is an example of the email that is sent. 37 | 38 | ![Magic links screenshot](/assets/sample-magic-link-email.png) 39 | 40 | ### Notes 41 | 42 | This endpoint is throttled and will only allow up to 5 requests per email per hour. If this limit is exceeded the following error will be returned: 43 | 44 | ```json 45 | {"error":"too_many_requests","message":"Too many requests per time interval"} 46 | ``` 47 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/plan-cancellation.md: -------------------------------------------------------------------------------- 1 | # Cancelling a plan 2 | 3 | Plans can be cancelled by making a request using your partner token from the step above and the URL of the site being cancelled. 4 | 5 | ### Endpoint Information (/partner-cancel) 6 | 7 | - __Method__: POST 8 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/{$siteOrBlogId}/partner-cancel` 9 | 10 | `$siteOrBlogId` can either be: 11 | 12 | - The WordPress.com blog ID. 13 | - The site's domain and path where `/` in the path is replaced with `::`. For example: 14 | 15 | | Site URL | $site Identifier | 16 | | --------------------- | ------------------- | 17 | | `example.com` | `example.com` | 18 | | `example.com/demo` | `example.com::demo` | 19 | | `example.com/demo/wp` | `example.com::demo::wp` | 20 | 21 | ### Request Parameters (/partner-cancel) 22 | - __plan__: A slug representing which plan or item to cancel. Note this is an optional parameter for Jetpack Plans (Personal, Premium, Professional) but required for cancelling standalone items including Jetpack backups. 23 | - Plans: `free`, `personal`, `premium`, or `professional`. 24 | - Backups: `jetpack-backup-realtime` or `jetpack-backup-daily`. 25 | - Scan: `jetpack-scan` 26 | - Anti Spam: `jetpack-anti-spam` 27 | - __cancel-all__: Optional. If this option is set to true, ALL purchased items provisioned by the calling partner for a given site URL will be cancelled. 28 | 29 | 30 | ### Query Parameters (/partner-cancel) 31 | - __http_envelope__: Default to `false`. Sending `true` will force the HTTP status code to always be `200`. The JSON response is wrapped in an envelope containing the "real" HTTP status code and headers. 32 | - __pretty__: Defaults to `false`. Setting to `true` will output pretty JSON. 33 | 34 | ### Response Parameters (/partner-cancel) 35 | 36 | Below, the response parameters are grouped by whether the request to cancel errored or not. 37 | 38 | #### Successful response (/partner-cancel) 39 | 40 | - __success__: (bool) Was the operation successful?. It is possible for success to be false if a plan did not exist for the site. 41 | 42 | - __pending_activations__: (conditional) (array) If cancel-all is set for the request, then this property will be added to the response to indicate all pending activations that were cancelled. 43 | 44 | - __activations__: (conditional) (array) If cancel-all is set for the request, then this property will be added to the response to indicate all activations that were cancelled. 45 | 46 | #### Errored response (/partner-cancel) 47 | 48 | - __error_code__: (string) Error code, if any. 49 | - __error_message__: (string) Error message, if any. 50 | 51 | ### Endpoint errors (/partner-cancel) 52 | 53 | | HTTP Code | Error Identifier | Error Message | 54 | | --------- | --------------------- | ------------------------------------------------------------------------- | 55 | | 400 | invalid_input | Unable to delete subscription | 56 | | 400 | not_jps_plan | The plan for this site was not provisioned by Jetpack Start | 57 | | 403 | invalid_scope | This token is not authorized to provision partner sites | 58 | | 403 | invalid_blog | The blog ID %s is invalid | 59 | | 403 | incorrect_partner_key | Subscriptions can only be cancelled by the oAuth client that created them | 60 | 61 | ### Examples (/partner-cancel) 62 | 63 | Here's an example using cURL in shell. 64 | 65 | ```shell 66 | ACCESS_TOKEN="access_token_here" 67 | SITE_DOMAIN="example.com" 68 | curl --request POST \ 69 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/"$SITE_DOMAIN"/partner-cancel \ 70 | --header "authorization: Bearer $ACCESS_TOKEN" \ 71 | --header 'cache-control: no-cache' \ 72 | ``` 73 | 74 | Here's an example using the request module in Node JS. 75 | 76 | ```javascript 77 | var request = require( 'request '); 78 | var accessToken = 'access_token_here'; 79 | var siteDomain = 'example.com'; 80 | 81 | var options = { 82 | method: 'POST', 83 | url: 'https://public-api.wordpress.com/rest/v1.3/jpphp/' + siteDomain + '/partner-cancel', 84 | headers: { 85 | 'cache-control': 'no-cache', 86 | authorization: 'Bearer ' + accessToken 87 | } 88 | }; 89 | 90 | request( options, function ( error, response, body ) { 91 | if ( error ) { 92 | throw new Error( error ); 93 | } 94 | 95 | console.log( body ); 96 | } ); 97 | ``` 98 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/plan-provisioning.md: -------------------------------------------------------------------------------- 1 | If you have any questions or issues, our contact information can be found on the [README.md document](../../README.md). 2 | 3 | ## What is Jetpack Start? 4 | 5 | Jetpack Start is a collection of endpoints that you can call in order to provision and cancel Jetpack plans for your customers. These endpoints also take care of activating any plan-specific features or activating additional plugin dependencies such as Akismet. 6 | 7 | ## Provisioning a plan 8 | 9 | Plans can be provisioned by making a request using your partner token along with local_user, siteurl, and plan parameters. 10 | 11 | ### Pending Activation 12 | 13 | We will create a "Pending Activation" if the WordPress site isn't connected to Jetpack or isn't responding at the moment of provisioning. A pending activation: 14 | 15 | * Will automatically be attached to the site when it connects to Jetpack (identified by the `siteurl` parameter used in the request). 16 | * Lasts for 14 days. If the Pending Activation hasn't been "claimed" within 14 days, then we will see it as invalid and will require a new provisioning attempt. 17 | 18 | ### Endpoint information (/provision) 19 | 20 | - __Method__: POST 21 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/provision` 22 | 23 | ### Request Parameters (/provision) 24 | 25 | - __local_user__: The username, ID or email on the local website (not the WordPress.com username) that should own the plan. The corresponding user _must_ already exist. 26 | - __siteurl__: The URL where the WordPress core files reside. 27 | - __plan__: A slug representing which plan or item to provision. 28 | - Plans: `personal`, `premium`, or `professional`. 29 | - Backups: `jetpack-backup-realtime` or `jetpack-backup-daily`. 30 | - Scan: `jetpack-scan` 31 | - Anti Spam: `jetpack-anti-spam` 32 | - __force_register__: (optional) A true/false value indicating whether to re-register a site even if we already have tokens for it. Useful for sites that have gotten into a bad state. 33 | - __force_connect__: (optional) A true/false value indicating whether to re-connect a user even if we already have tokens for them. Useful for sites that have gotten into a bad state. 34 | - __onboarding__: (optional) If true, put the user through our onboarding wizard for new sites. 35 | - __wpcom_user_id__: (optional) For certain keys, enables auto-connecting a WordPress.com user to the site non-interactively. 36 | - __ssh_user__: (optional) Set SSH user. 37 | - __ssh_pass__: (optional) Set SSH password. 38 | - __ssh_private_key__: (optional) Set SSH private key. 39 | - __ssh_host__: (optional) Set SSH host. Will be deduced from `siteurl` if missing. 40 | - __ssh_port__: (optional) Set SSH port. Will default to 22 is missing. 41 | - __ftp_user__: (optional) Set FTP user. 42 | - __ftp_pass__: (optional) Set FTP password. 43 | - __ftp_host__: (optional) Set FTP host. Will be deduced from `siteurl` if missing. 44 | - __ftp_port__: (optional) Set FTP port. Will default to 21 is missing. 45 | 46 | _Note: All the SSH parameters are optional but if you pass `ssh_user` you will need to either pass `ssh_pass` or `ssh_private_key`._ 47 | 48 | ### Response Parameters (/provision) 49 | 50 | Below, the responses are grouped by whether the call to provision a plan was successful or not. 51 | 52 | #### Successful response 53 | 54 | - __success__: (bool) Was the operation successful?. 55 | - __auth_required__: (bool) Does the user need to authorize the connection on WordPress.com to finish provisioning? 56 | - __next_url__: (string) When `auth_required` is true, the URL to redirect the user to in order to finish authorization. 57 | 58 | If SSH parameters have been passed, these extra fields will be present in the response: 59 | 60 | - __ssh_set__: (bool) Weather the SSH credentials have been saved or not. 61 | - __ssh_error__: (string) Empty if save was successful, otherwise contains the error message. 62 | 63 | #### Errored response 64 | 65 | - __error_code__: (string) Error code, if any. 66 | - __error_message__: (string) Error message, if any. 67 | 68 | ### Endpoint Errors (/provision) 69 | 70 | The following is non-exhaustive list of errors that could be returned. 71 | 72 | | HTTP Code | Error Identifier | Error Message | 73 | | --------- | ------------------------- | ------------------------------------------------------------------------- | 74 | | 400 | invalid_siteurl | The required "siteurl" argument is missing. | 75 | | 400 | invalid_local_user | The required "local_user" argument is missing. | 76 | | 400 | plan_downgrade_disallowed | Can not automatically downgrade plans. Contact support. | 77 | | 400 | invalid_plan | %s is not a valid plan | 78 | | 403 | invalid_scope | This token is not authorized to provision partner sites | 79 | | 400 | method_not_found | remoteRegister method not found on remote site. | 80 | | 400 | method_not_found | remoteProvision method not found on remote site. Try calling again with --force_register=true. | 81 | 82 | For more explanation about the `method_not_found` errors, including solutions, please see [this documentation](method-not-found.md). 83 | 84 | ### Examples (/provision) 85 | 86 | Here's an example using cURL in shell. 87 | 88 | ```shell 89 | curl --request POST \ 90 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/provision \ 91 | --header "authorization: Bearer $ACCESS_TOKEN" \ 92 | --header 'cache-control: no-cache' \ 93 | --form plan=plan_here \ 94 | --form siteurl=siteurl_here \ 95 | --form local_user=local_user_here 96 | ``` 97 | 98 | Here's an example using the request module in NodeJS. 99 | 100 | ```js 101 | var request = require( 'request' ); 102 | var accessToken = 'access_token_here'; 103 | var plan = 'plan_here'; 104 | var siteurl = 'http://example.com'; 105 | var local_user = 'username_id_or_email_here'; 106 | 107 | var options = { 108 | method: 'POST', 109 | url: 'https://public-api.wordpress.com/rest/v1.3/jpphp/provision', 110 | headers: { 111 | 'cache-control': 'no-cache', 112 | authorization: 'Bearer ' + accessToken, 113 | }, 114 | formData: { 115 | plan: plan, 116 | siteurl: siteurl, 117 | local_user: local_user 118 | } 119 | }; 120 | 121 | request( options, function ( error, response, body ) { 122 | if ( error ) { 123 | throw new Error( error ); 124 | } 125 | 126 | console.log( body ); 127 | } ); 128 | ``` 129 | 130 | ### Considerations for domain names that do not resolve 131 | 132 | During the typical provisioning process, several calls are made between WordPress.com and the site that will receive a plan. For calls from WordPress.com to the site to succeed, we must be able to resolve the host of the URL provided to this endpoint. 133 | 134 | That typical provisioning process presents an issue in the case of provisioning a plan to a site with a new domain name. As of early August 2018, we are able to gracefully degrade in this case. 135 | 136 | When WordPress.com cannot communicate to the remote site due to not being able to resolve the host, cURL error 6, WordPress.com will flag the URL for future provisioning of a plan. After doing this, the API will return a response that looks like this: 137 | 138 | ``` 139 | { 140 | "success": true, 141 | "next_url": "", 142 | "auth_required": true 143 | } 144 | ``` 145 | 146 | This response is the same as the standard `/provision` response, with the exception of `next_url` being blank. Since WordPress.com is not able to communicate to the remote site, the API is not able to set secrets that are needed in the `next_url` that allows users to finish the authorization process. Authorization is still required by the user to receive the plan, which the user can do by visiting `/wp-admin` of their WordPress site and clicking the "Set Up Jetpack" button. 147 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/setting-backups-ftp-credentials.md: -------------------------------------------------------------------------------- 1 | # Setting Jetpack Backups FTP credentials 2 | 3 | There are two ways to set Jetpack Backups FTP credentials. One way of doing this is during [plan provisioning](jetpack/plan-provisioning.md). The second one is by calling the `/jpphp/{blog_id}/ftp-credentials` endpoint directly. This document explains the latter. 4 | 5 | ## Getting an access token 6 | 7 | To query this endpoint, you'll first need to retrieve an access token. Information about that can be found on the [Authentication API document]( jetpack/../authentication.md#getting-a-jetpack-partner-access-token ). 8 | 9 | ## Endpoint Information 10 | - __Method__: POST 11 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/{$blog_id}/ftp-credentials` 12 | 13 | `$blog_id` is the is the WordPress.com blog id. 14 | 15 | ### Request Parameters 16 | 17 | - __ftp_user__: Set FTP user. 18 | - __ftp_pass__: (optional) Set FTP password. 19 | - __ftp_host__: Set FTP host. 20 | - __ftp_port__: (optional) Set FTP port. Will default to 21 is missing. 21 | 22 | #### Successful response 23 | 24 | - __success__: (bool) Was the operation successful? 25 | 26 | #### Errored response 27 | 28 | - __error_code__: (string) Error code, if any. 29 | - __error_message__: (string) Error message, if any. 30 | 31 | ### Example 32 | 33 | ```shell 34 | curl --request POST \ 35 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/$BLOG_ID/ftp-credentials \ 36 | --header 'Accept: */*' \ 37 | --header 'Authorization: Bearer $ACCESS_TOKEN' \ 38 | --header 'Cache-Control: no-cache' \ 39 | --header 'Host: public-api.wordpress.com' \ 40 | --form ftp_host=$FTP_HOST \ 41 | --form ftp_user=$FTP_USER \ 42 | --form ftp_pass=$FTP_PASS 43 | ``` 44 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/setting-backups-ssh-credentials.md: -------------------------------------------------------------------------------- 1 | # Setting Jetpack Backups SSH credentials 2 | 3 | There are two ways to set Jetpack Backups SSH credentials. One way of doing this is during [plan provisioning](/jetpack/jetpack-start-endpoints/plan-provisioning.md). The second one is by calling the `/jpphp/{blog_id}/ssh-credentials` endpoint directly. This document explains the latter. 4 | 5 | ## Getting an access token 6 | 7 | To query this endpoint, you'll first need to retrieve an access token. Information about that can be found on the [Authentication API document]( jetpack/../authentication.md#getting-a-jetpack-partner-access-token ). 8 | 9 | ## Endpoint Information 10 | - __Method__: POST 11 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/{$blog_id}/ssh-credentials` 12 | 13 | `$blog_id` is the is the WordPress.com blog id. 14 | 15 | ### Request Parameters 16 | 17 | - __ssh_user__: Set SSH user. 18 | - __ssh_pass__: (optional*) Set SSH password. 19 | - __ssh_private_key__: (optional*) Set SSH private key. 20 | - __ssh_host__: Set SSH host. 21 | - __ssh_port__: (optional) Set SSH port. Will default to 22 is missing. 22 | 23 | _\*Note: You need to pass at least `ssh_pass` or `ssh_private_key`; both cannot be empty._ 24 | 25 | #### Successful response 26 | 27 | - __success__: (bool) Was the operation successful? 28 | 29 | #### Errored response 30 | 31 | - __error_code__: (string) Error code, if any. 32 | - __error_message__: (string) Error message, if any. 33 | 34 | ### Example 35 | 36 | ```shell 37 | curl --request POST \ 38 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/$BLOG_ID/ssh-credentials \ 39 | --header 'Accept: */*' \ 40 | --header 'Authorization: Bearer $ACCESS_TOKEN' \ 41 | --header 'Cache-Control: no-cache' \ 42 | --header 'Host: public-api.wordpress.com' \ 43 | --form ssh_host=$SSH_HOST \ 44 | --form ssh_user=$SSH_USER \ 45 | --form ssh_pass=$SSH_PASS 46 | ``` 47 | -------------------------------------------------------------------------------- /jetpack/jetpack-start-endpoints/upgrade-paths.md: -------------------------------------------------------------------------------- 1 | # Upgrade Paths 2 | 3 | Not all Jetpack product offerings should be provisioned concurrently. Some products contain the functionality of others so it doesn't make sense to provision them concurrently. The logic to determine which products can be provisioned for a particular site is quite complex and should not be implemented by partners. This is exactly what the upgrade paths endpoint is about. In short, given a blog ID or a URL, it will return what products can be provisioned. 4 | 5 | The only time when we allow products with overlapping functionality to be provisioned is when the product to be provisioned is a superset of a product already in place. For example, Jetpack Professional includes Realtime Backups as part of its functionality. Consider these two scenarios: 6 | 7 | 1. A site already has Realtime Backups provisioned. A hosting partner wants to provision Jetpack Professional. Even though Jetpack Professional already includes Realtime Backups, this action *will* be allowed as the site would be gaining extra functionality. 8 | 2. A site already has Jetpack Professional provisioned. A hosting partner wants to provision Realtime Backups. This *will not* be allowed because the site would not gain anything from provisioning Realtime Backups as that same functionality is already included in the existing Jetpack Professional plan. 9 | 10 | ## Getting an access token 11 | 12 | To query this status endpoint, you'll first need to retrieve an access token. Information about that can be found on the [Authentication API document](../jetpack-start-endpoints/authentication.md#getting-a-jetpack-partner-access-token ). 13 | 14 | ### Endpoint information (/upgrade-paths) 15 | 16 | - __Method__: GET 17 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/{$siteOrBlogId}/upgrade-paths` 18 | 19 | `$siteOrBlogId` can either be: 20 | 21 | - The WordPress.com blog ID. 22 | - The site's domain and path where `/` in the path is replaced with `::`. For example: 23 | 24 | | Site URL | $site Identifier | 25 | | --------------------- | ------------------- | 26 | | `example.com` | `example.com` | 27 | | `example.com/demo` | `example.com::demo` | 28 | | `example.com/demo/wp` | `example.com::demo::wp` | 29 | 30 | ### Response Parameters (/upgrade-paths) 31 | 32 | Below, the responses are grouped by whether the call was successful or not. 33 | 34 | #### Successful response 35 | 36 | The response will include as top level keys the name of the product family that the available upgrade paths belong to. At the time of this writing, the available product families are `jetpack-plans` and `jetpack-backup`. Each of those keys will contain an array of possible upgrades. For example, a site with a free Jetpack plan would return these upgrade paths: 37 | 38 | ``` 39 | { 40 | "jetpack-backup": [ 41 | "jetpack-backup-daily", 42 | "jetpack-backup-realtime" 43 | ], 44 | "jetpack-plans": [ 45 | "personal", 46 | "premium", 47 | "professional" 48 | ], 49 | "jetpack-scan": [ 50 | "jetpack-scan" 51 | ], 52 | "jetpack-anti-spam": [ 53 | "jetpack-anti-spam" 54 | ] 55 | } 56 | ``` 57 | 58 | The above means that for this particular site, both daily and realtime backup products can be provisioned, and personal, premium, and professional Jetpack plans can be provisioned as well. 59 | 60 | It is important to understand that the above response does not mean that a host can provision *all* of those plans but just *one*. The reason is that by virtue of provisioning any of those plans, the available upgrade paths will change. 61 | 62 | #### Errored response 63 | 64 | - __error__: (string) Error code, if any. 65 | - __message__: (string) Error message, if any. 66 | 67 | ### Examples (/upgrade-paths) 68 | 69 | Here's an example using cURL in shell. 70 | 71 | ```shell 72 | curl --request POST \ 73 | --url https://public-api.wordpress.com/rest/v1.3/jpphp/$BLOG_ID/upgrade-paths \ 74 | --header "authorization: Bearer $ACCESS_TOKEN" \ 75 | --header 'cache-control: no-cache' \ 76 | --form plan=plan_here \ 77 | --form siteurl=siteurl_here \ 78 | --form local_user=local_user_here 79 | ``` 80 | -------------------------------------------------------------------------------- /jetpack/managing-modules.md: -------------------------------------------------------------------------------- 1 | # Customizing Jetpack's Modules 2 | 3 | Occasionally, hosts have asked how they could customize Jetpack's modules. The documentation below will provide use cases and instructions on how to manage modules. 4 | 5 | If you have any questions or issues, our contact information can be found on the [README.md document](../README.md). 6 | 7 | ### How to get a list of modules 8 | 9 | Before we can disable or force a module on or off, we need to know the slug of the module we want to modify. To get the slugs, we have a couple of options:modules 10 | 11 | 1) You can run `wp jetpack module list` to get list of module slugs as well as the status for each module. 12 | 2) You can view the PHP files directly in the `modules` directory in Jetpack. Each PHP file that is in the top-level `modules` direcory is loaded as a module. The module slug is the file name minus the extension. 13 | 14 | ### Disabling modules 15 | 16 | In cases where Jetpack has a competing feature with a host, it may be preferable to disable the module in Jetpack. This is easily done via a filter in Jetpack, however, we would caution hosts to consider user experience when making this decision. If a user expects a commonly used module to be available, and it's not, that could cause confusion and a support request for the host and/or Jetpack support. 17 | 18 | Now that we've got that warning out of the way, let's get to it! 19 | 20 | The filter that we'll use to disable a module is `jetpack_get_available_modules`. You can find documentation as well as an example for that filter here:PHP 21 | 22 | [https://developer.jetpack.com/hooks/jetpack_get_available_modules](https://developer.jetpack.com/hooks/jetpack_get_available_modules/) 23 | 24 | Here are a couple more alternative examples: 25 | 26 | #### Disabling the Photon module 27 | 28 | ```php 29 | add_filter( 'jetpack_get_available_modules', 'jetpack_docs_filter_module_example' ); 30 | function jetpack_docs_filter_module_example( $modules ) { 31 | if( isset( $modules['photon'] ) ) { 32 | unset( $modules['photon'] ); 33 | } 34 | 35 | return $modules; 36 | } 37 | ``` 38 | 39 | #### Disabling the Lazy Images module 40 | 41 | ```php 42 | add_filter( 'jetpack_get_available_modules', 'jetpack_docs_filter_module_example' ); 43 | function jetpack_docs_filter_module_example( $modules ) { 44 | return array_diff_key( $modules, array( 'photon' => 'Does not matter' ) ); 45 | } 46 | ``` 47 | 48 | Note: As of Jetpack 5.8.0, there is a regression in filtering out the Photon module. While the module can be filtered out with the code above, the Jetpack admin UI shows an `undefined` string instead of hiding the setting. This behavior also applies to the Lazy Images module which was introduced in 5.8.0. This issue has been fixed in Automattic/jetpack#8780 which should go out in Jetpack 5.9.0. 49 | 50 | ### Forcing modules to be active 51 | 52 | In some cases, a host may decide that forcing a module to be active may be preferable. For example, to minimize bandwidth on the host's server, a host could force the Photon module to be active. In these cases, it is possible to force a module on with the `jetpack_active_modules` filter. 53 | 54 | Documentation for that filter can be found at the following URL:preferable 55 | 56 | [https://developer.jetpack.com/hooks/jetpack_active_modules](https://developer.jetpack.com/hooks/jetpack_active_modules/) 57 | 58 | Here's an example of how to force the Photon module to be activated:preferable 59 | 60 | ```php 61 | add_filter( 'option_jetpack_active_modules', 'jetpack_docs_filter_active_modules' ); 62 | function jetpack_docs_filter_active_modules( $modules ) { 63 | return array_values( array_merge( $modules, array( 'photon' ) ) ); 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /jetpack/method-not-found.md: -------------------------------------------------------------------------------- 1 | # Method Not Found Errors 2 | 3 | When calling the [Jetpack provisioning API directly](jetpack/../jetpack-start-endpoints/plan-provisioning.md), one side-effect is an increase in communication between WordPress.com/Jetpack servers and the remote site that a hosting partner maintains. 4 | 5 | The primary reason that this communication is necessary is that we require a site to be connected to WordPress.com/Jetpack before a plan can be provisioned to that site. The extra communication handles an initial registration of the site as well as setting secrets and gathering information necessary to create an authorization URL so that a user may authorize a connection between WordPress.com/Jetpack and their site. 6 | 7 | One side-effect of this extra communication is that it increases the possibilities that something can go wrong. The most common and confusing issues that occur with this extra communication are errors with code `method_not_found`. Below, I'll go over the cases where a `method_not_found` error may occur as well as options for fixing the issue. 8 | 9 | ## remoteRegister Not Found 10 | 11 | An example response of what you'll get back from this specific `method_not_found` error is: 12 | 13 | ``` 14 | { 15 | "error": "method_not_found", 16 | "message": "remoteRegister method not found on remote site." 17 | } 18 | ``` 19 | 20 | Here are the known cases for this error as well as suggested solutions. 21 | 22 | ### Jetpack is not installed and active 23 | 24 | If Jetpack is not installed and active then the `jetpack.remoteRegister` method is never add to the list of available XML-RPC methods. The simplest fix here is to simply install and activate Jetpack. You can do that via WP-CLI: 25 | 26 | ``` 27 | wp plugin install jetpack 28 | wp plugin activate jetpack 29 | ``` 30 | 31 | Note: The `bin/partner-provision.sh` script that is packaged in the Jetpack plugin will attempt to silently active the Jetpack plugin before calling to the API. So, installing the Jetpack plugin and then calling the `bin/partner-provision.sh` script is an alternative to fix this error as well. 32 | 33 | ### Site uses https but https not specified in siteurl argument 34 | 35 | For some hosting partners, this error has occurred when passing only the domain, or the host portion of the url. This typically work fine since we run `esc_url_raw()` on the WordPress.com/Jetpack side to get a proper URL to call out to. But, in the case of one hosting partner, where the site automatically redirect `http` to `https`, the `method_not_found` error was returned. 36 | 37 | One fix in this case is to pass the full URL with the correct protocol in the `siteurl` argument. We will consider options for improving this on the WordPress.com/Jetpack side in the future. 38 | 39 | ## remoteProvision Not Found 40 | 41 | 42 | An example response of what you'll get back for this specific `method_not_found` error is: 43 | 44 | ``` 45 | { 46 | "error": "method_not_found", 47 | "message": "remoteProvision method not found on remote site. Try calling again with --force_register=true." 48 | } 49 | ``` 50 | 51 | This error usually occurs because there is a mismatch in tokens between the WordPress.com/Jetpack side and the site that is hosted with the hosting partner. Specifically, there is a blog token on the WordPress.com/Jetpack side but there is not a matching token on the hosted site. Some reasons that this error might have occurred are: 52 | 53 | 1. The site was disconnected but the call to WordPress.com/Jetpack failed 54 | 1. The `jetpack_options` and/or `jetpack_private_options` options were deleted 55 | 56 | The recommended solution for this issue is to pass `force_register=1` in direct calls to the API or `--force_register=true` when running the `bin/partner-provision.sh` script. 57 | 58 | In the past, some hosting partners have asked if they could always set `force_register` to true. In our experience, this does work. But, it does slow down the request by adding at least one network request. 59 | -------------------------------------------------------------------------------- /jetpack/migrate-v1-2-to-v1-3.md: -------------------------------------------------------------------------------- 1 | # Migrating from version 1.2 to version 1.3 2 | 3 | Migrating your existing integration from version 1.2 of the Jetpack Start API to version 1.3 will allow you to take advantage of improved speed, improved UX, and features that are only available in version 1.3. 4 | 5 | A number of things have changed between versions 1.2 and 1.3. This document will attempt to cover the high-level changes between versions 1.2 and 1.3, but please be aware that there may be some nuances that are covered in detail outside of this migration document. Please consult the rest of the [Jetpack](./) documentation to get more in-depth description of the functionality in version 1.3. 6 | 7 | ## Understanding the flows 8 | 9 | Before we discuss how to migrate from version 1.2 to 1.3, let's take a moment to understand the provisioning process of each version of the API. 10 | 11 | ### Version 1.2 integration flow 12 | 13 | Below is a high-level diagram of the version 1.2 integration flow. 14 | 15 | ![Jetpack version 1.2 flow diagram](/assets/jps-v1-2-overview.png) 16 | 17 | There are a few key things which we'll point out from this diagram: 18 | 19 | - A WordPress.com oAuth token from the user is required to call the endpoint 20 | - This requires sending users through the WordPress oAuth flow 21 | - This also requires that users have, or create, a WordPress.com account 22 | - In some cases, the oAuth token may not be accepted if the site is already connected to another WordPress.com user 23 | - The host is required to set many values via WP-CLI or some other method to activate and setup Jetpack, Akismet, and VaultPress 24 | 25 | ### Version 1.3 integration flow 26 | 27 | Below is a high-level diagram of the version 1.3 integration flow. 28 | 29 | ![Jetpack version 1.3 flow diagram](/assets/jps-v1-3-overview.png) 30 | 31 | At first glance, you may notice that the diagram for version 1.3 is more complex. That's because version 1.3 of the API is definitely more complex beneath the hood. But, I'll point out that much of that complexity is hidden "under the hood". 32 | 33 | From the hosting partner's perspective, we believe the integration is actually much simpler for the following reasons: 34 | 35 | - oAuth is not required before calling the API 36 | - If a user does not already exist on WordPress.com then the API will attempt to create the user and connect the site automatically (if the partner is whitelisted) 37 | - The host does not have to run WP-CLI commands to install Akismet and VaultPress 38 | - The host does not have to run WP-CLI commands to set key for Jetpack, Akismet, and VaultPress 39 | 40 | We created version 1.3 with the goal of making the integration process simpler for hosting partners. Now, hosting partners should only have to: 41 | 42 | 1. Make an API request to the `/v1.3/jpphp/provision` endpoint with the following information: 43 | - Site URL 44 | - User ID, email, or username 45 | - The plan to provision to the site 46 | 2. Choose whether to redirect the user based on the response from the API 47 | - If the API returns a response that includes `auth_required: true`, then the user will need to connect their Jetpack site 48 | - In this case, a `next_url` value should be returned, if possible, which will allow the user to connect their site to WordPress.com 49 | - Alternatively, the user can click the "Set Up Jetpack" button within WordPress.com to go through the connection process and then receive their plan 50 | 51 | ## Doing the migration 52 | 53 | With the above in mind, let's go over the changes for migration. 54 | 55 | ### Base URL 56 | 57 | The base URL has changed from the `https://public-api.wordpress.com/rest/v1.2` to `https://public-api.wordpress.com/rest/v1.3`. 58 | 59 | ### Endpoint 60 | 61 | The endpoint paths have changed from `/product-keys` in version 1.2 to `/provision` in version 1.3. 62 | 63 | ### oAuth flow no longer needed 64 | 65 | Version 1.3 no longer user oAuth tokens from user, so you can completely remove the WordPress.com oAuth flow from your provisioning process if you'd like. 66 | 67 | ### Jetpack is required to be installed and active 68 | 69 | In version 1.3 of the Jetpack Start API, Jetpack is required to be installed and active when making a call to the `/v1.3/jpphp/provision` endpoint so that the WordPress.com API can communicate back to the Jetpack site. This was not the case for version 1.2 of the API. 70 | 71 | ### CLI calls minimized 72 | 73 | Version 1.3 of the Jetpack Start API now remotely installs and configures Akismet and VaultPress via an API call from WordPress.com to the Jetpack site. 74 | 75 | Because of this, you can remove all of the WP-CLI calls that you previously ran to: 76 | 77 | - Install Akismet 78 | - Install VaultPress 79 | - Set keys for Akismet, VaultPress, and Akismet 80 | 81 | ### Handling successful provision requests 82 | 83 | There are three cases of a successful API response to consider how to handle for the integration. 84 | 85 | #### Authorization is not required 86 | 87 | In this case, you can expect a response like this: 88 | 89 | ```json 90 | { 91 | "success": true, 92 | "next_url": "https://example.com/wp-login.php?action=jetpack-sso&redirect_to=https%3A%2F%2Fexample.com%2Fwp-admin", 93 | "auth_required": false 94 | } 95 | ``` 96 | 97 | In this case the plan has already been provisioned to the site and no further action is required. The `next_url` value, in a default configuration, should be a Jetpack Secure Sign On link that will automatically log the user in to the `wp-admin` of their site. That being said, it is not required to redirect the user anywhere. 98 | 99 | #### Authorization is required and next URL is not empty 100 | 101 | In this case, you can expect a response like this: 102 | 103 | ```json 104 | { 105 | "success": true, 106 | "next_url": "https://jetpack.wordpress.com/jetpack.authorize/1/...", 107 | "auth_required": true 108 | } 109 | ``` 110 | 111 | In this case, the plan has not yet been added to the Jetpack site yet, but a pending activation has been registered for the site on WordPress.com. For the site to receive the plan that you have attempted to provision to them, the site must connect to WordPress.com. 112 | 113 | The `next_url` value is a URL at which the user can connect their site to WordPress.com and then be provisioned the plan that was set in the pending activation. That being said, the `next_url` is provided for convenience. You can choose to redirect the user to this URL or display it somehow in your dashboard, but it is not a hard requirement that the user go to this `next_url` value. Instead, the user can also click the "Set Up Jetpack" button that appears in their `wp-admin`. 114 | 115 | Note: Hosting partners are not charged for pending activations where a plan is a plan was never provisioned. Hosts are only charged for active plans. Therefore, only after a user connects the WordPress.com site. 116 | 117 | Note: Pending activations are only valid for two weeks. Afterwards, another request will need to be made to the provisioning API to provision a plan for a given site. 118 | 119 | #### Authorization is required and next URL is empty 120 | 121 | In this case, you can expect a response like this: 122 | 123 | ```json 124 | { 125 | "success": true, 126 | "next_url": "", 127 | "auth_required": true 128 | } 129 | ``` 130 | 131 | This case is very similar to the one above directly above, the only difference being that the `next_url` value is empty. This is a very specific use case where hosting partners are provisioning plans to sites where the DNS has not yet propagated. In this case, we choose to register a pending activation for a given URL, but we are not able to populate the `next_url` since we're not able to communicate to the site. 132 | 133 | In this case, the hosting partner is not able to automatically redirect the user to the `next_url` value in order to have the user go throug the Jetpack connection process. Instead, the hosting partner must rely on the user clicking the "Set Up Jetpack" button in the `wp-admin` of their site. -------------------------------------------------------------------------------- /jetpack/monitor-downtime-notifications-webhook.md: -------------------------------------------------------------------------------- 1 | # Monitor Downtime Notifications Webhook 2 | 3 | This document outlines the system by which a Jetpack partner host may receive notifications of downtime for sites they are hosting, which are using Jetpack. This allows the host to independently examine the downtime event, and verify it from their end. 4 | 5 | In addition, there is allowance for the partner host to request we suppress user notifications in the case of scheduled or known downtime. 6 | 7 | ## Basic Architecture 8 | 9 | Jetpack Monitor uses a distributed set of nodes in different data centers to check the response being received from sites running Jetpack. After an initial failure from one node, multiple secondary nodes are used to verify the initial results before triggering a notification (via email) to the user. Requests are executed as HEAD requests, and only currently verify HTTP response codes (not actual page content). 10 | 11 | Immediately before sending the notification to users, Monitor may send a webhook-style request to the host of the site in question (host is determined per our records, based primarily on DNS information). 12 | 13 | Optionally, a host may respond to this initial notification to indicate that the site in question is known to be down (e.g. scheduled maintenance) and thus we may suppress notifying the user of their downtime at our discretion. 14 | 15 | ## Endpoint Specification 16 | 17 | ### Request Payload 18 | 19 | Jetpack Monitor will make an HTTP POST request to the URI you specify. The POST will contain a body which is the JSON-encoded details of the last check for a site. It will look approximately like this: 20 | 21 | ```json 22 | {"ts":1385139152,"url":"http:\/\/example.com","code":403,"host":"example","type":"http"} 23 | ``` 24 | 25 | 26 | Fields included are: 27 | 28 | * **ts:** Timestamp of the last check, as a UNIX style timestamp. 29 | * **url:** The URL that was checked (with forward slashes escaped) 30 | * **code:** The _highest_ HTTP response code we received during the last check. Note that since multiple nodes are used to verify a URL, it is possible for one node to receive e.g. a 200 response, while another gets a 500. In this case, we will return the 500. Can contain any HTTP status code, including 200 (indicating site is back online). If code is ‘0’, then there was a timeout on our verification check. Any non 2xx code is considered a failure. 31 | * **host:** A string/”slug” representing who we think the host of this site is. Normally based off either DNS or ASN records. 32 | * **type:** Indication of what kind of error was encountered. Currently only supports “http” 33 | 34 | ### Response 35 | 36 | #### Normal Response 37 | 38 | When we notify you of an unexpected/normal downtime event, your endpoint should just respond to our request with an HTTP 200 status, with the string `ok` in the body (no quotes, no period). 39 | 40 | #### Scheduled downtime/suppress notification 41 | 42 | In the case where the specific URL (or entire host) is known to be down, you may optionally respond with a timestamp (full UTC ISO 8601 format; 2017-11-05T13:15:30Z), indicating the expected time after which the site will be online again. An HTTP 200 is still expected in this case. Given this timestamp, we may optionally suppress further webhook notifications/requests to your endpoint until that time for this site/partner, to reduce redundant requests. We may also use this timestamp as an indication to suppress notification to the user. 43 | -------------------------------------------------------------------------------- /jetpack/plan-provisioning.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED: Please see docs on how to use the API directly. 2 | 3 | # Provisioning and Cancelling Jetpack Plans 4 | 5 | In this document, we’ll briefly go over how to provision and cancel Jetpack plans via the shell scripts that ship with Jetpack. If you have any questions or issues, our contact information can be found on the [README.md document](../README.md). 6 | 7 | ## What is Jetpack Start? 8 | 9 | Jetpack Start is a collection of scripts that you can run in order to provision and cancel Jetpack plans for your customers. These scripts are packaged with the Jetpack plugin, and are designed for lightweight integration and maximum compatibility across Jetpack versions. The scripts also take care of activating any plan-specific features or activating additional plugin dependencies such as Akismet. 10 | 11 | In general, you only need to know about two scripts: 12 | 13 | 1. `tools/partner-provision.sh` - when the user purchases a plan, or bundle of plans, you’ll run this script to provision a plan 14 | 2. `tools/partner-cancel.sh` - when the user cancels their plan, you’ll run this script to cancel the plan on WordPress.com, and you will no longer be billed for this site 15 | 16 | A Jetpack-Start-provisioned plan has no expiry or renewal date, which means you (and your customers) won’t have to worry about monthly or yearly renewals. 17 | 18 | ## How does Jetpack Start work? 19 | 20 | Jetpack Start supports provisioning a single plan or bundles of plans (for resellers). 21 | 22 | For hosts that are bundling our Jetpack plans with their managed WordPress products, we suggest going the single plan route. 23 | 24 | ### CLI Arguments Key 25 | 26 | Further in this document, you will find a few CLI commands with various arguments. Directly below, you will also find a key to explain what the most common arguments are. 27 | 28 | - `partner_id` : Provided to you when we provision your partner account. 29 | - `partner_secret` : Provided to you when we provision your partner account. 30 | - `user` : The ID, email address, or login of a valid user on the WordPress installation hosted by the partner. See: https://make.wordpress.org/cli/handbook/config/#global-parameters. 31 | - `plan` : The plan or product you wish to provision. These includes - but are not limited to - `free`, `personal`, `premium` and `professional`. The partner's account will need to have these types of plans allowed. 32 | - `url` : This optional URL value is used to select a specific subsite in a network. See: https://make.wordpress.org/cli/handbook/config/#global-parameters. 33 | - `onboarding` : This optional value can be set to `1` to enabled an onboarding wizard. 34 | - `partner_tracking_id` : This optional value allows us to attach specific actions to a specific site on the partner's side. This has proved useful in cases where users had multiple staging sites. 35 | - `wp-cli-path` : Allows setting the path of WP-CLI. 36 | - `ssh-host` : The SSH host for Jetpack Backups remote access. 37 | - `ssh-user` : The SSH user for Jetpack Backups remote access. 38 | - `ssh-pass` : The SSH password for Jetpack Backups remote access. 39 | - `ssh-private-key` : The local path to the SSH private key file for Jetpack Backups remote access. 40 | - `ssh-port` : The SSH port for Jetpack Backups remote access. 41 | - `ftp-host` : The FTP host for Jetpack Backups remote access. 42 | - `ftp-user` : The FTP user for Jetpack Backups remote access. 43 | - `ftp-pass` : The FTP password for Jetpack Backups remote access. 44 | - `ftp-port` : The FTP port for Jetpack Backups remote access. 45 | 46 | _Note: All the SSH parameters are optional but if you pass `ssh-user` you will need to either pass `ssh-pass` or `ssh-private-key`._ 47 | 48 | ### Provisioning a single plan for a given site 49 | 50 | We like to think that integrating with Jetpack Start is fairly easy. From beginning to end, the process looks like this: 51 | 52 | 1. Obtain a Jetpack Partner ID and token, which we will provide to you 53 | 2. Ensure Jetpack is installed on the WordPress site: 54 | - `wp plugin install jetpack` 55 | 3. Run the partner provision script with the Jetpack Partner ID and token that were provided to you 56 | - `sh partner-provision.sh --partner_id={partner_id} --partner_secret={partner_secret} --user={id_or_email} --plan={plan_slug} [--url=http://example.com]` 57 | - The script makes a call to our servers to register the site (if necessary) and provision the requested plan and any additional plugins such as VaultPress and Akismet 58 | 4. If the script is successful, it will exit with code 0, and a JSON string. If any next steps are required in the browser, the JSON will include a URL to send your user to. E.g 59 | - `{ success: true, next_url: "http://wordpress.com/start/plans?foo=bar", "auth_required": true }` 60 | - When `auth_required` is `true`, the user must finish authorizing the connection between WordPress.com and their site to finish provisioning. In this case, `next_url` will be a URL that allows the user to finish that authorization step. 61 | - When `auth_required` is `false` provisioning is complete and redirecting the user to `next_url` is optional. In this case, `next_url` will be a URL back to the user's `wp-admin`. 62 | 5. If the script is unsuccessful, it will exit with code 1, and some text describing the error, like this: 63 | `{ success: false, error_code: "site_inaccessible", error_message: "We couldn't contact your site" }` 64 | 6. Any additional products and settings will be installed on the site within a couple of minutes. 65 | 66 | ### Cancelling a single plan 67 | 68 | The process for cancelling a single plan is just as simple as provisioning a plan! 69 | 70 | 1. Obtain a Jetpack Partner ID and token, which we will provide to you 71 | 2. Ensure Jetpack is installed on site 72 | - `wp plugin install jetpack` 73 | 3. Run the following script with the Jetpack Partner ID and token that were provided to you 74 | - `sh ./wp-content/plugins/jetpack/bin/partner-cancel.sh --partner_id={partner_id} --partner_secret={partner_secret} [--url=http://example.com]` 75 | 4. If the script is successful, it will exit with code 0, and a JSON string. 76 | - `{ success: true }` 77 | 5. If the script is unsuccessful, it will exit with code 1, and some text describing the error, like this: 78 | `{ success: false, error_code: "incorrect_partner_key'", error_message: "Subscriptions can only be cancelled by the oAuth client that created them" }` 79 | 80 | Note: If `{ success: false }` is returned, that means that the site no longer had a plan registered on WordPress.com. In this case, retries are not necessary. 81 | 82 | ### Provisioning a bundle of plans 83 | 84 | As a Jetpack Partner, you can sell your customers “bundles” of Jetpack plans. This is useful if your customers are web hosts or agencies who want to distribute Jetpack to their own customers, or generally just want to buy plans in bulk. 85 | 86 | The way this works is that you have access to an API to create new “partner keys”. A key is generated for each “bundle”, and distributed to your customers. 87 | 88 | Those customers (e.g. hosts or web professionals) then use those keys to provision plans to their WordPress sites. 89 | 90 | These generated partner keys can have limits – certain numbers of personal, premium or professional plans. You (the reseller) are responsible for paying Automattic a wholesale rate for any plans generated using these keys, and in turn you can bill your customers at a markup. 91 | 92 | _**Note**: Only [Jetpack legacy bundles](https://jetpack.com/support/jetpack-plan-equivalency-chart/) are specifically mentioned in the documentation but more recent products/plans like `complete` or `jetpack-videopress` can be issued as well, if the partner has access to them._ 93 | 94 | When your customers buy a bundle of Jetpack plans, you create a new key by generating a “client_credentials”-granted oauth token. With that token, you can make a request to the jpphp/partner-keys/new API, like this (assumes you have curl and the excellent json-parsing command jq installed): 95 | 96 | ```bash 97 | # generate token 98 | PARTNER_ID= your partner id 99 | PARTNER_SECRET= your partner secret 100 | API_HOST=public-api.wordpress.com 101 | ACCESS_TOKEN_JSON=$(curl https://$API_HOST/oauth2/token \ 102 | --silent \ 103 | -d "grant_type=client_credentials&client_id=$PARTNER_ID&client_secret=$PARTNER_SECRET&scope=jetpack-partner") 104 | 105 | ACCESS_TOKEN=$(echo $ACCESS_TOKEN_JSON | jq -r ".access_token") 106 | 107 | # generate partner key 108 | PARTNER_KEY_INFO=$(curl https://$API_HOST/rest/v1.3/jpphp/partner-keys/new \ 109 | --silent \ 110 | --header "authorization: Bearer $ACCESS_TOKEN" \ 111 | -d "name=My%sKey&allowed_premium_plans=100") 112 | ``` 113 | 114 | After running the script above, PARTNER_KEY_INFO should contain a value like this: 115 | 116 | ```json 117 | {"id": 10, "name":"My%sKey", "allowed_personal_plans":"0", "allowed_premium_plans":"100", "allowed_professional_plans":"0", "notes":null,"client_id":"12345","client_secret":"ab34fd21,,,"} 118 | ``` 119 | 120 | The client_id and client_secret values are the ones you should or your customers should use to license Jetpack plans with the partner-provision.sh script. 121 | -------------------------------------------------------------------------------- /jetpack/redirect-after-authorization.md: -------------------------------------------------------------------------------- 1 | # Controlling the Redirect After Users Authorize on WordPress.com 2 | 3 | Provisioning a plan for a given site is usually a two-step process: 4 | 5 | 1) The partner host must call our API, by running a script or calling the API directly 6 | 2) The user must authorize a connection between WordPress.com and their site (**This step is not necessary when the site is already connected**) 7 | 8 | After the user authorizes the connection, the default behavior is for the user to be redirected back to the `wp-admin` of their site via a Jetpack SSO login URL, which may not be ideal for all hosting partners. To address that potential issue, hosting partners are able to control where users are redirected after they finish authorizing on WordPress.com. 9 | 10 | ## Controlling the redirect 11 | 12 | After provisioning a site via the Jetpack partners API, hosting partners will receive a response that contains `next_url` and `auth_required` values. When `auth_required` is `true`, the `next_url` value is either a URL that allows the user to authorize the connection between WordPress.com and the site. When `auth_required` is `false`, the `next_url` value is a link back to the user's site. 13 | 14 | To change the default redirect behavior, hosts will want to append `&partner_redirect=http%3A%2F%2Fexample.com`, where `http%3A%2F%2Fexample.com` is a URL encoded URL, to the end of `next_url` when `auth_required` is `true`. 15 | 16 | The `partner_redirect` value will be validated on WordPress.com against a whitelist, and assuming the redirect is valid, the user will be redirected to `partner_redirect` after authorization. 17 | 18 | **Note:** Because redirects are validated against a whitelist, please be sure to get in touch with us about whitelisting your redirect if you'd like to change the default redirect behavior after authorization. 19 | 20 | ## Example 21 | 22 | Here is an example in NodeJS, using the request module, which will print the `next_url` value after adding the `&partner_redirect=` value when `auth_required` is `true`. 23 | 24 | ```js 25 | var request = require( 'request' ); 26 | var accessToken = 'access_token_here'; 27 | var plan = 'plan_here'; 28 | var siteurl = 'http://example.com'; 29 | var local_user = 'username_id_or_email_here'; 30 | 31 | var options = { 32 | method: 'POST', 33 | url: 'https://public-api.wordpress.com/rest/v1.3/jpphp/provision', 34 | headers: { 35 | 'cache-control': 'no-cache', 36 | authorization: 'Bearer ' + accessToken, 37 | }, 38 | formData: { 39 | plan: plan, 40 | siteurl: siteurl, 41 | local_user: local_user 42 | } 43 | }; 44 | 45 | request( options, function ( error, response, body ) { 46 | if ( error ) { 47 | throw new Error( error ); 48 | } 49 | 50 | body = JSON.parse( body ); 51 | console.log( 52 | body.auth_required 53 | ? body.next_url + '&partner_redirect=' + encodeURIComponent( 'http://example.com' ) 54 | : body.next_url 55 | ); 56 | } ); 57 | ``` 58 | -------------------------------------------------------------------------------- /jetpack/reporting-endpoints/README.md: -------------------------------------------------------------------------------- 1 | # Partners REST API Endpoint Documentation 2 | 3 | We are developing a partner portal that provides aggregate and site-level reporting about the plans that a hosting partner has provisioned. But, this partner portal is not currently available for partners and we do not have a date for it at the moment. That being said, while the partner portal is not usable itself, the endpoints are accessible for hosting partners by querying the REST API endpoints that power the partner portal. 4 | 5 | This document details how to get setup to query these endpoints. 6 | 7 | ## Endpoints 8 | 9 | - [Activations List](activations-list.md) 10 | - [Activations Summary](activations-summary.md) 11 | - [Past Invoices](invoices-past.md) 12 | - [Upcoming Invoices](invoices-upcoming.md) 13 | 14 | ## Authentication 15 | 16 | To retrieve reports via the WordPress.com API, you'll need to authenticate with a bearer token that was authorized by the WordPress.com user attached to your partner keys. The way that authentication is handled for these reporting endpoints is different than how authorization works for provisioning and cancelling plans. 17 | 18 | Why the different authentication you ask? The reasoning for this is that the `/jpphp` endpoints for provisioning and cancelling plans are meant to be used without explicit user authentication, specifically without requiring that end users authenticate via OAuth before provisioning a plan to the site. Whereas, for these reporting endpoints, we want to be sure that the WordPress.com user that is responsible for the hosting partner has authenticated the access. 19 | 20 | In order to get a bearer token, there are two methods: 21 | 22 | ### Via the Jetpack Partner Portal 23 | 24 | In order to get your bearer token via the Jetpack Partner Portal: 25 | 26 | - Navigate to the Jetpack Partner's portal 27 | - Open your browser's developer console and paste in the following to get your Bearer token: 28 | 29 | ```javascript 30 | localStorage.getItem( 'wp_oauth' ); 31 | ``` 32 | 33 | This is the simpler option, but the Jetpack Partner Portal is currently for internal use only. Jetpack partners will need to use the OAuth method below for the time being. 34 | 35 | ### Via OAuth 36 | 37 | Retrieving a bearer token via OAuth requires a few steps, but with the steps below, it shouldn't take very long. 38 | 39 | First, you'll need to be able to login to WordPress.com with the WordPress.com user that is tied to your Jetpack hosting partner. For hosting partners, this user would have been supplied to Automattic by your company when we created your keys to connect to the provisioning API. If you are not sure what the user is, feel free to reach out in Slack or via email and we will assist you with that. 40 | 41 | Second, to get authenticated with OAuth, you'll need to create an applicaton on WordPress.com. You can do that by going to [https://developer.wordpress.com/apps/new/](https://developer.wordpress.com/apps/new/). You may set the values to anything that you'd like. But, we'd recommend that you use `http://127.0.0.1:3210` for the redirect and website URL if you'd like to use the script we have below. 42 | 43 | After you create your application, make note of the client ID and client secret. We'll need those to actually authenticate. Below, we'll provide a script along with steps to authenticate, but if you'd rather not use the script, you can find documentation for retrieving a bearer token here: 44 | 45 | [https://developer.wordpress.com/docs/oauth2/](https://developer.wordpress.com/docs/oauth2/) 46 | 47 | #### Script for Retrieving a Bearer Token 48 | 49 | In order to retrieve a bearer token for the WordPress.com API without writing much code, we have provided the script below. Assuming that you've already logged in to the correct WordPress.com account, we expect that the following steps will take a few minutes. 50 | 51 | - On your desktop, create a directory 52 | - In this directory, create a PHP file named `index.php` 53 | - In that file place: 54 | 55 | ```php 56 | $client_id, 78 | 'redirect_uri' => 'http://127.0.0.1:3210', 79 | 'client_secret' => $client_secret, 80 | 'code' => $_GET['code'], 81 | 'grant_type' => 'authorization_code' 82 | ) ); 83 | 84 | curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1); 85 | 86 | $auth = curl_exec( $curl ); 87 | echo $auth; 88 | ``` 89 | 90 | - Be sure to change `$client_id` and `$client_secret` to the appropriate values for your WordPress.com application 91 | - Change to the directory that was created earlier and run `php -S '127.0.0.1:3210' -t .` in order to start up a test server 92 | - Navigate to `http://127.0.0.1:3210?do_redirect=1` 93 | - Click the blue "Approve" button 94 | - You should then be redirected back to `127.0.0.1:3210` with some JSON output 95 | - The value for the `secret` key is used for your bearer token 96 | -------------------------------------------------------------------------------- /jetpack/reporting-endpoints/activations-list.md: -------------------------------------------------------------------------------- 1 | # Get Details About Your Individual Activations 2 | 3 | This endpoint will list out individual activations in a paged method. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/jetpack-partners/PARTNER_ID/key/KEY_ID/activations` 9 | 10 | ### Request Parameters 11 | 12 | - __page__: Optional. Page number to return. 13 | - __per_page__: Optional. Sites per page. Defaults to 20. 14 | - __plans__: Optional. Array of plans to filter down to. 15 | - __activated_after__: Optional. Only return sites activated after this datetime. 16 | - __activated_before__: Optional. Only return sites activated before this datetime. 17 | 18 | ### Response Properties 19 | 20 | - __total__: Total number of results. 21 | - __activations__: Array of site objects. 22 | 23 | #### Site Object Properties 24 | 25 | - __id__: Site ID. 26 | - __jetpack_partner_key_id__: Your partner ID. 27 | - __wpcom_blog_id__: The ID of the WP.com shadow copy site. 28 | - __wpcom_user_id__: The owner's WP.com user ID. 29 | - __external_user_id__: ? 30 | - __product_id__: The ID of the Jetpack product that the site has. 31 | - __created_on__: Datetime of the site's creation. 32 | - __activated_on__: Datetime of the site's activation. 33 | - __cancelled_on__: Datetime of the site's cancellation. Probably `null`. 34 | - __disputed_on__: Probably `null`. 35 | - __site_registered__: Datetime. 36 | - __site_url__: The site's URL. 37 | - __site_name__: The site's name. 38 | - __site_icon__: The site's icon. Can be `null`. 39 | - __current_product_id__: Always same as `product_id` -------------------------------------------------------------------------------- /jetpack/reporting-endpoints/activations-summary.md: -------------------------------------------------------------------------------- 1 | # Get A Summary Of Your Activations 2 | 3 | This is the endpoint used to make the graph in the Jetpack Partner Portal. 4 | 5 | ### Endpoint Information 6 | 7 | - __Method__: GET 8 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/jetpack-partners/activations` 9 | 10 | ### Request Parameters 11 | 12 | - __key_id__: Your key ID, as pulled from the portal. 13 | - __scale__: `day`, `month`, or `year`. Defaults to `month`. 14 | 15 | ### Response Properties 16 | 17 | An array of the following objects: 18 | 19 | - __date__: The time period that the data is for. 20 | - __new__: The number of new activations in this time period. 21 | - __total__: The total number of activations as of this time period. -------------------------------------------------------------------------------- /jetpack/reporting-endpoints/invoices-past.md: -------------------------------------------------------------------------------- 1 | # Get Your Past Invoice Details 2 | 3 | ### Endpoint Information 4 | 5 | - __Method__: GET 6 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/jetpack-partners/PARTNER_ID/key/KEY_ID/stripe/invoices` 7 | 8 | ### Request Parameters 9 | 10 | None. -------------------------------------------------------------------------------- /jetpack/reporting-endpoints/invoices-upcoming.md: -------------------------------------------------------------------------------- 1 | # Get Your Upcoming Invoice Details 2 | 3 | ### Endpoint Information 4 | 5 | - __Method__: GET 6 | - __URL__: `https://public-api.wordpress.com/wpcom/v2/jetpack-partners/PARTNER_ID/key/KEY_ID/stripe/upcoming-invoice` 7 | 8 | ### Request Parameters 9 | 10 | None. -------------------------------------------------------------------------------- /jetpack/upgrade-redirection.md: -------------------------------------------------------------------------------- 1 | # Redirecting Upgrades Back to Hosting Partners 2 | 3 | In an effort to minimize confusion for users and improve relations with our hosting partners, we have added the ability to redirect users who click on upgade prompts within the Jetpack plugin back to the hosting partner's checkout flow, as opposed to WordPress.com. 4 | 5 | ## What it looks like 6 | 7 | For example, the typical upgrade path might look like this: 8 | 9 | - User purchases hosting package 10 | - User installs Jetpack 11 | - User clicks on the upgrade prompt that shows for the Jetpack Search feature 12 | - User is taken to WordPress.com where they can upgrade their plan in order to use Jetpack Search 13 | 14 | In some cases, this is a less than ideal flow. One example would be when the hosting partner is bundling a Jetpack plan as part of the user's hosting package. In that case, if the user were to upgrade on WordPress.com it would result in the user now double-paying for a Jetpack plan, which could reflect poorly on the partnership between Jetpack and the hosting partner. 15 | 16 | With the ability to redirect users to our hosting partners, the upgrade flow can look like this instead: 17 | 18 | - User purchases hosting package 19 | - User installs Jetpack 20 | - User clicks on upgrade prompt that shows for Jetpack Search feature 21 | - User is redirected to a page on the hosting partner's website where the user can upgrade their plan 22 | - After purchasing on the hosting partner's website, the hosting partner upgrades the Jetpack plan behind the scenes and the user is able to use the Jetpack Search feature 23 | 24 | In this flow, the user is only paying for the Jetpack plan once and the host still maintains the billing relationship. 25 | 26 | ## How it works 27 | 28 | When a user clicks an upgrade button, as well as most other links in the Jetpack plugin, the user will end up going to a URL that looks something like this: 29 | 30 | `https://jetpack.com/redirects?source=FOO&site=example.com` 31 | 32 | With the above information, specifically the source and the site URL, we are able to determine the intent of the click as well as whether the user is coming from a site that has been registered with a hosting partner. We will redirect the user to the hosting partner's purchase/upgrade flow if all of the following conditions are met: 33 | 34 | - The source must have purchase intent, meaning that the user would have landed on a purchase flow on WordPress.com 35 | - The site needs to have been registered with the partners API, with or without a plan 36 | - The hosting partner that registered the site needs to have provided us with URLs for their upgrade flows. Currently, we can specify URLs for the following: 37 | - Personal plan (the site does not have an existing plan) 38 | - Premium plan (the site is upgrading from personal) 39 | - Professional plan (the site is upgrading from premium) 40 | - A comparison page, where plan tiers are compared 41 | 42 | ## Subsidiaries 43 | 44 | In some cases a hosting partner may have multiple subsidiaries that they work with and may want to control upgrade redirects for each subsidiary individually. This means that, for example, the Personal plan upgrade link may go to one url for one subsidiary and to another url for another subsidiary. 45 | 46 | To set this up, the hosting provider will need to set the subsidiary id in their provisioned WordPress sites. Setting the subsidiary id can be done via a filter or an option. More information can be found in the Jetpack repository, more specifically, in the [Partner package documentation](https://github.com/Automattic/jetpack/tree/master/packages/partner). 47 | 48 | ## Get started 49 | 50 | For hosting partners to get started with upgrade redirecting, there are only two steps: 51 | 52 | 1) Be sure to register all sites with the partner API 53 | 2) Send us the relevant purchase URLs for the personal, premium, and professional plans as well as a comparison page. If using subsidiaries, make sure to note which upgrade url corresponds to which subsidiary. 54 | -------------------------------------------------------------------------------- /users/user-creation.md: -------------------------------------------------------------------------------- 1 | # User Creation 2 | 3 | Aside from [automatic account creation](/jetpack/automatic-account-creation-connection.md) there is an endpoint available for creating a WordPress.com user. This endpoint assumes the user creation is part of a product provisioning flow, such as provisioning a WooCommerce package to someone that does not yet have a WordPress.com account. 4 | 5 | To successfully create a WordPress.com account for a given user, there are two pre-requisites that must be met: 6 | 7 | - The hosting partner making the request must be whitelisted. 8 | - There must not be an existing WordPress.com account for the given email. 9 | 10 | ## Authentication 11 | In order to make use of this endpoint you will need to be authenticated. Information on this can be found [here](/jetpack/jetpack-start-endpoints/plan-provisioning.md###endpoint-information) 12 | 13 | ## Endpoint Information (/user) 14 | 15 | - __Method__: POST 16 | - __URL__: `https://public-api.wordpress.com/rest/v1.3/jpphp/user` 17 | 18 | ## Request Parameters (/user) 19 | 20 | - __email__: The email address for the user that will be created. 21 | - __product_type__: The product type that is being provisioned for the user being created. This is either `woocommerce` or `jetpack` 22 | - __language__(optional): The ISO 639 code for the language for the user being created. Used to ensure that the email sent to the user to verify their account is translated. Supported languages include: en,af,ar,as,be,bg,bm,bn,bo,ca,cs,csb,cy,da,de,dz,el,eo,es,et,fa,fi,fo,fr,fur,fy,ga,gu,he,hi,hu,ia,id,is,it,ja,ka,km,kn,ko,ku,la,li,lo,lt,ml,ms,nds,nl,nn,no,non,nv,oc,or,os,pa,pl,ps,pt,ro,ru,sc,sk,sl,sq,sr,sv,ta,te,th,tt,uk,ur,wa,yi,tr,az,als,arc,ast,av,ay,ba,br,ce,cv,dv,eu,gn,hr,ii,ks,kv,mk,nah,nap,pt-br,qu,sd,su,ty,udm,ug,vec,vi,xal,za,zh-cn,zh-tw,lv,bs,tl,ne,gl,uz,so,mr,kk,va,mwl,mt,hy,el-po,ilo,si,mn,fil,fr-ch,fr-ca,gd,yo,fr-be,ky,tir,am,en-gb,mya,rup 23 | 24 | 25 | ## Response Parameters (/user) 26 | 27 | Below, the responses are grouped by whether the call to create a user was succesful or not. 28 | 29 | ### Successful response 30 | 31 | - __success__: (bool) Was the operation successful?. 32 | - __bearer_token__: (string) The access token for the newly created user. 33 | 34 | ### Errored response 35 | 36 | - __error_code__: (string) Error code, if any. 37 | - __error_message__: (string) Error message, if any. 38 | 39 | ### Endpoint Errors (/user) 40 | 41 | The following is non-exhaustive list of errors that could be returned. 42 | 43 | | HTTP Code | Error Identifier | Error Message | 44 | | --------- | ------------------------- | ------------------------------------------------------------------------- | 45 | | 403 | forbidden | {partner} is not whitelisted for allowing user creation. | 46 | | 400 | invalid_input_no_email | email is required to create a new WordPress.com account. | 47 | | 400 | invalid_input_no_product_id | product_id is required to provide context for newly created WordPress.com accounts. | 48 | | 400 | invalid_input_unknown_product_id | The supplied product ID is unknown. | 49 | | 400 | user_exists | A WordPress.com user with given email address already exists. | 50 | | 500 | error_access_token | Failure to create acess token 51 | 52 | ## Examples 53 | 54 | ***Replace access_token, product_type and email requirements*** 55 | ```shell 56 | RESULT=$( curl -X POST \ 57 | https://public-api.wordpress.com/rest/v1.3/jpphp/user \ 58 | -H 'Authorization: Bearer {access_token}' \ 59 | -H 'cache-control: no-cache' \ 60 | -F product_tye={product_type} \ 61 | -F email={email} ) 62 | ``` 63 | -------------------------------------------------------------------------------- /woocommerce/install.md: -------------------------------------------------------------------------------- 1 | # Install Product 2 | 3 | Install a product from the plan on the connected site. 4 | 5 | ``` 6 | POST /install 7 | ``` 8 | 9 | - [API v2.0](#api-v20) 10 | 11 | ## API v2.0 12 | 13 | Example request and response: 14 | 15 | ``` 16 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v2.0/install' \ 17 | -H 'Authorization: Bearer ' \ 18 | -H 'Content-Type: application/json' \ 19 | -d '{ 20 | "product_slug": "dynamic-pricing", 21 | "url": "https://example.com", 22 | "order_id": 123 23 | }' 24 | 25 | HTTP/1.1 200 OK 26 | { 27 | "success":true 28 | "request_id": 168, 29 | "order_id": 18734003407356, 30 | "product_id": 18643, 31 | "product_slug":"dynamic-pricing", 32 | "url":"https://example.com" 33 | } 34 | ``` 35 | 36 | ### Parameters v2.0 37 | 38 | | Name | Type | Description | 39 | |----------------|----------|-----------------------------------------| 40 | | `url` | `string` | URL of the site to install the product. | 41 | | `order_id` | `number` | Order ID in WooCommerce.com. | 42 | | `product_slug` | `string` | Slug of the product to install. | 43 | 44 | 45 | ### Response v2.0 46 | 47 | | Name | Type | Description | 48 | |----------------|----------|----------------------------------------------| 49 | | `request_id` | `number` | ID of the installation request. | 50 | | `success` | `bool` | Status of the installation request. | 51 | | `order_id` | `number` | Order ID in WooCommerce.com. | 52 | | `product_id` | `number` | Product ID in WooCommerce.com. | 53 | | `product_slug` | `string` | Slug of the product to install. | 54 | | `url` | `string` | URL of the site the product is installed on. | 55 | 56 | ``` 57 | HTTP/1.1 200 OK 58 | { 59 | "request_id": 168, 60 | "status": "completed", 61 | "order_id": 18734003407356, 62 | "product_id": 18643, 63 | "product_slug":"dynamic-pricing", 64 | "url":"https://example.com" 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /woocommerce/management-via-wp-cli.md: -------------------------------------------------------------------------------- 1 | # Management via WP-CLI 2 | 3 | WP-CLI is a powerful tool for managing sites and is a tool that we imagine many hosting partners will use. Below we will provide some information that we hope will make integration simpler for hosts that use WP-CLI. 4 | 5 | - [Setting up WooCommerce and extensions after calling /register](#setting-up-woocommerce-and-extensions-after-calling-register) 6 | - [Considerations for WP-ClI](#considerations-for-using-wp-cli) 7 | 8 | ## Setting up WooCommerce and extensions after calling /register 9 | 10 | On a successful `/register` call, a hosting partner will end up with something like this: 11 | 12 | ```json 13 | { 14 | "customer_id":1872797, 15 | "order_id":2666930, 16 | "access_token":"e95a8cc87027ec3c303e904d2ea69dd8e0ad0acf", 17 | "access_token_secret":"f71287fdce053102c71536b1648f27657e8be912", 18 | "site_id":42506 19 | } 20 | ``` 21 | 22 | At this point, we have registered the site and made a purchase on WooCommerce.com, but we still need to save the values from the `/register` response as well as install/activate products on the site. Below is an example of how we might do that: 23 | 24 | ```shell 25 | ~ wp plugin install woocommerce --activate 26 | Installing WooCommerce (3.5.6) 27 | Downloading installation package from https://downloads.wordpress.org/plugin/woocommerce.3.5.6.zip... 28 | Using cached file '/srv/users/user0c3505ec/.wp-cli/cache/plugin/woocommerce-3.5.6.zip'... 29 | Unpacking the package... 30 | Installing the plugin... 31 | Plugin installed successfully. 32 | Activating 'woocommerce'... 33 | Plugin 'woocommerce' activated. 34 | Success: Installed 1 of 1 plugins. 35 | ~ wp eval 'require_once WC()->plugin_path() . "/includes/admin/helper/class-wc-helper-options.php"; WC_Helper_Options::update( "auth", array( "access_token" => "e95a8cc87027ec3c303e904d2ea69dd8e0ad0acf", "access_token_secret" => "f71287fdce053102c71536b1648f27657e8be912", "site_id" => 42506, "user_id" => 1, "updated" => time(), ) );' 36 | ~ wp plugin install 'http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-usps/woocommerce-shipping-usps.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=lbxifNZRLGSresGFSE6wNoVyQ2w%3D' --activate 37 | Downloading installation package from http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-usps/woocommerce-shipping-usps.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=lbxifNZRLGSresGFSE6wNoVyQ2w%3D... 38 | Unpacking the package... 39 | Installing the plugin... 40 | Plugin installed successfully. 41 | Activating 'woocommerce-shipping-usps'... 42 | Plugin 'woocommerce-shipping-usps' activated. 43 | Success: Installed 1 of 1 plugins. 44 | ``` 45 | 46 | After running the above commands, you should notice: 47 | 48 | - The site has WooCommerce installed 49 | - The USPS Shipping extension is installed and shows it's using a license in the WooCommerce.com subscriptions page 50 | 51 | ## Considerations for using WP-CLI 52 | 53 | Due to some code not being loaded in the WP-CLI context, there are some issues that require special consideration to work around until fixed in core. We'll list these below along with suggestions for fixing. 54 | 55 | ### Setting authentication information 56 | 57 | As part of the `/register` request, a hosting partner will get back information that allows the site to authenticate with WooCommerce.com. This information is expected to be set in the `woocommerce_helper_data` option, in an array, under the `auth` key. Core WooCommerce provides a helper to set this information, which simplifies setting the information to something like: 58 | 59 | ```php 60 | $response['access_token'], 65 | 'access_token_secret' => $response['access_token_secret'], 66 | 'site_id' => $response['site_id'], 67 | 'user_id' => $user_id, // This is the ID of the user on the customer's site, which is usually 1. 68 | 'updated' => time(), 69 | ) 70 | ); 71 | ``` 72 | 73 | When run in WP-CLI though, `WC_Helper_Options` is not available. A work-around for this is to require the file for the `WC_Helper_Options` class and then set the option. Something like this: 74 | 75 | ``` 76 | wp eval 'require_once WC()->plugin_path() . "/includes/admin/helper/class-wc-helper-options.php"; WC_Helper_Options::update( "auth", array( "access_token" => "ACCESS_TOKEN_HERE", "access_token_secret" => "ACCESS_TOKEN_SECRET_HERE", "site_id" => 123456789, "user_id" => 1, "updated" => time(), ) );' 77 | ``` 78 | 79 | ### Automatically activating and deactivating subscriptions 80 | 81 | There is a known, and [logged](https://github.com/woocommerce/woocommerce/issues/22762), issue where WooCommerce subscriptions for extensions are not automatically managed when the extension plugins are activated or deactivated. Until this is fixed in WooCommerce core, we suggest adding the following snippet of code that runs in an `mu-plugin`: 82 | 83 | ```php 84 | require_helper_files() ) { 124 | return; 125 | } 126 | WC_Helper::activated_plugin( $filename ); 127 | } 128 | 129 | /** 130 | * Given a plugin filename, will attempt to deactivate a subscription on WooCommerce.com for the 131 | * plugin if it is a WooCommerce extension. 132 | * 133 | * @param string $filename The plugin filename. 134 | * @return void 135 | */ 136 | public function deactivated_plugin( $filename ) { 137 | if ( ! $this->require_helper_files() ) { 138 | return; 139 | } 140 | WC_Helper::deactivated_plugin( $filename ); 141 | } 142 | 143 | /** 144 | * Will return true when WooCommerce is installed and active, or false otherwise. 145 | * 146 | * @return boolean 147 | */ 148 | private function is_woo_active() { 149 | return class_exists( 'WooCommerce' ) && function_exists( 'WC' ); 150 | } 151 | 152 | /** 153 | * Will require all helper files if WooCommerce is active. 154 | * 155 | * @return boolean 156 | */ 157 | private function require_helper_files() { 158 | if ( ! $this->is_woo_active() ) { 159 | return false; 160 | } 161 | 162 | try { 163 | foreach ( glob( WC()->plugin_path() . '/includes/admin/helper/*.php' ) as $helper_file ) { 164 | require_once( $helper_file ); 165 | } 166 | } catch ( Exception $e ) { 167 | return false; 168 | } 169 | 170 | return true; 171 | } 172 | } 173 | 174 | WooCommerce_CLI_Integration_Hosting_Partners::init(); 175 | 176 | ``` 177 | 178 | Once this code is added in an `mu-plugin`, then subscriptions should be properly activated/deactivated whenever the plugin file for the extension is activated/deactivated. 179 | -------------------------------------------------------------------------------- /woocommerce/overview.md: -------------------------------------------------------------------------------- 1 | # WooCommerce Integration Overview 2 | 3 | The WooCommerce `host-plan` endpoints are used to provision either a single extension or a bundle of extensions to a given site and user. The extensions that a host partner may provision are defined in what we call a package. This package is unique to a partner and is guarded by a pre-shared secret key that is sent along with requests. This pre-shared secret key is unique to each package, so a given host may have multiple keys if that host is provisioning from multiple packages. 4 | 5 | Below, we'll go over the various integration steps that a hosting partner will need to implement. 6 | 7 | 1. **Registration** 8 | 9 | Once a new customer data (email, first name, last name, and site URL) is available 10 | from plan registration, a request to WooCommerce.com [register](plan-register.md) endpoint 11 | must be made. If site URL is not ready or not propagated yet, it's fine to send 12 | temporary URL. There's another endpoint to [update](update-url.md) a site's URL. 13 | 14 | The response from the register endpoint is important as it is used for establishing a connection between the customer's site and WooCommerce.com as well as in follow-up requests to manage the provisioned package. For example: 15 | 16 | - Cancellation request requires `order_id` parameter. 17 | - Updating site URL request requires `access_token` and `access_token_secret`. 18 | 19 | To save the response in the customer's site options: 20 | 21 | ```php 22 | $response['access_token'], 27 | 'access_token_secret' => $response['access_token_secret'], 28 | 'site_id' => $response['site_id'], 29 | 'user_id' => $user_id, // This is the ID of the user on the customer's site, which is usually 1. 30 | 'updated' => time(), 31 | ) 32 | ); 33 | ``` 34 | 35 | **Note** `WC_Helper_Options` is available when WooCommerce is activated. 36 | 37 | **Note** See [Considerations for WP-CLI](management-via-wp-cli.md#considerations-for-using-wp-cli) if you will be running the above via WP-CLI. 38 | 39 | Documentation can be found [here](plan-register.md). For an overview of the flow see the following flowchart: 40 | 41 | ![WooCommerce registration flow](/assets/woocommerce-register-flow-chart.png) 42 | 43 | 1. **Cancellation** 44 | 45 | Once a WPCOM plan is expired, a request to the WooCommerce.com [cancel](plan-cancel.md) endpoint 46 | must be made. This will cancel the order created from the registration request and 47 | revoke all subscription keys for the extensions (customers still able to use 48 | the extension, but no update and support from WooCommerce.com will be given 49 | for those extensions). 50 | 51 | Documentation can be found [here](plan-cancel.md). 52 | 53 | 1. **Update URL** 54 | 55 | Update a customer site URL for a WooCommerce.com-connected site. 56 | 57 | Documentation can be found [here](update-url.md). 58 | 59 | 1. **Package/Product Information** 60 | 61 | Get information about products in a package / host plan. Response includes latest version and download URL to our internal repository, and as such, that makes these endpoints important for ensuring that a hosting partner is installing the latest WooCommerce products from their package. 62 | 63 | Documentation can be found [here](product-info.md). 64 | -------------------------------------------------------------------------------- /woocommerce/plan-cancel.md: -------------------------------------------------------------------------------- 1 | # Cancel 2 | 3 | Cancel the order created from host plan registration. 4 | 5 | ``` 6 | POST /cancel 7 | ``` 8 | 9 | Example request: 10 | 11 | ``` 12 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/cancel' \ 13 | -H 'Authorization: Bearer ' \ 14 | -H 'Content-Type: application/json' \ 15 | -d '{ 16 | "order_id": 2666932 17 | }' 18 | 19 | HTTP/1.1 200 OK 20 | { 21 | "order_id": 2666932, 22 | "status": "cancelled" 23 | } 24 | ``` 25 | 26 | ## Parameters 27 | 28 | | Name | Type | Description | 29 | | ---- | ---- | ----------- | 30 | | `order_id` | `number` | Order ID in WooCommerce.com. | 31 | 32 | ``` 33 | { 34 | "order_id": 2666932 35 | } 36 | ``` 37 | 38 | ## Response 39 | 40 | | Name | Type | Description | 41 | | ---- | ---- | ----------- | 42 | | `order_id` | `number` | Order ID in WooCommerce.com. | 43 | | `status` | `string` | Order status in WooCommerce.com. | 44 | 45 | ``` 46 | HTTP/1.1 200 OK 47 | { 48 | "order_id": 2666932, 49 | "status": "cancelled" 50 | } 51 | ``` -------------------------------------------------------------------------------- /woocommerce/plan-register.md: -------------------------------------------------------------------------------- 1 | # Register 2 | 3 | Register a new WooCommerce.com customer with initial order of a host plan. 4 | 5 | ```code 6 | POST /register 7 | ``` 8 | 9 | - [API v2.0](#api-v20) 10 | - Simplifies arguments required for registering a plan. Returns same response as v1.0. 11 | - [API v1.0](#api-v10) 12 | 13 | ## API v2.0 14 | 15 | Example request and response: 16 | 17 | ```code 18 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v2.0/register' \ 19 | -H 'Authorization: Bearer ' \ 20 | -H 'Content-Type: application/json' \ 21 | -d '{ 22 | "url": "https://example.com", 23 | "wpcom_access_token": "#K(EkA1*$gx*!JrC#DCe45meEAllcnXjhKNM2Eu!if%^BAAx3z(AaOw@t(CVFnjK)))" 24 | }' 25 | 26 | HTTP/1.1 200 OK 27 | { 28 | "customer_id":1872797, 29 | "order_id":2666930, 30 | "access_token":"e95a8cc87027ec3c303e904d2ea69dd8e0ad0acf", 31 | "access_token_secret":"f71287fdce053102c71536b1648f27657e8be912", 32 | "site_id":42506 33 | } 34 | ``` 35 | 36 | ### Parameters v2.0 37 | 38 | | Name | Type | Description | 39 | | ---- | ---- | ----------- | 40 | | `url` | `string` | Customer site URL. | 41 | | `wpcom_access_token` | `string` | WordPress.com user access token. | 42 | | `products` | `array` | Array of product slugs. This is optional. | 43 | | `metadata` | `object` | Whitelisted key-value pair of custom data. This is optional. | 44 | 45 | ```code 46 | { 47 | "url": "https://example.com", 48 | "wpcom_access_token": "#K(EkA1*$gx*!JrC#DCe45meEAllcnXjhKNM2Eu!if%^BAAx3z(AaOw@t(CVFnjK)))" 49 | "products": [ 'facebook-for-woocommerce', 'woocommerce-shipping-ups' ] 50 | } 51 | ``` 52 | 53 | `metadata` key-value pair is whitelisted based on host request and can be passed as 54 | an object: 55 | 56 | ``` 57 | { 58 | "url": "https://example.com", 59 | "wpcom_access_token": "#K(EkA1*$gx*!JrC#DCe45meEAllcnXjhKNM2Eu!if%^BAAx3z(AaOw@t(CVFnjK)))" 60 | "products": [ 'facebook-for-woocommerce', 'woocommerce-shipping-ups' ], 61 | "metadata": { 62 | "customer_email": "john.doe@example.com", 63 | "customer_first_name": "John", 64 | "customer_last_name": "Doe" 65 | } 66 | } 67 | ``` 68 | 69 | To request the metadata, please contact us and provide details of key name (i.e. `customer_email`) 70 | and its value type (`string` or `email`). 71 | 72 | ### Response v2.0 73 | 74 | Unchanged from [v1.0](#response-v10). 75 | 76 | ## API v1.0 77 | 78 | Example request and response: 79 | 80 | ```code 81 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/register' \ 82 | -H 'Authorization: Bearer ' \ 83 | -H 'Content-Type: application/json' \ 84 | -d '{ 85 | "url": "https://example.com", 86 | "customer": { 87 | "first_name": "John", 88 | "last_name": "Doe", 89 | "email": "john.doe@example.com", 90 | "wpcom_user_id": 123 91 | }}' 92 | 93 | HTTP/1.1 200 OK 94 | { 95 | "customer_id":1872797, 96 | "order_id":2666930, 97 | "access_token":"e95a8cc87027ec3c303e904d2ea69dd8e0ad0acf", 98 | "access_token_secret":"f71287fdce053102c71536b1648f27657e8be912", 99 | "site_id":42506 100 | } 101 | ``` 102 | 103 | ### Parameters v1.0 104 | 105 | | Name | Type | Description | 106 | |------------|----------|--------------------------------------------------------------| 107 | | `url` | `string` | Customer site URL. | 108 | | `customer` | `object` | Customer object. See below. | 109 | | `products` | `array` | Array of product slugs. This is optional. | 110 | | `metadata` | `object` | Whitelisted key-value pair of custom data. This is optional. | 111 | 112 | | Name | Type | Description | 113 | |----------------------|-----------|---------------------------------------------------------------------------------------------------------| 114 | | `first_name` | `string` | Customer first name. | 115 | | `last_name` | `string` | Customer last name. | 116 | | `email` | `string` | Customer email address. Required. | 117 | | `wpcom_user_id` | `integer` | WordPress.com user ID. Optional if `wpcom_access_token` is passed and will be deprecated in the future. | 118 | | `wpcom_access_token` | `string` | WordPress.com user access token. | 119 | 120 | ```code 121 | { 122 | "url": "https://example.com", 123 | "customer": { 124 | "first_name": "John", 125 | "last_name": "Doe", 126 | "email": "john.doe@example.com", 127 | "wpcom_user_id": 123, 128 | "wpcom_access_token": "#K(EkA1*$gx*!JrC#DCe45meEAllcnXjhKNM2Eu!if%^BAAx3z(AaOw@t(CVFnjK)))" 129 | }, 130 | "products": [ 'facebook-for-woocommerce', 'woocommerce-shipping-ups' ], 131 | "metadata": { "plan": "custom-plan" } 132 | } 133 | ``` 134 | 135 | ### Response v1.0 136 | 137 | | Name | Type | Description | 138 | | ---- | ---- | ----------- | 139 | | `customer_id` | `number` | Customer ID in WooCommerce.com. | 140 | | `order_id` | `number` | Order ID in WooCommerce.com. | 141 | | `access_token` | `string` | Customer access token. | 142 | | `access_token_secret` | `string` | Customer access token secret. | 143 | | `site_id` | `number` | Customer site ID in WooCommerce.com. | 144 | 145 | ```code 146 | HTTP/1.1 200 OK 147 | { 148 | "customer_id":1872797, 149 | "order_id":2666930, 150 | "access_token":"e95a8cc87027ec3c303e904d2ea69dd8e0ad0acf", 151 | "access_token_secret":"f71287fdce053102c71536b1648f27657e8be912", 152 | "site_id":42506 153 | } 154 | ``` 155 | 156 | Note: The `access_token_secret` field will only be a valid secret for the first time a plan is registered to a given site. Afterwards, `access_token_secret` will contain `null` as its value. 157 | -------------------------------------------------------------------------------- /woocommerce/product-info.md: -------------------------------------------------------------------------------- 1 | # Package Information 2 | 3 | The following endpoints will allow you to retrieve information about all products for a package or a single product from a package. The expected information for a product will look like this: 4 | 5 | ```json 6 | { 7 | "name": "Facebook for WooCommerce", 8 | "type": "plugin", 9 | "version": "1.9.6", 10 | "last_updated": "2018-09-21", 11 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/facebook-for-woocommerce/facebook-for-woocommerce.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1541139531&Signature=iJMJrkCsUqJNPvctF3HQVZ2ubMI%3D", 12 | "slug": "facebook-for-woocommerce", 13 | "homepage": "https://woocommerce.test/products/facebook/", 14 | "support_documentation": "http://docs.woocommerce.test/document/facebook" 15 | 16 | } 17 | ``` 18 | 19 | **Note:** `type` is not supplied in the `/info/.json` endpoint. 20 | 21 | ## Table of contents 22 | 23 | - [All Products Information](#all-products-information) 24 | - [Single Product Information](#single-product-information) 25 | - [Tips and Tricks](#tips-and-tricks) 26 | 27 | ## All Products Information 28 | 29 | Get information all of the products in a package. 30 | 31 | ```code 32 | GET /info 33 | ``` 34 | 35 | Example request: 36 | 37 | ```code 38 | curl -i -X GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info' \ 39 | -H 'Authorization: Bearer ' \ 40 | -H 'Content-Type: application/json' 41 | 42 | HTTP/1.1 200 OK 43 | { 44 | "name": "wpcom_ecommerce", 45 | "description": "WordPress.com eCommerce Plan", 46 | "products": [ 47 | { 48 | "name": "USPS Shipping Method", 49 | "type": "plugins", 50 | "version": "4.4.19", 51 | "last_updated": "2018-10-17", 52 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-usps/woocommerce-shipping-usps.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=lbxifNZRLGSresGFSE6wNoVyQ2w%3D", 53 | "slug": "woocommerce-shipping-usps", 54 | "homepage": "https://woocommerce.test/products/usps-shipping-method/", 55 | "support_documentation": "http://docs.woocommerce.test/document/usps" 56 | }, 57 | { 58 | "name": "UPS Shipping Method", 59 | "type": "plugins", 60 | "version": "3.2.14", 61 | "last_updated": "2018-10-30", 62 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-ups/woocommerce-shipping-ups.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=emYTeJ98l4mVaViKwKQgM2HCuYA%3D", 63 | "slug": "woocommerce-shipping-ups", 64 | "homepage": "https://woocommerce.test/products/ups-shipping-method/" 65 | "support_documentation": "http://docs.woocommerce.test/document/usps" 66 | }, 67 | { 68 | "name": "Royal Mail", 69 | "type": "plugins", 70 | "version": "2.5.11", 71 | "last_updated": "2018-10-16", 72 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-royalmail/woocommerce-shipping-royalmail.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=tNQDfjKHWLQkE5tyWwxBKCosUaA%3D", 73 | "slug": "woocommerce-shipping-royalmail", 74 | "homepage": "https://woocommerce.test/products/royal-mail/" 75 | }, 76 | { 77 | "name": "Australia Post Shipping Method", 78 | "type": "plugins", 79 | "version": "2.4.7", 80 | "last_updated": "2018-09-27", 81 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-australia-post/woocommerce-shipping-australia-post.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=g%2Fit%2FArPygdkQCf%2FIcN7BVJrHRI%3D", 82 | "slug": "woocommerce-shipping-australia-post", 83 | "homepage": "https://woocommerce.test/products/australia-post-shipping-method/", 84 | "support_documentation": "http://docs.woocommerce.test/document/australia" 85 | }, 86 | { 87 | "name": "Canada Post Shipping Method", 88 | "type": "plugins", 89 | "version": "2.5.7", 90 | "last_updated": "2018-10-17", 91 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-shipping-canada-post/woocommerce-shipping-canada-post.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=%2BgC48cQxXHk9ihjS3YXzH9NeRNA%3D", 92 | "slug": "woocommerce-shipping-canada-post", 93 | "homepage": "https://woocommerce.test/products/canada-post-shipping-method/", 94 | "support_documentation": "http://docs.woocommerce.test/document/candada-post" 95 | }, 96 | { 97 | "name": "Facebook for WooCommerce", 98 | "type": "plugins", 99 | "version": "1.9.8", 100 | "last_updated": "2018-11-30", 101 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/facebook-for-woocommerce/facebook-for-woocommerce.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=lVBd50jPoHZMo7CNFq1P%2BvUiVgs%3D", 102 | "slug": "facebook-for-woocommerce", 103 | "homepage": "https://woocommerce.test/products/facebook/", 104 | "support_documentation": "http://docs.woocommerce.test/document/facebook" 105 | }, 106 | { 107 | "name": "Product Add-Ons", 108 | "type": "plugins", 109 | "version": "3.0.4", 110 | "last_updated": "2018-11-21", 111 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/woocommerce-product-addons/woocommerce-product-addons.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=lIbJCqX6UXRlsBGCmKhBqkF4UGo%3D", 112 | "slug": "woocommerce-product-addons", 113 | "homepage": "https://woocommerce.test/products/product-add-ons/", 114 | "support_documentation": "http://docs.woocommerce.test/document/product-add-ons" 115 | }, 116 | { 117 | "name": "Galleria", 118 | "type": "themes", 119 | "version": "2.2.17", 120 | "last_updated": "2018-08-13", 121 | "download_link": "http://woothemes-products.s3.amazonaws.com/theme-packages/galleria/galleria.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1544211649&Signature=i4Tckbs1bLYGcMdei7SEwIkuR%2FA%3D", 122 | "slug": "galleria", 123 | "homepage": "https://woocommerce.test/products/galleria/", 124 | "support_documentation": "http://docs.woocommerce.test/document/galleria" 125 | } 126 | ] 127 | } 128 | ``` 129 | 130 | ## Single Product Information 131 | 132 | Get information about a product in a package. 133 | 134 | ```code 135 | GET /info/.json 136 | ``` 137 | 138 | Example request: 139 | 140 | ```code 141 | curl -i -X GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info/facebook-for-woocommerce.json' \ 142 | -H 'Authorization: Bearer ' \ 143 | -H 'Content-Type: application/json' 144 | 145 | HTTP/1.1 200 OK 146 | { 147 | "name": "Facebook for WooCommerce", 148 | "version": "1.9.6", 149 | "last_updated": "2018-09-21", 150 | "download_link": "http://woothemes-products.s3.amazonaws.com/plugin-packages/facebook-for-woocommerce/facebook-for-woocommerce.zip?AWSAccessKeyId=AKIAJE6A7GBT4ZRLENMA&Expires=1541139531&Signature=iJMJrkCsUqJNPvctF3HQVZ2ubMI%3D", 151 | "slug": "facebook-for-woocommerce", 152 | "homepage": "https://woocommerce.test/products/facebook/" 153 | "support_documentation": "http://docs.woocommerce.test/document/facebook" 154 | } 155 | ``` 156 | 157 | ## Tips and Tricks 158 | 159 | Using [jq](https://stedolan.github.io/jq/), hosting partners can slice up this data in interesting, useful ways. Below are some examples that hosting partners may find helpful: 160 | 161 | ### Get all of the slugs 162 | 163 | ``` 164 | curl -s GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info' \ 165 | -H 'Authorization: Bearer ' \ 166 | -H 'Content-Type: application/json' | jq '.products[].slug' 167 | ``` 168 | 169 | **Note:** You can substitute `download_link` or another product field for `slug` above to information for that field. For example: 170 | 171 | ### Get all products that are themes 172 | 173 | ``` 174 | curl -s GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info' \ 175 | -H 'Authorization: Bearer ' \ 176 | -H 'Content-Type: application/json' | jq '.products[] | select( .type == "theme" )' 177 | ``` 178 | 179 | **Note:** You can substitute `plugin` for `theme` above to get all extensions. 180 | 181 | ### Get products that were updated on or after a specified day 182 | 183 | The following will return all products that were updated on, or after, `2019-02-14`. 184 | 185 | ``` 186 | curl -s GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info' \ 187 | -H 'Authorization: Bearer ' \ 188 | -H 'Content-Type: application/json' | jq '.products[] | select( .last_updated >= "2019-02-14" )' 189 | ``` 190 | 191 | ### Combining the above 192 | 193 | The following snippet will get the **slug** of all products that are of **theme** type where the theme has been updated after `2019-01-01`. 194 | 195 | ``` 196 | curl -s GET 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/info' \ 197 | -H 'Authorization: Bearer ' \ 198 | -H 'Content-Type: application/json' \ 199 | | jq '.products[] | select( .last_updated >= "2019-01-01" ) | select( .type == "theme" ) | .slug' 200 | ``` 201 | -------------------------------------------------------------------------------- /woocommerce/reporting-endpoints.md: -------------------------------------------------------------------------------- 1 | # WooCommerce Reporting Endpoints 2 | 3 | The following are endpoints used to retrieve stats for a given host plan, identified by the partner's bearer token. 4 | 5 | ## List orders 6 | 7 | List all host-plan orders created to the authenticated host-plan. 8 | 9 | ```code 10 | GET /orders 11 | ``` 12 | 13 | ### Parameters (/orders) 14 | 15 | | Name | Description | 16 | |---------------|-------------------------------------------------------------------------------------------| 17 | | `before` | Limit response to host-plan orders created before a given ISO8601 compliant date. | 18 | | `after` | Limit response to host-plan orders created after a given ISO8601 compliant date. | 19 | | `status` | Limit result set to host-plan orders assigned one or more statuses. Default: `completed`. | 20 | | `customer_id` | Limit result set to host-plan orders assigned a specific customer ID. | 21 | | `page` | Current page of the collection. Default is `1`. | 22 | | `per_page` | Maximum number of items to be returned in result set. Default is `20`. Maximum `100`. | 23 | | `offset` | Offset the result set by a specific number of items. | 24 | 25 | ### Example request and response (/orders) 26 | 27 | ```code 28 | curl -i -X GET \ 29 | --url https://woocommerce.com/wp-json/wccom/host-plan/v2.0/orders \ 30 | --header 'Authorization: Bearer ' \ 31 | --header 'cache-control: no-cache' 32 | HTTP/2 200 33 | server: nginx 34 | date: Fri, 14 Jun 2019 14:38:17 GMT 35 | content-type: application/json; charset=UTF-8 36 | content-length: 6667 37 | x-robots-tag: noindex 38 | x-content-type-options: nosniff 39 | access-control-expose-headers: X-WP-Total, X-WP-TotalPages 40 | access-control-allow-headers: Authorization, Content-Type 41 | x-wp-total: 615 42 | x-wp-totalpages: 31 43 | link: ; rel="next" 44 | cache-control: max-age=60 45 | allow: GET 46 | x-rq: dfw1 82 50 3130 47 | age: 0 48 | x-cache: pass 49 | accept-ranges: bytes 50 | [ 51 | { 52 | "id": 4263050, 53 | "status": "completed", 54 | "date_created": "2019-06-12T21:53:45", 55 | "date_created_gmt": "2019-06-12T19:53:45", 56 | "date_modified": "2019-06-12T21:53:45", 57 | "date_modified_gmt": "2019-06-12T19:53:45", 58 | "customer_id": 123, 59 | "customer_email": "user@example.com", 60 | "line_items": [ 61 | { 62 | "name": "eCommerce Plan" 63 | }, 64 | { 65 | "name": "WooCommerce Bookings" 66 | } 67 | ] 68 | }, 69 | { 70 | "id": 4262968, 71 | "status": "completed", 72 | "date_created": "2019-06-12T21:26:56", 73 | "date_created_gmt": "2019-06-12T19:26:56", 74 | "date_modified": "2019-06-12T21:26:56", 75 | "date_modified_gmt": "2019-06-12T19:26:56", 76 | "customer_id": 124, 77 | "customer_email": "user@example.com", 78 | "line_items": [ 79 | { 80 | "name": "eCommerce Plan" 81 | }, 82 | { 83 | "name": "WooCommerce Bookings" 84 | } 85 | ] 86 | }, 87 | { 88 | "id": 4262918, 89 | "status": "completed", 90 | "date_created": "2019-06-12T21:13:26", 91 | "date_created_gmt": "2019-06-12T19:13:26", 92 | "date_modified": "2019-06-12T21:13:26", 93 | "date_modified_gmt": "2019-06-12T19:13:26", 94 | "customer_id": 125, 95 | "customer_email": "user@example.com", 96 | "line_items": [ 97 | { 98 | "name": "eCommerce Plan" 99 | }, 100 | { 101 | "name": "WooCommerce Bookings" 102 | } 103 | ] 104 | }, 105 | ... 106 | ] 107 | ``` 108 | 109 | ## Get a single order 110 | 111 | Get a single host-plan order. 112 | 113 | ```code 114 | GET /orders/ 115 | ``` 116 | 117 | ### Example request and response (orders/order_id) 118 | 119 | ```code 120 | curl -i -X GET \ 121 | --url https://woocommerce.com/wp-json/wccom/host-plan/v2.0/orders/4262918 \ 122 | --header 'Authorization: Bearer ' \ 123 | --header 'cache-control: no-cache' 124 | HTTP/2 200 125 | server: nginx 126 | date: Fri, 14 Jun 2019 14:36:31 GMT 127 | content-type: application/json; charset=UTF-8 128 | content-length: 344 129 | x-robots-tag: noindex 130 | link: ; rel="https://api.w.org/" 131 | x-content-type-options: nosniff 132 | access-control-expose-headers: X-WP-Total, X-WP-TotalPages 133 | access-control-allow-headers: Authorization, Content-Type 134 | cache-control: max-age=60 135 | allow: GET 136 | x-rq: dfw2 87 152 3154 137 | age: 0 138 | x-cache: pass 139 | accept-ranges: bytes 140 | 141 | { 142 | "id": 4262918, 143 | "status": "completed", 144 | "date_created": "2019-06-12T21:13:26", 145 | "date_created_gmt": "2019-06-12T19:13:26", 146 | "date_modified": "2019-06-12T21:13:26", 147 | "date_modified_gmt": "2019-06-12T19:13:26", 148 | "customer_id": 2442392, 149 | "customer_email": "user@example.com", 150 | "line_items": [ 151 | { 152 | "name": "eCommerce Plan" 153 | }, 154 | { 155 | "name": "WooCommerce Bookings" 156 | } 157 | ], 158 | "metadata": [] 159 | } 160 | ``` 161 | 162 | ## List order connections 163 | 164 | List all connected products in an order. 165 | 166 | ```code 167 | GET /orders//connections 168 | ``` 169 | 170 | ### Response (/orders/order_id/connections) 171 | 172 | ```code 173 | Status: 200 OK 174 | 175 | [ 176 | { 177 | "product_slug": "woocommerce-shipping-usps", 178 | "url": "https://example.com" 179 | }, 180 | ... 181 | ], 182 | ``` 183 | 184 | ## Get a single site 185 | 186 | Get a single host-plan site. 187 | 188 | ```code 189 | GET /sites/ 190 | ``` 191 | 192 | ### Example request and response (/sites/site_id) 193 | 194 | ```code 195 | curl -i -X GET \ 196 | --url https://woocommerce.com/wp-json/wccom/host-plan/v2.0/sites/196037 \ 197 | --header 'Authorization: Bearer ' \ 198 | --header 'Cache-Control: no-cache' 199 | HTTP/2 200 200 | server: nginx 201 | date: Fri, 14 Jun 2019 18:18:27 GMT 202 | content-type: application/json; charset=UTF-8 203 | content-length: 263 204 | x-robots-tag: noindex 205 | link: ; rel="https://api.w.org/" 206 | x-content-type-options: nosniff 207 | access-control-expose-headers: X-WP-Total, X-WP-TotalPages 208 | access-control-allow-headers: Authorization, Content-Type 209 | cache-control: max-age=60 210 | allow: GET 211 | x-rq: dfw2 91 202 3159 212 | age: 0 213 | x-cache: pass 214 | accept-ranges: bytes 215 | 216 | { 217 | "order_ids": { 218 | "completed": [], 219 | "cancelled": [] 220 | }, 221 | "connections": [ 222 | { 223 | "order_id": "3960664", 224 | "site_url": "example.com", 225 | "product_slug": "USPS Shipping Method" 226 | }, 227 | { 228 | "order_id": "3960664", 229 | "site_url": "example.com", 230 | "product_slug": "WooCommerce Bookings" 231 | } 232 | ] 233 | } 234 | ``` 235 | 236 | ## Get totals 237 | 238 | Get totals of orders and connected products over time. 239 | 240 | ```code 241 | GET /totals 242 | ``` 243 | 244 | ### Example request and response (/totals) 245 | 246 | ```code 247 | curl -i -X GET \ 248 | --url https://woocommerce.com/wp-json/wccom/host-plan/v2.0/totals \ 249 | --header 'Authorization: Bearer ' \ 250 | --header 'Cache-Control: no-cache' 251 | HTTP/2 200 252 | server: nginx 253 | date: Fri, 14 Jun 2019 18:25:10 GMT 254 | content-type: application/json; charset=UTF-8 255 | x-robots-tag: noindex 256 | link: ; rel="https://api.w.org/" 257 | x-content-type-options: nosniff 258 | access-control-expose-headers: X-WP-Total, X-WP-TotalPages 259 | access-control-allow-headers: Authorization, Content-Type 260 | cache-control: max-age=60 261 | allow: GET 262 | x-rq: dfw2 87 42 3168 263 | age: 0 264 | x-cache: pass 265 | accept-ranges: bytes 266 | 267 | { 268 | "total_orders": { 269 | "completed": 615, 270 | "cancelled": 56 271 | }, 272 | "total_connections": { 273 | "woocommerce-xero": 1, 274 | "wooslider": 7, 275 | "woocommerce-bookings": 13, 276 | "woocommerce-shipping-usps": 2, 277 | "woothemes-sensei": 2, 278 | "woocommerce-eu-vat-number": 1, 279 | "woocommerce-gateway-paypal-pro": 2, 280 | "woocommerce-shipping-ups": 1, 281 | "woocommerce-product-csv-import-suite": 2, 282 | "woocommerce-software-add-on": 2, 283 | "woocommerce-table-rate-shipping": 1, 284 | "woocommerce-product-vendors": 3 285 | }, 286 | "total_orders_by_month": { 287 | ... 288 | "6-2019": { 289 | "completed": 105, 290 | "cancelled": 28 291 | } 292 | }, 293 | "total_connections_by_month": { 294 | ... 295 | "6-2019": { 296 | "woocommerce-eu-vat-number": 1, 297 | "woocommerce-gateway-paypal-pro": 2, 298 | "woocommerce-shipping-usps": 1, 299 | "woocommerce-shipping-ups": 1, 300 | "woocommerce-product-csv-import-suite": 2, 301 | "woocommerce-software-add-on": 2, 302 | "woocommerce-table-rate-shipping": 1, 303 | "wooslider": 5, 304 | "woothemes-sensei": 1, 305 | "woocommerce-product-vendors": 3, 306 | "woocommerce-bookings": 8 307 | } 308 | } 309 | } 310 | ``` 311 | -------------------------------------------------------------------------------- /woocommerce/update-connected-site.md: -------------------------------------------------------------------------------- 1 | # Update Connected Site 2 | 3 | Change the site connected to the plan. 4 | 5 | ``` 6 | POST /update-connected-site 7 | ``` 8 | 9 | - [API v2.0](#api-v20) 10 | 11 | ## API v2.0 12 | 13 | Example request and response: 14 | 15 | ``` 16 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v2.0/update-connected-site' \ 17 | -H 'Authorization: Bearer ' \ 18 | -H 'Content-Type: application/json' \ 19 | -d '{ 20 | "url": "https://example.com", 21 | "order_id": 123 22 | }' 23 | 24 | HTTP/1.1 200 OK 25 | { 26 | "order_id": 123, 27 | "site_id": 42506, 28 | "url": "https://example.com", 29 | } 30 | 31 | ``` 32 | 33 | ### Parameters v2.0 34 | 35 | | Name | Type | Description | 36 | |------------|----------|------------------------------| 37 | | `url` | `string` | New customer site URL. | 38 | | `order_id` | `number` | Order ID in WooCommerce.com. | 39 | 40 | ### Response v2.0 41 | 42 | | Name | Type | Description | 43 | |------------|----------|--------------------------------------| 44 | | `url` | `string` | New customer site URL. | 45 | | `order_id` | `number` | Order ID in WooCommerce.com. | 46 | | `site_id` | `number` | Customer site ID in WooCommerce.com. | 47 | 48 | ``` 49 | HTTP/1.1 200 OK 50 | { 51 | "url": "https://example.com", 52 | "order_id": 123, 53 | "site_id": 42506 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /woocommerce/update-url.md: -------------------------------------------------------------------------------- 1 | # Update Site URL 2 | 3 | Update customer site URL for a WooCommerce.com-connected site. 4 | 5 | ``` 6 | POST /update-url 7 | ``` 8 | 9 | - [API v2.0](#api-v20) 10 | - Simplifies arguments required for updating a URL to new URL and order ID for a site. 11 | - [API v1.0](#api-v10) 12 | 13 | ## API v2.0 14 | 15 | Example request and response: 16 | 17 | ``` 18 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v2.0/update-url' \ 19 | -H 'Authorization: Bearer ' \ 20 | -H 'Content-Type: application/json' \ 21 | -d '{ 22 | "url": "https://example.com", 23 | "order_id": 123 24 | }' 25 | 26 | HTTP/1.1 200 OK 27 | { 28 | "url": "https://example.com", 29 | "order_id": 123, 30 | "site_id": 42506 31 | } 32 | 33 | ``` 34 | 35 | ### Parameters v2.0 36 | 37 | | Name | Type | Description | 38 | | ---- | ---- |------------------------------| 39 | | `url` | `string` | New customer site URL. | 40 | | `order_id` | `number` | Order ID in WooCommerce.com. | 41 | 42 | ### Response v2.0 43 | 44 | | Name | Type | Description | 45 | | ---- | ---- |--------------------------------------| 46 | | `url` | `string` | New customer site URL. | 47 | | `order_id` | `number` | Order ID in WooCommerce.com. | 48 | | `site_id` | `number` | Customer site ID in WooCommerce.com. | 49 | 50 | ``` 51 | HTTP/1.1 200 OK 52 | { 53 | "url": "https://example.com", 54 | "order_id": 123, 55 | "site_id": 42506 56 | } 57 | ``` 58 | 59 | 60 | ## API v1.0 61 | 62 | Example request and response 63 | 64 | ``` 65 | curl -i -X POST 'https://woocommerce.com/wp-json/wccom/host-plan/v1.0/update-url' \ 66 | -H 'Authorization: Bearer ' \ 67 | -H 'Content-Type: application/json' \ 68 | -d '{ 69 | "url": "https://example.com", 70 | "access_token": "48db97200442b67582147beb6b538f7bafb800d3", 71 | "signature": "beea26f5215d1c1a2312509c1ea0eff2964431972bd45812cae0b27f032f36bf" 72 | }' 73 | 74 | HTTP/1.1 200 OK 75 | true 76 | ``` 77 | 78 | ### Parameters v1.0 79 | 80 | | Name | Type | Description | 81 | | ---- | ---- | ----------- | 82 | | `url` | `string` | New customer site URL. | 83 | | `access_token` | `string` | Customer access token. | 84 | | `signature` | `string` | New customer site url signed (sha256) with the access token secret. | 85 | 86 | Example to create signature in PHP: 87 | 88 | ```php 89 | hash_hmac( 'sha256', 'https://example.com', $access_token_secret ); 90 | ``` 91 | 92 | ``` 93 | { 94 | "url": "https://example.com", 95 | "access_token": "48db97200442b67582147beb6b538f7bafb800d3", 96 | "signature": "beea26f5215d1c1a2312509c1ea0eff2964431972bd45812cae0b27f032f36bf" 97 | } 98 | ``` 99 | 100 | ### Response v1.0 101 | 102 | ``` 103 | HTTP/1.1 200 OK 104 | true 105 | ``` 106 | --------------------------------------------------------------------------------