Add-on, ExpressionEngine, Headless, API
Bones
Headless ExpressionEngine With One Line of Template Code.
Buy NowINSTALLATION
- Copy entire
bones
folder to yoursystem/user/addons
folder. - On your EE backend, navigate to
Developer > Addons
(yoursite.com/admin.php?/cp/addons). - Scroll to
Third Party Add-Ons
. - Find
Bones
and clickInstall
. - Add your settings, and enjoy!
SETTINGS
Active: If turned on, will return data. When turned off, will return an error.
Use API Key: If turned on, each API call will require your API key to be attached to the request.
API Key: Add in an API key of your choosing.
USAGE
Reading Entries Via Template Code
Bones is meant to be used within a template all it's own, and is flexible enough to accept all of ExpressionEngine's channel entries tag parameters, either within the template tag itself, or as parameters in your API call.
Create a template group with an index file. For our example, we created api.group
with index.html.
If you wanted to retrieve all entries without any filtering, or including filtering within your API call, then you would simply add this to your template:
{exp:bones:entries}
You would then be able to view this in browser (for testing) at your URL and template group, i.e. https://example.com/api
Channel Entry Parameters
Bones automatically accepts all Channel Entries tags parameters as well. So, if you wanted to view only the blog
channel with a status of draft
, your template code will look like:
{exp:bones:entries channel="blog" status="draft"}
Skipping Standard Object Keys
For entries that are sent back, each one includes a number of standard fields included with each EE entry (see #responses for more information). You can use the following parameters in your call in order to skip those fields:
- skip_view_count: skip view count data
- skip_signature: skip signature data
- skip_avatar: skip avatar data
- skip_member_data: skip member data
For example:
https://example.com/api?channel=blog&status=draft&skip_view_count=y&skip_member_data=y
Reading Entries Via API Call
You can now use your API by making a GET call to your site as such https://example.com/api
All available channel entries tag parameters are also available via the API as GET or POST variables. So, if you wanted to view only the blog
channel with a status of draft
, your API Call will look like:
https://example.com/api?channel=blog&status=draft
All query parameters must be properly URL encoded when submitting.
Reading Categories
Categories can be read similarly to entries:
{exp:bones:categories channel="blog"}
Category Parameters
Since EE Category data is only available via a string in the template code, we adjusted this method to get just the categories. Therefore, all of the category parameters in the Channel Categories tag are available except the following:
- backspace
- class
- disable
- id
- style
Reading Entries Via API Call
You can now use your API by making a GET call to your site as such https://example.com/api
All available channel categories tag parameters, minus those mentioned above, are also available via the API as GET or POST variables. So, if you wanted to view only the blog
channel with a status of draft
, your API Call will look like:
https://example.com/api?channel=blog
All query parameters must be properly URL encoded when submitting.
Reading Entries Via Action URL
You can now use your API by making a GET call to your site as such https://example.com/api
Your action IDs are listed in the settings panel of Bones.
https://example.com/ACT=123?channel=blog&status=draft
All query parameters must be properly URL encoded when submitting.
API Key
If you are using an API key to get your data, including the api_key
parameter in your calls.
https://example.com/api?api_key=123456789
Search
Since EE search works a bit different in channel parameters, Bones handles this with GET or POST parameters structured as such:
https://example.com/api?search[title]=my+awesome+title
This would be the equivalent of:
{exp:channel:entries search:title="my awesome title"}
All search parameters work the same as the Channel Entries tag, and should be properly url encoded when submitted.
Custom Fields
Out of the box, Bones handles all native EE fields, including Grids, Relationships, and Fluid Fields. It also handles Bloqs, and any custom fields that output text (i.e. WYGWAM).
For other custom fields, you can add your own custom Field Parsers into the FieldFormatters
folder. (COMING SOON, let us know what you need)
Response String Only
If you are just looking for quick JSON of your data to use in a template, you can use the response_string=y
in the API call in order to get the JSON encoded string for use in your templates.
Security Concerns
Secure API Key
If you are looking for a secure implementation of Bones to a third party app, it is recommended utilizing the API key set up through a backend connector. This allows you to use your API key in other applications without exposing another site and its credentials.
Frontend API Calls
Frontend API calls are a great way to get your data to be slurped on in your frontend javascript. As you do this, ensure you are taking standard API security precautions to protect sensitive data.
It is highly recommend that you should avoid calling data from a secondary domain via the frontend, which may reveal unintended routes from the child site or API credentials, or set up proper CORS for any third party site you would want to call.
RESPONSES
All responses, whether success or error, have 4 incoming parameters:
- success: Boolean value to indicate whether API call was successful or not
- message: Any incoming message that would attached to the call. Primarily used for error indication
- count: Count of incoming data objects. 0 if success is
false
- data: Array of items coming in. Array will be empty if success if
false
.
Success
ENTRIES: GET https://example.com/api?api_key=123&entry_id=12
{
"success": true,
"message": "success",
"count": 1,
"data":
[
{
"entry_id": 12,
"forum_topic_id": null,
"title": "Entry with vimeo or some junk!!!",
"url_title": "action-comedy-how-to",
"status": "open",
"view_count_one": 0,
"view_count_two": 0,
"view_count_three": 0,
"view_count_four": 0,
"sticky": "n",
"entry_date":
{
"pretty_date": "Thu, 25 Feb 2021 11:00:00 -0500",
"seconds_from_epoch": "1614268800",
"iso8601": "2021-02-25T11:00:00-05:00",
"raw": 1614268800
},
"year": "2021",
"month": "02",
"day": "25",
"edit_date":
{
"pretty_date": "Fri, 12 Nov 2021 11:25:23 -0500",
"seconds_from_epoch": "1636734323",
"iso8601": "2021-11-12T11:25:23-05:00",
"raw": 1636734323
},
"expiration_date": 0,
"recent_comment_date": 1614268852,
"comment_total": 11,
"channel_title": "Blog",
"channel_name": "blog",
"username": "doug",
"email": "[email protected]",
"screen_name": "doug",
"signature": null,
"sig_img_filename": null,
"sig_img_width": null,
"sig_img_height": null,
"avatar_filename": null,
"avatar_width": null,
"avatar_height": null,
"photo_filename": null,
"photo_width": null,
"photo_height": null,
"site_id": 1,
"test_fluid_field":
{
"about_image":
[
{
"image": "https://ee-pro-ee.test/themes/user/site/default/asset/img/common/8yf91jhf3ef71.jpg",
"caption": "adadsasd",
"align": "right"
}
],
"order_billing_address": " 123 Fake St"
},
"seo_title": "Action Comedy",
"seo_desc": "This is how it's done, the incomparable Jackie Chan shows us the way.",
"related_entries":
[
{
"entry_id": 7,
"title": "Super old entry BUT asdasdaMATION POINTS!!!",
"url_title": "super-old-entry",
"status": "open",
"sticky": false,
"entry_date": 1614268800,
"edit_date":
{
"date": "2021-07-27 20:33:11.000000",
"timezone_type": 1,
"timezone": "+00:00"
},
"channel_name": null,
"username": null,
"email": null,
"screen_name": null
},
{
"entry_id": 10,
"title": "Entry with SoundCloud audio!!! WHENENNSHSHSHSSHSAOSDJOSDAASDOSDAOSDAJOSJIOSIO",
"url_title": "the-one-where-we-shake-it-ff",
"status": "open",
"sticky": false,
"entry_date": 1614268800,
"edit_date":
{
"date": "2021-08-06 13:48:28.000000",
"timezone_type": 1,
"timezone": "+00:00"
},
"channel_name": null,
"username": null,
"email": null,
"screen_name": null
},
{
"entry_id": 13,
"title": "Test Page With Everything!!!!",
"url_title": "test-page-with-everything",
"status": "open",
"sticky": false,
"entry_date": 1628156040,
"edit_date":
{
"date": "2021-10-04 12:16:14.000000",
"timezone_type": 1,
"timezone": "+00:00"
},
"channel_name": null,
"username": null,
"email": null,
"screen_name": null
}
],
"blog_video":
[
{
"id": "113439313",
"type": "vimeo"
}
],
"blog_image":
[],
"blog_audio":
[],
"blog_content": "Lorem ipsum dolor sit amet, <b>this is bold text</b> consectetur <strong>this text is strongly emphasized</strong> adipisicing elit, sed do eiusmod tempor incididunt <i>this is italic text</i> ut labore <em>this text is emphasized</em> et dolore magna aliqua. Ut enim ad minim veniam, <a href=\"\">this is a link</a> quis nostrud <a href=\"\" rel=\"external\">this is an external link</a> laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse <del>This text is deleted</del> <ins>this text is inserted</ins> cillum <code>this is a code sample</code> dolore eu <mark>this text is highlighted</mark> fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nIOJIJOASDOIJDASJOIASDJOIASDOJASD",
"rando_date":
{
"pretty_date": "Sat, 20 Nov 2021 09:43:56 -0500",
"seconds_from_epoch": "1637419436",
"iso8601": "2021-11-20T09:43:56-05:00",
"raw": null
},
"slider_field": {
"value":49,
"field_min_value": "0",
"field_max_value": "100",
"field_step": "1"
},
"duration_field": {
"value":"984",
"units":"minutes"
}
}
]
}
Every entry at a root level will contain the following standard EE fields:
- entry_id
- forum_topic_id
- title
- url_title
- status
- view_count_one
- view_count_two
- view_count_three
- view_count_four
- sticky
- entry_date
- year
- month
- day
- edit_date
- expiration_date
- recent_comment_date
- comment_total
- channel_title
- channel_name
- username
- screen_name
- signature
- sig_img_filename
- sig_img_width
- sig_img_height
- avatar_filename
- avatar_width
- avatar_height
- photo_filename
- photo_width
- photo_height
Entries at any nested level will display:
- entry_id
- title
- url_title
- status
- sticky
- entry_date
- edit_date
- channel_name
- username
- screen_name
CATEGORIES: GET https://example.com/api?api_key=123
{
"success": true,
"message": "success",
"count": 5,
"data":
[
{
"category_name": "News",
"category_url_title": "news",
"category_description": null,
"category_image": "",
"category_id": 1,
"parent_id": 0,
"active": false,
"count": 1,
"total_results": 5
},
{
"category_name": "Personal",
"category_url_title": "personal",
"category_description": null,
"category_image": "",
"category_id": 2,
"parent_id": 0,
"active": false,
"count": 2,
"total_results": 5
},
{
"category_name": "Photos",
"category_url_title": "photos",
"category_description": null,
"category_image": "",
"category_id": 3,
"parent_id": 0,
"active": false,
"count": 3,
"total_results": 5
},
{
"category_name": "Videos",
"category_url_title": "videos",
"category_description": null,
"category_image": "",
"category_id": 4,
"parent_id": 0,
"active": false,
"count": 4,
"total_results": 5
},
{
"category_name": "Music",
"category_url_title": "music",
"category_description": null,
"category_image": "",
"category_id": 5,
"parent_id": 0,
"active": false,
"count": 5,
"total_results": 5
}
]
}
Errors
Authorization Error
{"success":false,"message":"Not authorized","count":0,"data":[]}
SAMPLES
In the samples
folder attached here, you will see a couple of EE templates that will demonstrate usage of Bones:
- basic-usage: The absolute minimum needed in a template
- blog-channel-only: Get all entries from a Blog channel
Sample Javascript Implementation
- Bones Test: In the
samples/test.group
folder is a template that will fully connect to your API route. - bones-hello-world: A simple Vue implementation of the API
TERMS OF SERVICE
Utilizing any API-based service means that your data can be called via a network call. It is of great importance that you use the best API security practices with your implementation of Bones. The creator of this addon and its subsidiaries can not be held responsible for data that is available via API calls through this addon. For more information, or assistance setting up your Bones implementation, please see Support information below.
SUPPORT
We want to make sure you have what you need on this. Email [email protected] for help.