diff --git a/docs/api/index.md b/docs/api/index.md
index fe3dda76fc39b6c9cdd6d5a3752aa373d6d2b795..ebc737d13c7335eaa62770b3af5205db829042d2 100644
--- a/docs/api/index.md
+++ b/docs/api/index.md
@@ -1,28 +1,24 @@
 # The CiviCRM API
 
-CiviCRM has a stable comprehensive **API** (Application Programming Interface) that can be used to access and manage data in CiviCRM. The API is the recommended way for any CiviCRM extension, CMS module, or external program to interact with CiviCRM.
+CiviCRM has a stable, comprehensive **API** (Application Programming Interface) that can be used to access and manage data in CiviCRM. The API is the recommended way for any CiviCRM extension, CMS module or external program to interact with CiviCRM.
 
 Utilizing the API is superior to accessing core functions directly (e.g.calling raw SQL, or calling functions within the BAO files) because the API offers a consistent interface to CiviCRM's features. It is designed to function predictably with every new release so as to preserve backwards compatibility of the API for several versions of CiviCRM. If you decide to use other ways to collect data (like your own SQL statements), you risk running into future problems when changes to the schema and BAO arguments inevitably occur.
 
 The best place to begin working with the API is your own *test* install of CiviCRM, using the API explorer and the API parameter list.
 
-For help creating your own API custom calls, see [civix generate:api](/extensions/civix.md#generate-api)
+Extensions can provide additional API functionality. For help creating your own additions to the API, see [civix generate:api](/extensions/civix.md#generate-api).
 
-## API explorer
+## API Versions
 
-The API explorer is a powerful GUI tool for building and executing API calls.
+CiviCRM's API has major versions (APIv2, APIv3, APIv4) which are independent of the CiviCRM version. The API version is incremented more slowly in order to maintain stability within the extension ecosystem. Typically, two versions of the API are maintained concurrently (currently v3 and v4) to allow gradual transitions. New releases of CiviCRM may add features to the API but will not break backward-compatibility within an API version.
 
-### Access the APIv3 explorer:
+## API Explorer
 
-1. Go to any CiviCRM site
-    * This can even be the [demo site](http://dmaster.demo.civicrm.org/).
-1. Within the CivCRM menu, go to **Support > Developer > APIv3 Explorer** or go to the URL `/civicrm/api`.
-
-### Access the APIv4 explorer:
+The API explorer is a powerful GUI tool for building and executing API calls. To access it:
 
-1. Go to any CiviCRM site
+1. Log in to a CiviCRM site as an administrator.
     * This can even be the [demo site](http://dmaster.demo.civicrm.org/).
-1. Within the CivCRM menu, go to **Support > Developer > APIv4 Explorer** or go to the URL `/civicrm/api4`.
+2. Within the CivCRM menu, go to **Support > Developer** and either **API Explorer v3** or **API Explorer v4** (URL `/civicrm/api` or `/civicrm/api4`).
 
 !!! warning
     The API explorer actually executes real API calls. It can modify data! So if you execute a `Contact` `delete` call, it will really delete the contact. As such, any experimenting is best done within a test site.
@@ -33,14 +29,14 @@ You can select the entity you want to use, for example `Contact` and the action
 
 From the API explorer, you can get documentation on how to construct your API query. This is done either in the screen as you fill out the GUI to create your API call or in the v3 Explorer there are docs under the Code Docs tab which will point at the relevant aspects of the v3 code base that run the API calls.
 
-## API examples
+## API Examples (APIv3 Only)
 
 Within the API Explorer you will be able to attain an example of the code that you should write to call the API. In APIv3, you can also access epscific examples of some API calls from the Examples tab within the explorer. You can also [explore these examples on GitHub](https://github.com/civicrm/civicrm-core/tree/master/api/v3/examples).
 
-### API Examples in your extensions
+### API examples in your extensions
 
-From CiviCRM v5.8 the APIv3 explorer will now be able to show examples that are stored in your extension. The only requirement is that they are found in the same sort of directory structure as core e.g. in `<yourextension>/api/v3/examples/<entity>/<file>`
+Beginning in CiviCRM v5.8, the APIv3 explorer will now be able to show examples that are stored in your extension. The only requirement is that they are found in the same sort of directory structure as core e.g. in `<yourextension>/api/v3/examples/<entity>/<file>`
 
 ## Changelog
 
-All important changes made to the APIv3 are recorded in [APIv3 changes](/api/v3/changes.md).
+All important changes made to the API are recorded in [APIv3 changes](/api/v3/changes.md) and [APIv4 changes](/api/v4/changes.md).
diff --git a/docs/api/v4/changes.md b/docs/api/v4/changes.md
new file mode 100644
index 0000000000000000000000000000000000000000..fbaaca542097531a480eaa7278bfd0b51a2fdaea
--- /dev/null
+++ b/docs/api/v4/changes.md
@@ -0,0 +1,9 @@
+# API v4 Changelog
+
+This page lists additions to the v4 api with each new release of CiviCRM Core.
+
+Also see: [Differences Between Api v3 and v4](/api/v4/differences-with-v3.md).
+
+## Nothing here yet.
+
+API v4 is brand new. No changes yet!
diff --git a/docs/api/v4/differences-with-v3.md b/docs/api/v4/differences-with-v3.md
new file mode 100644
index 0000000000000000000000000000000000000000..7c04e3815b667ff4c14e43503972e216e087baea
--- /dev/null
+++ b/docs/api/v4/differences-with-v3.md
@@ -0,0 +1,166 @@
+# Differences Between API v3 and v4
+
+APIv4 is broadly similar to APIv3. Both are designed for reading and writing data.
+Both use *entities*, *actions*, and *parameters*. However, APIv4 is specifically a
+breaking-change which aims to reduce *ambiguity* and improve *flexibility* and *consistency*.
+
+This document walks through a list of specific differences.  As you consider
+them, it may help to have a concrete example expressed in both APIv3 and APIv4:
+
+<!-- Would be nice if Markdown made it easier to do side-by-side comparison... -->
+<table>
+  <thead>
+    <tr>
+      <th>APIv3</th>
+      <th>APIv4</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+<td>
+  <em>Procedural-array style:</em><br/>
+  <div class="codehilite"><pre>
+ 1: $res = civicrm_api3('Contact', 'get', [
+ 2:   'sequential' => 1,
+ 3:   'check_permissions' => 0,
+ 4:   'first_name' => 'Bob',
+ 5:   'return' => 'id,display_name',
+ 6:   'options' => [
+ 7:     'limit' => 2,
+ 8:     'offset' => 2,
+ 9:   ],
+10: ]);
+11:
+12: foreach ($res['values'] as $row) {
+13:   echo $row['display_name'];
+14: }
+</pre></div>
+</td>
+<td>
+  <em>Procedural-array style:</em><br/>
+  <div class="codehilite"><pre>
+ 1: $res = civicrm_api4('Contact', 'get', [
+ 2:   'checkPermissions' => FALSE,
+ 3:   'where' => [['first_name', '=', 'Bob']],
+ 4:   'select' => ['id', 'display_name'],
+&nbsp;
+ 6:   'limit' => 2,
+ 7:   'offset' => 2,
+&nbsp;
+ 9: ]);
+10:
+11: foreach ($res as $row) {
+12:   echo $row['display_name'];
+13: }
+</pre></div>
+
+  <em>Object-oriented style:</em><br/>
+  <div class="codehilite"><pre>
+ 1: $res = \Civi\Api4\Contact::get()
+ 2:  ->setCheckPermissions(FALSE)
+ 3:  ->addWhere(['first_name', '=', 'Bob'])
+ 4:  ->addSelect(['id', 'display_name'])
+&nbsp;
+ 6:  ->setLimit(2)
+ 7:  ->setOffset(2)
+&nbsp;
+ 9:  ->execute();
+10:
+11: foreach ($res as $row) {
+12:   echo $row['display_name'];
+13: }
+</pre></div>
+</td>
+    </tr>
+  </tbody>
+</table>
+
+
+## API Wrapper
+
+* APIv4 supports two notations in PHP:
+    * Procedural/array style: `civicrm_api4('Entity', 'action', $params)`
+    * Object-oriented style: `\Civi\Api4\Entity::action()->...->execute()`
+* When using OOP style in an IDE, most actions and parameters can benefit from auto-completion and type-checking.
+* `$checkPermissions` always defaults to `TRUE`. In APIv3, the default depended on the environment (`TRUE` in REST/Javascript; `FALSE` in PHP).
+* A 4th param `index` controls how results are returned:
+    * Passing a string will index all results by that key e.g. `civicrm_api4('Contact', 'get', $params, 'id')` will index by id.
+    * Passing a number will return the result at that index e.g. `civicrm_api4('Contact', 'get', $params, 0)` will return the first result and is the same as `\Civi\Api4\Contact::get()->execute()->first()`. `-1` is the equivalent of `$result->last()`.
+* When chaining API calls together, back-references to values from the main API call must be explicitly given (discoverable in the API Explorer).
+
+## Actions 
+* For `Get`, the default `limit` has changed. If you send an API call without an explicit limit, then it will return *all* records. (In v3, it would silently apply a default of 25.) However, if you use the API Explorer, it will *recommend* a default limit of 25.
+* The `Create` action is now only used for creating *new* items (no more implicit update by passing an id to v3 `create`).
+* The `Save` action in v4 is most similar to v3's `create` - it accepts one or more records to create or update, infering the action based on the presence of `id` in each record.
+* `Update` and `Delete` can be performed on multiple items at once by specifying a `where` clause, vs a single item by id in v3.
+* `getsingle` is gone, use `$result->first()` or `index` `0`.
+* `getoptions` is no longer a standalone action, but part of `getFields`.
+
+## Output  
+* Output is an object (`Result` aka [`ArrayObject`](https://www.php.net/manual/en/class.arrayobject.php)) rather than a plain `array`.
+* In PHP, you can iterate over the `ArrayObject` (`foreach ($myResult as $record)`), or you can call methods like `$result->first()` or `$result->indexBy('foo')`.
+* By default, results are indexed sequentially (`0,1,2,3,...` - like APIv3's `sequential => 1`). You may optionally index by `id`, `name`, or any other field, as in:
+    * (Procedural-style; use `$index` parameter): `civicrm_api4('Contact', 'get', [], 'id')`
+    * (OOP-style; use `indexBy()` method): `\Civi\Api4\Contact::get()->execute()->indexBy('id')`
+
+## Input
+* Instead of a single `$params` array containing a mishmash of fields, options and parameters, each APIv4 parameter is distinct (see section on Params below).
+* Custom fields are refered to by name rather than id. E.g. use `constituent_information.Most_Important_Issue` instead of `custom_4`.
+
+## Params
+
+If you used early versions of APIv3, you might have written some code like this:
+
+```php
+civicrm_api3('Contact', 'get', array(
+  'check_permissions' => 0,
+  'first_name' => 'Elizabeth',
+  'return' => 'id,display_name',
+  'rowCount' => 2,
+  'offset' => 2,
+));
+```
+
+You may notice that there are no subordinate arrays -- everything goes into one flat list of parameters.
+As the system grew, this became a bit awkward:
+
+* What happens if you want to filter on a field named `return` or `action` or `rowCount`?
+* How do you ensure that the same option gets the same name across all entities (`rowCount` vs `limit`)?
+* Why does `first_name` use snake_case while `rowCount` uses lowerCamelCase?
+* Why is `Contact.get` the only API to support `rowCount`?
+
+Over time, APIv3 evolved so that this example would be more typical:
+
+```php
+civicrm_api3('Contact', 'get', [
+  'check_permissions' => FALSE,
+  'first_name' => 'Elizabeth',
+  'return' => ['id','display_name'],
+  'options' => ['limit' => 1000, 'offset' => 2],
+]);
+```
+
+Observe:
+
+* The `options` adds a place where you can define parameters without concern for conflicts.
+* The new generation of `options` are more standardized - they often have generic implementations that work with multiple entities/actions.
+* The top-level still contains a mix of *option* fields (like `return`) and *data* or *query* fields (like `first_name`).
+* The old options at the top-level are deprecated but still around.
+
+APIv4 presented an opportunity to *break backward compatibility* and thereby *become more consistent*. In APIv4, a typical call would look like:
+
+```php
+civicrm_api4('Contact', 'get', [
+  'checkPermissions' => FALSE,
+  'where' => [['first_name', '=', 'Elizabeth']],
+  'select' => ['id', 'display_name'],
+  'limit' => 2,
+  'offset' => 2,
+]);
+```
+
+Key things to note:
+
+* The `options` array is completely gone. The params array *is* the list of options.
+* Most of the options in the params array have shared/generic implementations - ensuring consistent naming and behavior.
+* The *data* fields (e.g. `id`, `display_name`, and `first_name`) no longer appear at the top. They always appear beneath some other option, such as `where` or `select`.
diff --git a/mkdocs.yml b/mkdocs.yml
index 19142b4c956f35aeaa269a3254fed042b4e6505e..b02ea360eb881eaf0926f215d63fae498ed4211c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -54,12 +54,11 @@ pages:
   - APIv4:
     - APIv4 Usage: api/v4/usage.md
     - APIv4 Actions: api/v4/actions.md
-  #  - APIv4 Options: api/v4/options.md
     - APIv4 Joins: api/v4/joins.md
     - APIv4 Chaining: api/v4/chaining.md
     - APIv4 Custom Data: api/v4/custom-data.md
-  #  - APIv4 Examples: api/v4/examples.md
-  #  - APIv4 Changes: api/v4/changes.md
+    - Differences Between Api v3 and v4: api/v4/differences-with-v3.md
+    - APIv4 Changes: api/v4/changes.md
   - APIv3:
     - APIv3 Usage: api/v3/usage.md
     - APIv3 Actions: api/v3/actions.md