From 5ab6adec81791b20583156a1958cf0934e82ec15 Mon Sep 17 00:00:00 2001
From: Jon goldberg <jon@palantetech.coop>
Date: Thu, 15 Jun 2017 11:42:10 -0400
Subject: [PATCH] Document API joins - closes #125

---
 docs/api/joins.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 mkdocs.yml        |  1 +
 2 files changed, 63 insertions(+)
 create mode 100644 docs/api/joins.md

diff --git a/docs/api/joins.md b/docs/api/joins.md
new file mode 100644
index 00000000..30521bda
--- /dev/null
+++ b/docs/api/joins.md
@@ -0,0 +1,62 @@
+# API Joins
+
+An API "get" action will typically return only the values of the entity
+requested. However, there are times when it is advantageous to returned
+data from a related entity.  For instance, when querying the API for email
+addresses, you may want to return the name of the associated contact from the
+Contact entity.
+
+The CiviCRM API supports two methods of returning data from associated entities;
+API Joins and [API Chaining](/api/chaining).  API joins provide higher
+performance by making a single SQL query with a
+[SQL join](https://dev.mysql.com/doc/refman/5.7/en/join.html), and are
+generally preferable to API chaining where available.
+
+## Using an API Join
+
+To use a join in an API call, specify the name of the field on which the
+join happens, a period, and the name of the field to reference.  
+
+For instance, to search for all primary emails, returning the email and joining
+to also return the contact's display name:
+```php
+$result = civicrm_api3('Email', 'get', array(
+  'return' => array("email", "contact_id.display_name"),
+  'is_primary' => 1,
+));
+```
+
+Alternatively, to return email addresses of everyone whose last name is Smith
+by joining to the Contact entity:
+```php
+$result = civicrm_api3('Email', 'get', array(
+  'contact_id.last_name' => "Smith",
+));
+```
+
+You can join multiple times in one query.  For instance, to return a list of
+events, displaying their name, the name of the related campaign, and that
+campaign's type:
+```php
+$result = civicrm_api3('Event', 'get', array(
+  'return' => array("title", "campaign_id.name", "campaign_id.campaign_type_id"),
+));
+```
+!!! tip
+    Joins are available only with the [get](/api/actions/#getfields),
+    [getsingle](/api/actions/#getsingle), and [getcount](/api/actions/#getcount)
+    actions.
+
+## Identifying fields eligible for a join
+
+It is possible to join an entity to any other entity if the [xml](/core/architecture/#xml)
+schema identifies a [foreign key](https://en.wikipedia.org/wiki/Foreign_key) or
+a pseudoconstant.  The [getfields](/api/actions/#getfields) action identifies
+fields that are eligible for an API join.
+
+!!! warning
+    For historical reasons, some entities have a non-standard API in APIv3
+    in order to handle more complicated operations. Those entities -  'Contact',
+    'Contribution', 'Pledge', and 'Participant' - can be joined to from another
+    table, but you can not join to other tables from them.  This limitation will
+    be removed in APIv4.
diff --git a/mkdocs.yml b/mkdocs.yml
index edbc6586..8c890a4e 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -61,6 +61,7 @@ pages:
   - APIv3 Actions: api/actions.md
   - APIv3 Parameters: api/params.md
   # APIv3 Permissions: api/permissions.md
+  - APIv3 Joins: api/joins.md
   - APIv3 Chaining: api/chaining.md
   # APIv3 Changes: api/changes.md
 - Hooks:
-- 
GitLab