diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 8adca156616..00000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,30 +0,0 @@ -# Changelog - -## Version 1.1 - -*July 27th, 2014* - -**Fixes:** - -- Finally, a fix for the redcarpet upgrade bug - -## Version 1.0 - -*July 2, 2014* - -[View Issues](https://github.com/tripit/slate/issues?milestone=1&state=closed) - -**Features:** - -- Responsive designs for phones and tablets -- Started tagging versions - -**Fixes:** - -- Fixed 'unrecognized expression' error -- Fixed #undefined hash bug -- Fixed bug where the current language tab would be unselected -- Fixed bug where tocify wouldn't highlight the current section while searching -- Fixed bug where ids of header tags would have special characters that caused problems -- Updated layout so that pages with disabled search wouldn't load search.js -- Cleaned up Javascript diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index b04fc955ca5..00000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,9 +0,0 @@ -# Contributing to Slate - -Thanks for contributing to Slate! A couple of quick guidelines for submitting PRs: - -- Please point your pull requests at the `dev` branch, and keep your commit messages clear and informative. -- Please make sure your contributions work in the most recent version of Chrome, Firefox, and IE. -- If you're implementing a new feature, even if it's relatively small, it's nice to open an issue before you start so that others know what you're working on and can help make sure you're on the right track. - -Thanks again! Happy coding. \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index e3931cd63af..fac0fd8dddf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: http://rubygems.org/ specs: - activesupport (4.1.10) + activesupport (4.1.16) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) @@ -9,11 +9,11 @@ GEM tzinfo (~> 1.1) celluloid (0.16.0) timers (~> 4.0.0) - chunky_png (1.3.4) + chunky_png (1.3.10) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1.1) + coffee-script-source (1.12.2) compass (1.0.3) chunky_png (~> 1.2) compass-core (~> 1.0.2) @@ -27,34 +27,35 @@ GEM compass-import-once (1.0.5) sass (>= 3.2, < 3.5) erubis (2.7.0) - execjs (2.5.2) - ffi (1.9.8) - haml (4.0.6) + execjs (2.7.0) + ffi (1.9.23) + haml (5.0.4) + temple (>= 0.8.0) tilt hike (1.2.3) - hitimes (1.2.2) - hooks (0.4.0) - uber (~> 0.0.4) + hitimes (1.2.6) + hooks (0.4.1) + uber (~> 0.0.14) i18n (0.7.0) - json (1.8.2) - kramdown (1.7.0) - libv8 (3.16.14.7) - listen (2.10.0) + json (1.8.6) + kramdown (1.16.2) + libv8 (3.16.14.19) + listen (2.10.1) celluloid (~> 0.16.0) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) - middleman (3.3.11) + middleman (3.3.12) coffee-script (~> 2.2) compass (>= 1.0.0, < 2.0.0) compass-import-once (= 1.0.5) execjs (~> 2.0) haml (>= 4.0.5) kramdown (~> 1.2) - middleman-core (= 3.3.11) + middleman-core (= 3.3.12) middleman-sprockets (>= 3.1.2) sass (>= 3.4.0, < 4.0) uglifier (~> 2.5) - middleman-core (3.3.11) + middleman-core (3.3.12) activesupport (~> 4.1.0) bundler (~> 1.1) erubis @@ -68,7 +69,7 @@ GEM tilt (~> 1.4.1, < 2.0) middleman-gh-pages (0.0.3) rake (> 0.9.3) - middleman-sprockets (3.4.2) + middleman-sprockets (3.5.0) middleman-core (>= 3.3) sprockets (~> 2.12.1) sprockets-helpers (~> 1.1.0) @@ -76,26 +77,26 @@ GEM middleman-syntax (2.0.0) middleman-core (~> 3.2) rouge (~> 1.0) - minitest (5.6.1) - multi_json (1.11.0) - padrino-helpers (0.12.5) + minitest (5.11.3) + multi_json (1.13.1) + padrino-helpers (0.12.9) i18n (~> 0.6, >= 0.6.7) - padrino-support (= 0.12.5) - tilt (~> 1.4.1) - padrino-support (0.12.5) + padrino-support (= 0.12.9) + tilt (>= 1.4.1, < 3) + padrino-support (0.12.9) activesupport (>= 3.1) - rack (1.6.0) + rack (1.6.9) rack-test (0.6.3) rack (>= 1.0) rake (10.4.2) - rb-fsevent (0.9.4) - rb-inotify (0.9.5) - ffi (>= 0.5.0) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) redcarpet (3.2.3) - ref (1.0.5) + ref (2.0.0) rouge (1.8.0) - sass (3.4.13) - sprockets (2.12.3) + sass (3.4.25) + sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) @@ -105,18 +106,19 @@ GEM sprockets-sass (1.3.1) sprockets (~> 2.0) tilt (~> 1.1) - therubyracer (0.12.2) - libv8 (~> 3.16.14.0) + temple (0.8.0) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) ref - thor (0.19.1) - thread_safe (0.3.5) + thor (0.20.0) + thread_safe (0.3.6) tilt (1.4.1) - timers (4.0.1) + timers (4.0.4) hitimes - tzinfo (1.2.2) + tzinfo (1.2.5) thread_safe (~> 0.1) - uber (0.0.13) - uglifier (2.7.1) + uber (0.0.15) + uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) @@ -131,3 +133,6 @@ DEPENDENCIES redcarpet (~> 3.2.2) rouge (~> 1.8.0) therubyracer (~> 0.12.1) + +BUNDLED WITH + 1.16.0 diff --git a/README.md b/README.md index 21ec87edac2..090df5ba08a 100644 --- a/README.md +++ b/README.md @@ -1,119 +1,14 @@ -Slate -======== +The home of our various API, Gem and other public documentation. +That's right, **PUBLIC**. -[![Build Status](https://travis-ci.org/tripit/slate.svg?branch=master)](https://travis-ci.org/tripit/slate) [![Dependency Status](https://gemnasium.com/tripit/slate.png)](https://gemnasium.com/tripit/slate) +Whatever is here is publicly available at http://developer.lexer.io. -Slate helps you create beautiful API documentation. Think of it as an intelligent, responsive documentation template for your API. +## How to run -Screenshot of Example Documentation created with Slate + # run a server on http://localhost:7890 + bundle exec middleman server --port=7890 -*The example above was created with Slate. Check it out at [tripit.github.io/slate](http://tripit.github.io/slate).* +## How to publish -Features ------------- - -* **Clean, intuitive design** — with Slate, the description of your API is on the left side of your documentation, and all the code examples are on the right side. Inspired by [Stripe's](https://stripe.com/docs/api) and [Paypal's](https://developer.paypal.com/webapps/developer/docs/api/) API docs. Slate is responsive, so it looks great on tablets, phones, and even print. - -* **Everything on a single page** — gone are the days where your users had to search through a million pages to find what they wanted. Slate puts the entire documentation on a single page. We haven't sacrificed linkability, though. As you scroll, your browser's hash will update to the nearest header, so linking to a particular point in the documentation is still natural and easy. - -* **Slate is just Markdown** — when you write docs with Slate, you're just writing Markdown, which makes it simple to edit and understand. Everything is written in Markdown — even the code samples are just Markdown code blocks! - -* **Write code samples in multiple languages** — if your API has bindings in multiple programming languages, you easily put in tabs to switch between them. In your document, you'll distinguish different languages by specifying the language name at the top of each code block, just like with Github Flavored Markdown! - -* **Out-of-the-box syntax highlighting** for [almost 60 languages](http://rouge.jayferd.us/demo), no configuration required. - -* **Automatic, smoothly scrolling table of contents** on the far left of the page. As you scroll, it displays your current position in the document. It's fast, too. We're using Slate at TripIt to build documentation for our new API, where our table of contents has over 180 entries. We've made sure that the performance remains excellent, even for larger documents. - -* **Let your users update your documentation for you** — by default, your Slate-generated documentation is hosted in a public Github repository. Not only does this mean you get free hosting for your docs with Github Pages, but it also makes it's simple for other developers to make pull requests to your docs if they find typos or other problems. Of course, if you don't want to, you're welcome to not use Github and host your docs elsewhere! - -Getting starting with Slate is super easy! Simply fork this repository, and then follow the instructions below. Or, if you'd like to check out what Slate is capable of, take a look at the [sample docs](http://tripit.github.io/slate). - - - -Getting Started with Slate ------------------------------- - -### Prerequisites - -You're going to need: - - - **Linux or OS X** — Windows may work, but is unsupported. - - **Ruby, version 1.9.3 or newer** - - **Bundler** — If Ruby is already installed, but the `bundle` command doesn't work, just run `gem install bundler` in a terminal. - -### Getting Set Up - - 1. Fork this repository on Github. - 2. Clone *your forked repository* (not our original one) to your hard drive with `git clone https://github.com/YOURUSERNAME/slate.git` - 3. `cd slate` - 4. Install all dependencies: `bundle install` - 5. Start the test server: `bundle exec middleman server` - -Or use the included Dockerfile! (must install Docker first) - -```shell -docker build -t slate . -docker run -d -p 4567:4567 slate -``` - -You can now see the docs at . Whoa! That was fast! - -*Note: if you're using the Docker setup on OSX, the docs will be -availalable at the output of `boot2docker ip` instead of `localhost:4567`.* - -Now that Slate is all set up your machine, you'll probably want to learn more about [editing Slate markdown](https://github.com/tripit/slate/wiki/Markdown-Syntax), or [how to publish your docs](https://github.com/tripit/slate/wiki/Deploying-Slate). - -Examples of Slate in the Wild ---------------------------------- - -* [Travis-CI's API docs](http://docs.travis-ci.com/api/) -* [Mozilla's localForage docs](http://mozilla.github.io/localForage/) -* [Mozilla Recroom](http://mozilla.github.io/recroom/) -* [ChaiOne Gameplan API docs](http://chaione.github.io/gameplanb2b/#introduction) -* [Drcaban's Build a Quine tutorial](http://drcabana.github.io/build-a-quine/#introduction) -* [PricePlow API docs](https://www.priceplow.com/api/documentation) -* [Emerging Threats API docs](http://apidocs.emergingthreats.net/) -* [Appium docs](http://appium.io/slate/en/master) -* [Golazon Developer](http://developer.golazon.com) -* [Dwolla API docs](https://docs.dwolla.com/) -* [RozpisyZapasu API docs](http://www.rozpisyzapasu.cz/dev/api/) -* [Codestar Framework Docs](http://codestarframework.com/documentation/) -* [Buddycloud API](http://buddycloud.com/api) -* [Crafty Clicks API](https://craftyclicks.co.uk/api/) -* [Paracel API Reference](http://paracel.io/docs/api_reference.html) -* [Switch Payments Documentation](http://switchpayments.com/docs/) & [API](http://switchpayments.com/developers/) -* [Coinbase API Reference](https://developers.coinbase.com/api) -* [Whispir.io API](https://whispir.github.io/api) -* [NASA API](https://data.nasa.gov/developer/external/planetary/) -* [CardPay API](https://developers.cardpay.com/) -* [IBM Cloudant](https://docs-testb.cloudant.com/content-review/_design/couchapp/index.html) -* [Bitrix basis components](http://bbc.bitrix.expert/) - -(Feel free to add your site to this list in a pull request!) - -Need Help? Found a bug? --------------------- - -Just [submit a issue](https://github.com/tripit/slate/issues) to the Slate Github if you need any help. And, of course, feel free to submit pull requests with bug fixes or changes. - - -Contributors --------------------- - -Slate was built by [Robert Lord](http://lord.io) while at [TripIt](http://tripit.com). - -Thanks to the following people who have submitted major pull requests: - -- [@chrissrogers](https://github.com/chrissrogers) -- [@bootstraponline](https://github.com/bootstraponline) -- [@realityking](https://github.com/realityking) - -Also, thanks to [Sauce Labs](http://saucelabs.com) for helping sponsor the project. - -Special Thanks --------------------- -- [Middleman](https://github.com/middleman/middleman) -- [jquery.tocify.js](https://github.com/gfranko/jquery.tocify.js) -- [middleman-syntax](https://github.com/middleman/middleman-syntax) -- [middleman-gh-pages](https://github.com/neo/middleman-gh-pages) -- [Font Awesome](http://fortawesome.github.io/Font-Awesome/) + # You'll need write perms on the github + rake publish diff --git a/source/CNAME b/source/CNAME new file mode 100644 index 00000000000..053bf84541d --- /dev/null +++ b/source/CNAME @@ -0,0 +1 @@ +developer.lexer.io diff --git a/source/images/activity/activity_cases.png b/source/images/activity/activity_cases.png new file mode 100644 index 00000000000..9769c14e7bc Binary files /dev/null and b/source/images/activity/activity_cases.png differ diff --git a/source/images/activity/activity_nps.png b/source/images/activity/activity_nps.png new file mode 100644 index 00000000000..ac41d5ab730 Binary files /dev/null and b/source/images/activity/activity_nps.png differ diff --git a/source/images/activity/activity_sla.png b/source/images/activity/activity_sla.png new file mode 100644 index 00000000000..578d4da75bf Binary files /dev/null and b/source/images/activity/activity_sla.png differ diff --git a/source/images/activity/activity_summary.png b/source/images/activity/activity_summary.png new file mode 100644 index 00000000000..fbbb92346d7 Binary files /dev/null and b/source/images/activity/activity_summary.png differ diff --git a/source/images/activity/activity_team.png b/source/images/activity/activity_team.png new file mode 100644 index 00000000000..ccec67ee99f Binary files /dev/null and b/source/images/activity/activity_team.png differ diff --git a/source/images/content/authors_engaged_2.png b/source/images/content/authors_engaged_2.png new file mode 100644 index 00000000000..71c581b76b3 Binary files /dev/null and b/source/images/content/authors_engaged_2.png differ diff --git a/source/images/content/authors_influential_2.png b/source/images/content/authors_influential_2.png new file mode 100644 index 00000000000..0758dd50729 Binary files /dev/null and b/source/images/content/authors_influential_2.png differ diff --git a/source/images/content/authors_volume.png b/source/images/content/authors_volume.png new file mode 100644 index 00000000000..733aa9033bc Binary files /dev/null and b/source/images/content/authors_volume.png differ diff --git a/source/images/content/classifications.png b/source/images/content/classifications.png new file mode 100644 index 00000000000..c51bf403572 Binary files /dev/null and b/source/images/content/classifications.png differ diff --git a/source/images/content/livestreamvolume_chart.png b/source/images/content/livestreamvolume_chart.png new file mode 100644 index 00000000000..a9ca7ebe7cc Binary files /dev/null and b/source/images/content/livestreamvolume_chart.png differ diff --git a/source/images/content/locations.png b/source/images/content/locations.png new file mode 100644 index 00000000000..868467b09ef Binary files /dev/null and b/source/images/content/locations.png differ diff --git a/source/images/content/mention_tweet_2.png b/source/images/content/mention_tweet_2.png new file mode 100644 index 00000000000..5a0a1a409d9 Binary files /dev/null and b/source/images/content/mention_tweet_2.png differ diff --git a/source/images/content/source_groups.png b/source/images/content/source_groups.png new file mode 100644 index 00000000000..4cf9fb4488d Binary files /dev/null and b/source/images/content/source_groups.png differ diff --git a/source/images/content/source_top.png b/source/images/content/source_top.png new file mode 100644 index 00000000000..6593a3f2854 Binary files /dev/null and b/source/images/content/source_top.png differ diff --git a/source/images/content/source_types.png b/source/images/content/source_types.png new file mode 100644 index 00000000000..21aca03609f Binary files /dev/null and b/source/images/content/source_types.png differ diff --git a/source/images/content/source_volume.png b/source/images/content/source_volume.png new file mode 100644 index 00000000000..84a74024019 Binary files /dev/null and b/source/images/content/source_volume.png differ diff --git a/source/images/content/summary_bar.png b/source/images/content/summary_bar.png new file mode 100644 index 00000000000..d9502ff48bd Binary files /dev/null and b/source/images/content/summary_bar.png differ diff --git a/source/images/content/terms_table.png b/source/images/content/terms_table.png new file mode 100644 index 00000000000..b2c80c8ee56 Binary files /dev/null and b/source/images/content/terms_table.png differ diff --git a/source/images/content/terms_volume.png b/source/images/content/terms_volume.png new file mode 100644 index 00000000000..2c8e2f185fe Binary files /dev/null and b/source/images/content/terms_volume.png differ diff --git a/source/images/favicon.png b/source/images/favicon.png new file mode 100644 index 00000000000..7b6602376dd Binary files /dev/null and b/source/images/favicon.png differ diff --git a/source/images/logo.png b/source/images/logo.png index fa1f13da819..8a9ee0a4b02 100644 Binary files a/source/images/logo.png and b/source/images/logo.png differ diff --git a/source/includes/_activity.md b/source/includes/_activity.md new file mode 100644 index 00000000000..61035727eb1 --- /dev/null +++ b/source/includes/_activity.md @@ -0,0 +1,1010 @@ +# Activity + +Using the Activity API, you can retrieve performance data on your team operating within Lexer Engage. Access insightful metrics such as the number of closed cases, average response time, or your overall NPS score for last month. We’ve made your Activity data accessible so you can run bespoke reports or add them to your applications. + +Our API is organised into two sections; Get and Post requests. Get requests allow you to access the user, groups and forms information related to your team. These are useful for filtering your reports. Post requests are queries that comprise of particular report types and filter parameters. Reports may be filtered by users, groups, forms and time. + +## API Tokens + +You will need an API token to access your Activity data. Tokens are managed within the Settings area of the Hub, and require Manager permissions to access. All endpoints require an API token to authenticate your requests. + +## GET Users + +Retrieve a list of users that have access to your Lexer account. You can use these user details to filter any of the Activity queries for agent specific metrics. Here we'll describe how you request and interpret this information. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" -X GET https://api.lexer.io/v1/users +``` + +**Endpoint** +`https://api.lexer.io/v1/users` + +```json + { + "id": 12345, + "email": "jane@business.io", + "first_name": "Jane", + "last_name": "Remington", + "timezone": "Australia/Sydney", + "gmtoffset": 10, + "sign_in_count": 76, + "last_sign_in_at": "2018-03-21T06:09:01Z", + "archived": false, + "groups": [ + 123, + 456, + 789, + ] + } +``` + + +Property | Description | Type | +---------|-------------|------| +id | user id | number +email | email account used to login | string +first_name | first name of the user | string +last_name | last name of the user | string +timezone | timezone location of user | string +gmtoffset | timezone offset of user | number +sign_in_count | count of logins | number +last_sign_in_at | date of users last login | string +archived | archived flag for user | boolean +groups | groups the user is in | array + + +## GET Groups + +Retrieve a list of groups that exist in your Lexer account. You can use these group details to filter any of the Activity queries for team specific metrics. Here we'll describe how you request and interpret this information. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" -X GET https://api.lexer.io/v1/groups +``` + +**Endpoint** +`https://api.lexer.io/v1/groups` + +```json + + { + "id": 123, + "name": "Social Customer Care", + "comment": "Social customer care team members" + } +``` + + +Property | Description | Type | +---------|-------------|------| +id | group id | number +name | name of the group | string +comment | description of the group | string + + + +## GET Forms + +Retrieve a list of forms/surveys that exist in your Lexer account. These include NPS surveys, authentication forms, and competition surveys. You need to specifiy the NPS Survey id when requesting the NPS Summary or NPS Volume data. Here we'll describe how you request and interpret this information. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" -X GET https://api.lexer.io/v1/forms +``` + +**Endpoint** +`https://api.lexer.io/v1/forms` + +```json + { + "id": 55, + "name": "NPS Survey", + "title": "Lexer NPS Survey", + "archived": false, + "created_at": "2018-05-26T21:54:19Z", + "groups": [ + 123 + ], + "nps": false, + "form_url": "https://d1z1wrkt4y2iqm.cloudfront.net/123455678899876543/1/form" + } +``` + + +Property | Description | Type | +---------|-------------|------| +id | group id | number +name | name of the form | string +title | title of the form | string +archived | archived flag | boolean +created_at | date this form was created | string +groups | groups that have access to this form | array +nps | is this form an NPS survey? | boolean +form_url | URL to view this form | string + + +## Summary + +Access your teams high level performance metrics - including total objects handled, response times, and classifications on these objects. + +![Source Volume](../images/activity/activity_summary.png) + +



+ +**Summary Metrics** + +Access the summary metrics that are used to power the big number metrics you can see in Activity. This includes the number of objects handled, response count, average response time, agent handle time and a few others. + + + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "summary", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` + +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** summary + +```json +{ + "total_volume": 7526, + "avg_response_time": 1315.27098046203, + "min_response_time": 50.702796, + "max_response_time": 200663.392234, + "avg_action_response_time": 509.337687048021, + "min_action_response_time": 4.908278, + "max_action_response_time": 199826.523834, + "total_responded_to": 3582, + "broke_sla": 166, + "broke_action_sla": 45, + "avg_response_time_min": 21.9211830077005, + "avg_action_response_time_min": 8.48896145080035 +} +``` +Property | Description | Type | +---------|-------------|------| +total_volume | total objects handled | number +avg_response_time | average customer to reponse time in seconds | number +min_response_time | min customer to reponse time in seconds | number +max_response_time | max customer to reponse time in seconds | number +avg_action_response_time | average assign to response time in seconds | number +min_action_response_time | min assign to response time in seconds | number +max_action_response_time | max assign to response time in seconds | number +total_responded_to | objects responded to | number +broke_sla | number of objects that exceeded customer SLA time | number +broke_action_sla | number of objects that exceeded agent handle SLA time | number +avg_response_time_min | average customer response time in minutes | number +avg_action_response_time_min | average agent handle time in minutes | number + + +





+ + +**Summary Volume** + +Daily volume of objects in each workflow state. Your response will contain an array for each state, and within that state an object for each period (i.e. each day). + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "states_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** states_volume + + +```json +{ + "closed": [ + { + "state": "closed", + "value": 174, + "date_range": { + "date_from": "2018-04-27 00:00" + } + }, + { + "state": "closed", + "value": 234, + "date_range": { + "date_from": "2018-04-28 00:00" + } + }, + { + "state": "closed", + "value": 255, + "date_range": { + "date_from": "2018-04-29 00:00" + } + }, + { + "state": "closed", + "value": 108, + "date_range": { + "date_from": "2018-04-30 00:00" + } + } + ] +} +``` + +Property | Description | Type | +---------|-------------|------| +state | workflow state | string +value | number of objects in this state | number +date_range | date for value | string + +**Notes:** + Most results will be found in the 'closed' state. We suggest using this volume to map total volume over time. + + If your query range is less than 4 days the time intervals will be reduced from days to hours. + + +




















+ + +**States** + +Total volume of objects in each of the workflow states. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "user_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** user_volume + + +```json +[ + { + "state": "closed", + "volume": 92 + }, + { + "state": "responded", + "volume": 49 + }, + { + "state": "assigned", + "volume": 26 + }, + { + "state": "in_progress", + "volume": 13 + }, + { + "state": "duplicate", + "volume": 4 + }, + { + "state": "awaiting_approval", + "volume": 1 + } +] +``` + +Property | Description | Type | +---------|-------------|------| +state | workflow state | string +volume | count of objects | number + + + +




















+ + +**Classifications (Objects)** + +Classifications and the number of objects in each workflow state. You can get the total count for each classification using the 'all_states' value. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "classifications", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** classifications + +```json +[ + { + "classification_id": 123, + "classification": "amusing", + "state": "assigned", + "volume": 2 + }, + { + "classification_id": 123, + "classification": "amusing", + "state": "all_states", + "volume": 3 + }, + { + "classification_id": 123, + "classification": "amusing", + "state": "closed", + "volume": 1 + }, + { + "classification_id": 143, + "classification": "customer service", + "state": "responded", + "volume": 1 + }, + { + "classification_id": 143, + "classification": "customer service", + "state": "all_states", + "volume": 1 + } +] +``` + +Property | Description | Type | +---------|-------------|------| +classification_id | unique id | number +classification | name | string +state | workflow state | string +volume | count of classifications | number + +























+ + + +**Response Time** + +Returns the daily average response time for all objects handled by your team. Here we're looking at the same data that powers the SLA Performance line chat in Activity. Note that if your query range is 3 days or less, the intervals will be reduced to hourly. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "response_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** response_volume + +```json +{ + "avg_response_time": [ + + { + "value": 317691.388907962, + "date_range": { + "date_from": "2018-06-05 00:00" + } + }, + { + "value": 31159.3797606667, + "date_range": { + "date_from": "2018-06-06 00:00" + } + }, + { + "value": 69850.8753626667, + "date_range": { + "date_from": "2018-06-07 00:00" + } + }, + { + "value": 10661.255474, + "date_range": { + "date_from": "2018-06-08 00:00" + } + } + ] +} +``` + +Property | Description | Type | +---------|-------------|------| +value | average response time in minutes | number +date_range | date interval | string + + + + + + + +## Team + +Access your teams individual performance data - including objects handled per agent, response times, and more. + +![Source Volume](../images/activity/activity_team.png) + +

+ +**Agent Summary** + +Return the performance metrics for each agent in your team. The data you access in this request is used to populate the 'Team' chart in Activity. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "user_summary", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** user_summary + +```json +[ + { + "first_name": "Jane", + "last_name": "Pear", + "mentions_assigned": 12, + "user_id": "123", + "responded_to": 9, + "responded_to_in_private": 6, + "avg_response_time": 17053.3492157778, + "min_response_time": 56.983366, + "max_response_time": 84664.420214, + "avg_action_response_time": 278.770835555556, + "min_action_response_time": 7.767898, + "max_action_response_time": 2261.353394, + "total_responded_to": 9, + "broke_sla": 3, + "broke_action_sla": 0, + "avg_response_time_min": 284.22248692962995, + "avg_action_response_time_min": 4.6461805925926, + "fraction_responded_to": 0.75, + "fraction_responded_to_in_private": 0.6666666666666666, + "fraction_broke_sla": 0.3333333333333333, + "fraction_broke_action_sla": 0.0 + }, + { + "first_name": "Barry", + "last_name": "Banana", + "mentions_assigned": 7, + "user_id": "789", + "responded_to": 1, + "responded_to_in_private": 1, + "avg_response_time": 352842.64921, + "min_response_time": 352842.64921, + "max_response_time": 352842.64921, + "avg_action_response_time": 134.51357, + "min_action_response_time": 134.51357, + "max_action_response_time": 134.51357, + "total_responded_to": 1, + "broke_sla": 1, + "broke_action_sla": 0, + "avg_response_time_min": 5880.710820166667, + "avg_action_response_time_min": 2.241892833333333, + "fraction_responded_to": 0.14285714285714285, + "fraction_responded_to_in_private": 1.0, + "fraction_broke_sla": 1.0, + "fraction_broke_action_sla": 0.0 + } +] +``` + +Property | Description | Type | +---------|-------------|------| +first_name | first name of agent | string +last_name | last name of agent | string +mentions_assigned | count of object assigned to agent | number +user_id | unique id of agent | string +responded_to | count of objects responded to | number +responded_to_in_private | count of objects responded to that are private messages | number +avg_response_time | average customer to reponse time in seconds | number +min_response_time | average customer to reponse time in seconds | number +max_response_time | max customer to reponse time in seconds | number +avg_action_response_time | average assign to response time in seconds | type +min_action_response_time | min assign to response time in seconds | type +max_action_response_time | max assign to response time in seconds | type +total_responded_to | count of objects responded to | number +broke_sla | number of objects that exceeded customer SLA time | number +broke_action_sla | number of objects that exceeded agent handle SLA time | number +avg_response_time_min | average customer response time in minutes | number +avg_action_response_time_min | average agent handle time in minutes | type +fraction_responded_to | responded_to divided by mentions_assigned | number +fraction_responded_to_in_private | responded_to_in_private divided by mentions_assigned | number +fraction_broke_sla | broke_sla divided by responded_to | number +fraction_broke_action_sla | broke_action_sla divided by responded_to | number + + + +




+ + + +**Agent Volume** + +Return the count of objects currently assigned to each agent in your team. For each team member, this will also breakdown the objects by their current workflow state. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "user_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** user_volume + +```json +[ + { + "user_id": 123, + "first_name": "Jane", + "last_name": "Pear", + "states": { + "all_states": 166, + "all_closed_states": 110, + "new": 0, + "assigned": 15, + "in_progress": 14, + "responded": 27, + "awaiting_approval": 0, + "redirected": 0, + "irrelevant": 0, + "duplicate": 0, + "closed": 110, + "no_response_required": 0 + } + }, + { + "user_id": 789, + "first_name": "Barry", + "last_name": "Banana", + "states": { + "all_states": 4, + "all_closed_states": 1, + "new": 0, + "assigned": 1, + "in_progress": 1, + "responded": 1, + "awaiting_approval": 0, + "redirected": 0, + "irrelevant": 0, + "duplicate": 0, + "closed": 1, + "no_response_required": 0 + } + } +] +``` + +Property | Description | Type | +---------|-------------|------| +user_id | unique id for agent | number +first_name | first name of agent | string +last_name | last name of agent | string +states | count of each state owned by agent | array + + +























+ + + + + +## SLA + +Export a complete log of all customer messages your team has triaged and replied to from Engage. Use this file if you're looking for a single master document. + + + + + + +## Cases + + +Access performance metrics on the conversations your team are having, which we call cases. This includes total case volume, first response times, resolution times, and case classifications. + +![Source Volume](../images/activity/activity_cases.png) + +

+ +**Case Summary** + +Return the summary metrics for the cases your team have handled. Cases are only created when an agent responds to a customer. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "case_summary", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** case_summary + +```json +{ + "total_cases": 4, + "first_reply_time": 1907.187351, + "resolution_time": 1907.187351, + "agent_interactions": 1.0, + "agents_involved": 1.0 +} +``` + +Property | Description | Type | +---------|-------------|------| +total_cases | count of cases closed in this period | number +first_reply_time | average case first reply time | number +resolution_time | average case resolution time | number +agent_interactions | average number of agent replies per case | number +agents_involved | average number of agents responding per case | number + + +




+ + +**Case Volume** + +Return the count of open cases for each day. Cases are tracked from the first customer query to the last agent response. Cases are closed 24 hours of inactivity from either the customer or the agent, provided all customer messages are in a closed state. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "case_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** case_volume + +```json +{ + "open": [ + { + "value": 9, + "date_range": { + "date_from": "2018-04-01 00:00" + } + }, + { + "value": 9, + "date_range": { + "date_from": "2018-04-02 00:00" + } + }, + { + "value": 9, + "date_range": { + "date_from": "2018-04-03 00:00" + } + }, + { + "value": 9, + "date_range": { + "date_from": "2018-04-04 00:00" + } + }, + { + "value": 9, + "date_range": { + "date_from": "2018-04-05 00:00" + } + }, + { + "value": 10, + "date_range": { + "date_from": "2018-04-06 00:00" + } + }, + { + "value": 9, + "date_range": { + "date_from": "2018-04-07 00:00" + } + } + ] +} +``` + + +Property | Description | Type | +---------|-------------|------| +value | count of active cases | number +date_from | date interval | string + + +
























+ + +**Case Classifications** + +Return the count of classifications applied to the cases in this time period. Classifications are only counted once per case, helping you understand the number of conversations about each topic. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "case_classifications", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00" +}' +``` +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** case_classifications + +```json +[ + { + "classification_id": 466, + "classification": "positive", + "volume": 1 + }, + { + "classification_id": 526, + "classification": "social nps", + "volume": 1 + }, + { + "classification_id": 528, + "classification": "feedback", + "volume": 1 + }, + { + "classification_id": 1246, + "classification": "amusing", + "volume": 1 + }, + { + "classification_id": 1465, + "classification": "image", + "volume": 1 + }, + { + "classification_id": 1467, + "classification": "loyalty", + "volume": 1 + }, + { + "classification_id": 1472, + "classification": "bot", + "volume": 1 + } +] +``` + +Property | Description | Type | +---------|-------------|------| +classification_id | unique id for each classification | number +classification | name for each classification | string +volume | count of classifications | number + + + +## NPS + +Access your teams NPS performance metrics - including overall score, count of detractors, promoters, passives, and your average response rate. Reminder to retrieve your forms (see GET Forms above) to retrieve a list of the NPS Surveys your team are using. The ID for your form will be used to generate the following queries. + +![Source Volume](../images/activity/activity_nps.png) + +

+ +**NPS Summary** + +Return the summary metrics for the specified NPS Survey. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "nps_summary", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00", + "form": 123, + "nps_category": "all" +}' +``` + +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** nps_summary + +```json +{ + "total_sent": 16, + "total_received": 12, + "total_promoters": 9, + "total_passives": 1, + "total_detractors": 2, + "nps_score": 58.333333333333336 +} +``` + +Property | Description | Type | +---------|-------------|------| +total_sent | count of surveys sent | number +total_received | count of responses received | number +total_promoters | count of 9-10 score responses | number +total_passives | count of 7-8 score responses | number +total_detractors | count of <7 score responses | number +nps_score | average nps score | number + + + + +

+ +**NPS Volume** + +Return the daily volume of NPS scores and responses for each day in your query range. + +```text +curl -H "Content-Type: application/json" -H "Auth-Api-Token: 12345678-1234-1234-1234-123456789" https://api.lexer.io/v1/activity/reports -d ' +{ + "type": "nps_volume", + "date_from": "2018-04-01T00:00:00+11:00", + "date_to": "2018-04-30T23:59:59+11:00", + "form": 123, + "nps_category": "all" +}' +``` + +**Endpoint** +`https://api.lexer.io/v1/activity/reports` + +**Type:** nps_volume + +```json +[ + { + "date": "2018-04-01T13:00:00+00:00", + "timestamp": 1522587600, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-02T13:00:00+00:00", + "timestamp": 1522674000, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-03T13:00:00+00:00", + "timestamp": 1522760400, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-04T13:00:00+00:00", + "timestamp": 1522846800, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-05T13:00:00+00:00", + "timestamp": 1522933200, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-06T13:00:00+00:00", + "timestamp": 1523019600, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + }, + { + "date": "2018-04-07T13:00:00+00:00", + "timestamp": 1523106000, + "data": { + "total_sent": 0, + "total_received": 0, + "total_promoters": 0, + "total_passives": 0, + "total_detractors": 0, + "nps_score": 0.0 + } + } +] +``` + +Property | Description | Type | +---------|-------------|------| +date | date time in UTC | string +timestamp | date time in Epoch time | number +total_sent | count of surveys sent | number +total_received | count of responses received | number +total_promoters | count of 9-10 score responses | number +total_passives | count of 7-8 score responses | number +total_detractors | count of <7 score responses | number +nps_score | average nps score | number + + + +## Errors + +The API may return the following error codes. + +Code | Type | Description | +---------|-------------|------| +400 | Invalid report - date range is too long | Your date range must be not greather than 12 months +400 | Invalid report - starting date is a future date | Starting date must be in the past +400 | Invalid report - invalid type| Chart type provided is invalid +401 | Unauthorized - api token not matching| Your API token provided is not valid +401 | Unauthorized | missing authentication data | API token is missing +404 | Not found | General error for malformed request +429 | Rate limited exceeded | You're making too many requests + + + +## Rate Limiting + +The API may rate limit requests made by your application. Our rate limits are managed by an allowed number of requests per time window. A single request could be to retrieve a list of users, or query a particular chart endpoint. + +The rate limit is **100 requests per 5 minutes per API Token.** + +In the case you are rate limited a "429 Rate limited exceeded" response will be returned. \ No newline at end of file diff --git a/source/includes/_chatbot.md b/source/includes/_chatbot.md new file mode 100644 index 00000000000..28c9aa9e716 --- /dev/null +++ b/source/includes/_chatbot.md @@ -0,0 +1,3 @@ +# Chatbot + +Coming soon. \ No newline at end of file diff --git a/source/includes/_content.md b/source/includes/_content.md new file mode 100644 index 00000000000..1c1e2e87365 --- /dev/null +++ b/source/includes/_content.md @@ -0,0 +1,636 @@ +# Content + +Our Content API allows you to access social and news content in a simple JSON format. Your queries are defined by saved dives within Listen, and your endpoints are retrieved from the Command charts they are connected to. Once you have a chart displaying in Command, simply click on the small link button in the top right corner. + +Read our [help article](https://learn.lexer.io/export-and-report/command/command-screens) for details on building a Command screen or contact support via live chat or at [support@lexer.io](mailto:support@lexer.io). + +## Prerequisites + +- **Listen**: to create your saved dives that define your search. +- **Command**: to create the charts using your saved dives. + + +## Configuration + +Unlike traditional APIs, your requests for the Content API must be created from our live dashboard feature Command. Your Command screen allows you to test and visualise the results before retrieving the API endpoint. Once you're happy with the results, simply click the link button on the top right corner of the chart and your request will be provided in the URL. + +### Endpoints +```text +https://hub.lexer.io/api/clients/{account_id}/screens/{screen_id}/charts/{chart_id}/result?client_token={client token} +``` +Retrieved from each chart in your screen, endpoints look like the example displayed to the right. They always include the account id, screen id, chart id, and your client token. Note that Command screens are designed for public use and can be accessed without authentication. + +All of your requests should match this format. + + +### Parameters +```text +;date_ending=2018-02-21 +``` +Requests can be modified with two paramaters to adjust the date range or filter for specific terms. + +Append date_ending to adjust the ending date of your query. This will adjust the time window of your chart to finish at this day or time. + +```text +;terms=lexer +;terms=lexer%20OR%20data +``` + +Append terms to filter your saved dive even further. Here we're filtering for mentions of *Lexer OR Data*. Tip: it's easier to define this from your saved dive within Listen! + + +## Summary Metrics + +Here we'll describe the summary bar and live stream volume charts. + +### Summary Bar +```json +{ + "id": 18041857, + "updated_at": "2018-03-13T02:04:04Z", + "data": { + "mentions": 71200, + "sources": 3, + "authors": 47134, + "reach": 309297204, + "average_engagements": 1.5105868375 + } +} +``` + +The summary bar displays the headline metrics for your saved dive. Each of the individual big number charts (i.e. Matches, Authors) uses the same query and will return all of the results. + +- `mentions`: the total number of objects matching your query. + +- `sources`: where the content has come from i.e. Twitter. + +- `authors`: unique authors that have published this content. + +- `reach`: sum of the followers for each author. + +- `average_engagements`: mentions divided by authors. + +![Summary Bar](../images/content/summary_bar.png) + + +### Live Stream Volume +```json +{ + "id": 17633606, + "updated_at": "2018-02-22T03:14:51Z", + "data": { + "Nintendo": { + "data": { + "1519185600000": 1459, + "1519189200000": 1284, + "1519192800000": 1243, + "1519196400000": 1123, + "1519200000000": 1422, + "1519203600000": 1295, + "1519268400000": 364 + }, + "original": [...], + + "summary": { + "current": { + "mentions": 39564 + } + }, + "id": 5448, + "color": "#ed1941" + } + } +} +``` +The Live Stream Volume chart will return a data object for each filter presented in the chart. In this example we're just looking at the Nintendo filter. This object contains the corresponding count of mentions for each time interval. + +Also included in this response is the total number of mentions and various other information to render this in the chart interface. + +Our volume charts bucket counts into time intervals based on the period covered in the report. Here is a summary of the query ranges and corresponding time intervals returned. + +- `<2 days`: results are grouped into 1 hour intervals. + +- `2-3 days`: results are grouped into 3 hour intervals. + +- `7 days`: results are grouped into 12 hour intervals. + +- `8+ days`: results are grouped into 1 day intervals. + + +Note: all of our volume over time charts are returned using unix time. + +![Live Stream Chart](../images/content/livestreamvolume_chart.png) + +## Mentions + +Let's take a closer look at the mention objects that are displayed in the Recent Mentions, Influential Mentions, and Recent Media charts. Each of these charts returns the top 100 hits for the query, allowing you to recreate a display feed of content in your app. + +### Recent & Influential Mentions + +![Tweet Example](../images/content/mention_tweet_2.png) + +Here we'll review a Tweet from the @camplexer account. Let's take a closer look in the table below. Most of the data you need to recreate a mention is contained within the _data_ object. The _original_ object is what we receive from the source, and will give you access to the media content (image or video) attached to the object. We suggest referring to the Twitter, Facebook or Instagram API documentation for more on the structure of the results. + +```json +{ + "id": [...], + "data": { + "content": "Ahead of #eTailWest, we’ve launched our 2018 Data Culture Study. This annual study benchmarks the opportunities in customer data and the actions you can take to capitalize on them: http://lexer.link/2CccBM0 ⚡ https://t.co/BG1n6IpJka", + "geography": { + "accuracy": "guessed", + "code": "AU/VIC", + "point": { + "lat": -37.814107, + "lon": 144.96328 + } + }, + "mentions": { + "links": [ + "t.co/BG1n6IpJka", + "lexer.link/2CccBM0" + ], + "mentions": [], + "authors": [], + "author_ids": [] + }, + "terms": [ + "benchmarks", + "capitalize", + "opportunities", + "ahead", + "culture", + "actions", + "#etailwest", + "customer", + "annual", + "study", + "data", + "launched" + ], + "source": { + "name": "twitter.com", + "group": [], + "id": 102, + "type": [ + "image", + "link" + ] + }, + "author": { + "id": "twitter_219052087", + "fullname": "Lexer", + "username": "camplexer", + "link": "https://twitter.com/camplexer/", + "bio": "Put data to work to genuinely understand and engage customers.", + "avatar": "https://pbs.twimg.com/profile_images/595397359808356352/ULzphDZ__normal.png", + "influence": 0.506, + "reach": { + "inbound": 1081, + "outbound": 942 + } + }, + "engagements": { + "comments": 0, + "likes": 0, + "shares": 0 + }, + "engagement_count": 0, + "language": "en", + "link": "https://twitter.com/camplexer/statuses/967621409668177920", + "original": [...], + "id": "967621409668177920", + "published": "2018-02-25T04:44:56Z", + "processed": "2018-02-25T04:44:57Z", + "_id": "twitter_967621409668177920" + }, + "original": [...] +} +``` + +Property | Description | +---------|-------------| +content | Body of the message. +geography.accuracy | Supplied if specifically provided with the content. Guessed if inferred from the account settings. Uknown if no location data is provided. +geography.code | Country code provided for this location. +geography.point | Latitude and longitude points. +mentions.links | Array of links in the content. +mentions.mentions | Objects mentioned i.e. a retweet. +mentions.authors | Authors tagged in the content. +mentions.author_ids | IDs of the authors tagged in the content. +terms | Tokenized words extracted from the content. +source.name | Domain name for the source. +source.group | Facebook or Instagram account the content lives on. Empty for Twitter. +source.id | Numeric ID associated with the source type. See Sources > Source Types for more information. +source.type | Image, video, link, text. Image and video are mutually exclusive. An object may be type video,link or image,link. Text indicates no media or links. +author.id | Author ID appended with the network prefix. +author.fullname | Display name of the author. +author.username | Username of the author i.e Twitter handle. +author.link | URL to the author's account. +author.bio | Bio description for the author. +author.avatar | URL to the author's avatar image. +author.influence | Lexer calculated influence score. +author.reach.inbound | Count of users this account is following. +author.reach.outbound | Count of followers. +engagements | Unused. We do not collect engagement metrics on objects. +engagement_count | Unused. We do not collect engagement metrics on objects. +language | Language code in ISO 639-1 format. +id | Unused. +link | URL to the content. +published | Date and time this content was created. +processed | Date and time this content was processed in Lexer. +_id | Unused. + + +### Paging Results + +In order to return more than 100 matches, you can page through the results using the timestamp of the last object returned. Simply add the `date_ending` parameter to your next call using the `data.published` time (minus one second so as not to include the same object again) and you will return the next 100 matches. + +For example if the 100th object in our result has `"published": "2018-02-25T04:30:00Z",` then you would add `;date_ending=2018-02-25T04:39:99Z` to the end of your request. + + +## Terms +Let's take a closer look at how we analyse trending words used in the content matching our query. Here we have the Trending Terms and Terms Volume charts. It's important to note that we remove stop words before tokenizing content. + +### Trending Terms +```json +{ + "id": 18119110, + "updated_at": "2018-03-14T05:24:35Z", + "data": [ + { + "term": "nintendo", + "count": 59123 + }, + { + "term": "switch", + "count": 36034 + }, + { + "term": "#nintendo", + "count": 8014 + }, + {...} + ] +} +``` +Our trending terms table is the simplest way to return counts for terms appearing in your query. This endpoint will return the top 100 terms sorted by volume. + +![Terms Volume Chart](../images/content/terms_table.png) + +### Terms Volume +```json +{ + "id": 18119109, + "updated_at": "2018-03-14T16:17:58+11:00", + "data": { + "nintendo": { + "data": { + "1520859600000": 2131, + "1520863200000": 2536, + "1520866800000": 2562, + "1520870400000": 2626, + "1520874000000": 2568, + "1520942400000": 1988 + }, + "original": [...], + "summary": null + }, + "switch": {...}, + "#nintendo": {...}, + "smash": {...}, + "#nintendoswitch": {...}, + "retweet": {...}, + "enter": {...}, + "giveaway": {...}, + "super": {...}, + "join": {...} + } +} +``` +Here we're returning an object for each of the top 10 terms for this query. Remember that our time intervals are determined by the range of our query, as mentioned in the Summary section above. + +Note that you can ignore the data in the original section. + +![Terms Volume Chart](../images/content/terms_volume.png) + + +## Sources +Sources are the social networks or websites the content has come from. We categorise this content in different ways to help you dig deeper. Let's take a closer look at the Top Sources, Sources Volume, Source Types and Source Groups charts. + +### Top Sources +```json +{ + "id": 18041879, + "updated_at": "2018-03-14T05:45:18Z", + "data": [ + { + "term": "twitter.com", + "count": 61076 + }, + { + "term": "instagram.com", + "count": 2356 + }, + { + "term": "facebook.com", + "count": 357 + } + ] +} +``` +Our Top Sources chart provides you with a count of matches for each source. The `term` field refers to the source name, and the `count` field will provide the number of matches. + +![Top Sources](../images/content/source_top.png) + + + +





+ + +### Sources Volume +```json +{ + "id": 18148227, + "updated_at": "2018-03-14T05:45:18Z", + "data": { + "twitter.com": { + "data": { + "1520920800000": 2287, + "1520924400000": 2269, + "1520928000000": 1919, + "1520931600000": 2094, + "1520935200000": 2385, + "1521003600000": 1729 + }, + "original": [...], + "summary": null + }, + "instagram.com": {...}, + "original": [...], + "summary": null + }, + "facebook.com": {...}, + "original": [...], + "summary": null + } + } +} +``` +The Source Volume chart will return an object for each source in your result, and will break this into time intervals based on your query length. + +![Source Volume](../images/content/source_volume.png) + +In the chart above your result would return an object for twitter.com, instagram.com and facebook.com. These objects contain a key pair value for each date value and the corresponding volume. + +The original and summary values can be ignored for these results. + + +











+ + + +### Source Types +```json +{ + "id": 18041880, + "updated_at": "2018-03-14T05:45:18Z", + "data": [ + { + "term": 102, + "count": 61076 + }, + { + "term": 122, + "count": 2080 + }, + { + "term": 113, + "count": 327 + }, + { + "term": 123, + "count": 276 + }, + { + "term": 112, + "count": 30 + } + ] +} +``` +Source Types go further into breaking down the source results into their specific content type, for example posts vs comments vs private messages. + +![Source Types](../images/content/source_types.png) + +You will notice that we return numeric IDs for each of the sources. Below is a table you should store as reference for each of the source types in our platform. + +ID | Source Type +---------|-------------| +102 | Twitter Tweet +103 | Twitter Direct Message +112 | Facebook Post +113 | Facebook Comment +114 | Facebook Message +115 | Facebook Dark Post +116 | Facebook Dark Comment +117 | Facebook Review +118 | Facebook Review Comment +122 | Instagram Post +123 | Instagram Comment +132 | News/Blog Post (deprecated) +152 | News Article +153 | News comment +154 | Blog Post +155 | Blog Comment +156 | Forum Post +157 | Forum Comment + + +### Source Groups +```json +{ + "id": 18041881, + "updated_at": "2018-03-14T05:51:04Z", + "data": [ + { + "term": "Nintendo", + "count": 82 + }, + { + "term": "ign", + "count": 66 + }, + { + "term": "rudy.splatoon2", + "count": 45 + }, + { + "term": "UNILADGaming", + "count": 38 + }, + ] +} +``` +Source groups are used for Facebook and Instagram to query or analyse content that exists on a specific page. For example, if we were to ask for all content on the source group "camplexer" we return all posts, comments and messages on this page. + +This endpoint will return the top 100 source groups for your query. + +![Source Groups](../images/content/source_groups.png) + +## Authors +Authors are the creators of the content matching your query. You can return these authors sorted by influence (follower count) or by engagement (count of objects). We also include the ability to return the top engaged authors in a time series format. + +Both of the tables below will return the top 100 authors based on the sorting that is being applied. Each author returned will provide the following details. + +```json +{ + "data": { + "term": "twitter_1317671", + "count": 17, + "total": 447828.0 + }, + "original": { + "id": "twitter_1317671", + "fullname": "My Nintendo News", + "lexer_id": "", + "username": "MyNintendoNews", + "link": "https://twitter.com/MyNintendoNews/", + "bio": "The most popular Nintendo news Twitter account. Tracking the hottest Nintendo news 24/7 #NintendoSwitch", + "avatar": "https://pbs.twimg.com/profile_images/976439872117510144/p2eEG3Ts_normal.jpg", + "influence": 1.266, + "reach": { + "inbound": 536, + "outbound": 447818 + } + } + }, +``` + +Property | Description | +---------|-------------| +data.term | Lexer internal author id +data.count | Volume of objects created by this author +data.total | Total number of followers +original.id | Lexer internal author id +original.fullname | Display name for this author +original.username | Username or handle of the author +original.link | URL to the author's bio +original.bio | Description from the author's account +original.avatar | URL to the author's bio +original.influence | Lexer internal influence score +original.inbound | Count of following +original.outbound | Count of followers + +### Influential Authors + +![Influential Authors](../images/content/authors_influential_2.png) + +### Authors Volume +```json +{ + "id": 18148228, + "updated_at": "2018-04-26T03:46:23Z", + "data": { + "MyNintendoNews": { + "data": { + "1524628800000": 0, + "1524632400000": 71, + "1524636000000": 0, + "1524639600000": 0, + "1524643200000": 0, + "1524646800000": 0, + "1524650400000": 0, + "1524654000000": 74, + "1524657600000": 0, + "1524661200000": 0, + "1524664800000": 0, + "1524668400000": 0, + "1524672000000": 67, + "1524675600000": 0, + "1524679200000": 0, + "1524682800000": 0, + "1524686400000": 0, + "1524690000000": 68, + "1524693600000": 0, + "1524697200000": 0, + "1524700800000": 0, + "1524704400000": 0, + "1524708000000": 0, + "1524711600000": 0 + }, + "original": [...], + "summary": null, + "author_name": "MyNintendoNews" + }, +``` + +You can also return the top authors in a time series format. Here we return a data object for the top 10 authors based on their volume of content matching your query. Similar to other timeseries results, there is a key pair value for the time and count of mentions. + + +![Top Authors Volume](../images/content/authors_volume.png) + + +## Locations +```json +{ + "id": 18042000, + "updated_at": "2018-04-04T00:01:45Z", + "data": [ + { + "term": "US/CA", + "count": 4950 + }, + { + "term": "US/VA", + "count": 1618 + }, + { + "term": "JP", + "count": 1507 + }, + ] +} +``` +Many authors of the content matching your query will have associated location information. Here we're analysing (when available) the author location for your search. These locations may be at either the state or country level, depending on the location and source of data. + +In this result the term is referring to the location code. + +![Top Locations](../images/content/locations.png) + + + +## Classifications +```json +{ + "id": 18041988, + "updated_at": "2018-04-03T23:56:09Z", + "data": [ + { + "id": 2392, + "term": "customer service", + "count": 2004 + }, + { + "id": 2390, + "term": "negative sentiment", + "count": 2001 + }, + { + "id": 465, + "term": "product related", + "count": 2000 + }, + ] +} +``` + +Classifications are custom tags that your team can apply to content. These are typically included in the customer service workflow within Engage. You can then report on the volumes for each classification that match your query. Here we're simply returning the counts for each classification that matches your saved dive. + + +Field | Definition +---------|-------------| +id | Unique id for this classification +term | Name of the classification +count | Count of objects that have this classification applied + +![Top Classifications](../images/content/classifications.png) diff --git a/source/includes/_errors.md b/source/includes/_errors.md deleted file mode 100644 index 56cffb34d22..00000000000 --- a/source/includes/_errors.md +++ /dev/null @@ -1,20 +0,0 @@ -# Errors - - - -The Kittn API uses the following error codes: - - -Error Code | Meaning ----------- | ------- -400 | Bad Request -- Your request sucks -401 | Unauthorized -- Your API key is wrong -403 | Forbidden -- The kitten requested is hidden for administrators only -404 | Not Found -- The specified kitten could not be found -405 | Method Not Allowed -- You tried to access a kitten with an invalid method -406 | Not Acceptable -- You requested a format that isn't json -410 | Gone -- The kitten requested has been removed from our servers -418 | I'm a teapot -429 | Too Many Requests -- You're requesting too many kittens! Slow down! -500 | Internal Server Error -- We had a problem with our server. Try again later. -503 | Service Unavailable -- We're temporarially offline for maintanance. Please try again later. diff --git a/source/includes/_events.md b/source/includes/_events.md new file mode 100644 index 00000000000..e8d69de15d9 --- /dev/null +++ b/source/includes/_events.md @@ -0,0 +1,5 @@ +# Events API + +TODO - Write Events API documentation + +cURL + Ruby Gem diff --git a/source/includes/_identities.md b/source/includes/_identities.md new file mode 100644 index 00000000000..c4cb3e86730 --- /dev/null +++ b/source/includes/_identities.md @@ -0,0 +1,444 @@ +# Identity + +The Lexer Identity API allows clients and their partners to read and write Identity information to [Lexer Identify](http://lexer.io). + +For details on the capability and project specific implementation of [Lexer Identify](http://lexer.io) please contact support at [support@lexer.io](mailto:support@lexer.io). + +Within the Lexer Identify platform an Identity is a person, brand, place or thing. +Each Identity has thousands of attributes which are generated and updated in real-time through the Lexer Identify platform. + +Each Identity is made up of: + +- **Links**: Unique, personally identifiable attributes including Email addresses, their Mobile number, Twitter handle, Facebook ID, etc. +- **Attributes**: An identity could contain thousands of attributes - each one defining their behaviour, facts and engagements, for example: `age`, `gender`, `favourite food`, `spouse`, etc. + +Clients can use the Lexer Identify platform to gather real-time insights on their customers, prospects and competitors by: + +1. Linking their proprietary data with one or more identities. +2. Contributing additional information to enrich the identity. +3. Consume an identities attributes into internal or 3rd party platforms for activation. + +All this is done within the Identity API. + +## Configuration + + +### Authentication + +```shell +# Tokens are used as part of the JSON request body + +curl https://identity.api.lexer.io/ \ + -XPOST \ + -H "Content-Type: application/json" \ + -d ' +{ + "api_token": "lexer-api-token", + "consumer_token": "lexer-consumer-token", + "contributor_token": "lexer-contrib-token" +}' +``` + +```ruby +require 'lexer' + +Lexer::Identity.configure do |config| + config.api_token = 'lexer-api-token' + config.contributor_token = 'lexer-contrib-token' + config.consumer_token = 'lexer-consumer-token' +end +``` + +> Make sure to replace the tokens with those provided. + +To access any Lexer API you will require access tokens which will be provided to you. Please [contact support](mailto:support@lexer.io) if you have not received these as part of your projects documentation. + +There are at least two of three possible tokens which you will need to communicate with the APIs: + +* **API Token + Consumer Token**: Read only access to Lexer APIs +* **API + Contributor Tokens**: Write only access to Lexer APIs +* **API + Consumer + Contributor Tokens**: Read _and_ Write access to Lexer APIs + + + + +## API Token + +All requests require an _API token_ which will be provided to each party who require access to the Lexer APIs. + +An _API token_ alone offers no access to the Lexer APIs. You need at least a _Consumer token_ or _Contributor token_ to make a valid request. Both a _Consumer token_ and _Contributor token_ can be provided in a single request payload for simultaneous read/write access. + +## Consumer Token + +A _Consumer token_ is supplied if the party requires **read** access to the Lexer APIs. + +When created, a _Consumer token_ is locked to a specific [namespace](#namespaces) only granting that token access to a specific dataset. + +A _Consumer token_ does not allow a party to **write** data to a Lexer APIs. For that a _Contributor token_ is required. + +## Contributor Token + +A _Contributor token_ is supplied if the party requires **write** access to the Lexer APIs. + +When created, a _Contributor token_ is locked to a specific [namespace](#namespaces) only granting that token access to a specific dataset. + + + +### Endpoints + +```text +https://identity.api.lexer.io/ +``` + +All access to the Lexer Identity API is performed via a single root endpoint. The correct behaviour of the API is determined by various input payload contexts. + +All input must be sent via `POST` in JSON format. + + +### Payload + +```json +{ + "api_token": "abc-123-...", + "consumer_token": "qwe-345-...", + "contributor_token": "ert-678-...", + "id": "987-mnb-...", + "links": { + "email": "joe.blog@mybrand.com", + "mobile": "+61404000000" + }, + "attributes": { + "com.mybrand.age": {...}, + "com.mybrand.car.color": {...} + } +} +``` + +All input must be sent via `POST` in JSON format to the [ROOT endpoint](#root-endpoint) and must contain the following keys: + +Key | Required | Description +----- | --- | ---- +api_token | Yes | The api token as provided by Lexer. +consumer_token | No | The consumer token as provided by Lexer. +contributor_token | No | The contributor token as provided by Lexer. +id | No | A Lexer ID if one is known. Is used over `links` if provided. +links | No | A key-value object of [linkage attributes](#links) unique to the Identity - only required if an `id` is not present. +attributes | No | An object of [attributes](#attributes) to be written to the Identity - only required if a `contributor_token` is present. + + +### Tokens + +```shell +curl https://identity.api.lexer.io/ \ + -XPOST \ + -H "Content-Type: application/json" \ + -d ' +{ + "api_token": "your-api-token", + "consumer_token": "your-consumer-token", + "contributor_token": "your-contrib-token" +}' +``` + +```ruby +Lexer::Identity.configure do |config| + config.api_token = 'lexer-api-token' + config.contributor_token = 'lexer-contrib-token' + config.consumer_token = 'lexer-consumer-token' +end +``` + +As outlined in [Access Tokens](#access-tokens) a set of tokens are required for all communication with the API. +An API token along with a Contributor and/or a Consumer token is required. + +You can validate your tokens by making a `curl` request to the API. A `403 Forbidden` will be returned if your tokens are invalid. + +Contact [support@lexer.io](mailto:support@lexer.io) if you require assistance. + + +## Namespaces + +Each _Consumer Token_ and _Contributor Token_ is bound to a particular namespace. + +A namespace is commonly defined as a reverse domain name. Such as `io.lexer`. + +Namespaces are used within the platform to: + +1. **Protect Secure Information**: Tokens can only read from defined namespaces, limiting each party's access to only the attributes permitted. +2. **Enforce Business Policy**: Our clients often have many partners with a complex permission tree. Using namespaces we’re able to allow certain partners to access certain attributes. + +Each attribute on an Identity has a name within the namespace. For example: + +- `io.lexer.age` defines the age of the Identity according to Lexer +- `com.mybrand.age` defines the age of the Identity according to MyBrand +- `com.mybrand.car.colour` defines the colour of the Identities car according to MyBrand + +Please refer to the project's documentation on available namespaces for your implementation. + +## Links + +```json +{ + "links": { + "email": ["joe.blog@mybrand.com", "joeblog1983@gmail.com"], + "mobile": "+61404000000", + "twitter": 1234567890, + "facebook": 2345678901, + "instagram": [3456789012, 4567890123], + "com.mybrand.customer_id": 9876543210, + "com.mybrand.loyalty_id": 6789054321 + }, + "attributes": {} +} +``` + +Internally the Lexer Identify platform uses links as a lookup for unique identities. They are also used to unify records across a Client's systems, partner networks and Lexer's public data sources. + +In each case the link must be globally unique - meaning the link must belong to just one identity. +An example of this is a mobile number, which in almost every case belongs to just one person, however an email may belong to more than one person - such as an email address provided by an ISP. + +If a link is provided to Lexer which belongs to multiple Identities an [error](#errors) will be returned. + +Currently, Lexer supports the following predefined links: + +- `email`: the email address of the identity +- `mobile`: the mobile phone number of the identity - written in international format with no spaces i.e. +61404000000 +- `twitter`: the Twitter id (not handle) of the identity +- `facebook`: the Facebook id (not username) of the identity +- `instagram`: the Instagram id (not username) of the identity + +We also allow clients and partners to write their own identifiers to an identity using the namespaces provided. + +This allows you to provide your own shared IDs for distribution through the Identify platform. +Common cases include an internal _customer id_, _device IDs_, _loyalty membership number_, etc. + +These links should be named using the following formula `.` i.e. `com.mybrand.customer_id`. + +If multiple link values exist for a single identity (i.e. they have more than one email address) then simply provide the multiple values as an array. + +## Attributes + +```json +{ + "links": {}, + "attributes": { + "com.mybrand.product.names": { + "value": ["iphone", "ipad"], + "confidence": 2 + }, + "com.mybrand.product.versions": { + "value": ["iphone 6+", "ipad air 2"], + "confidence": 2 + }, + "com.mybrand.customer_since": { + "value": "2013-01-07T18:43:21Z", + "confidence": 2 + }, + "com.mybrand.annual_spend": { + "value": 2000.00, + "confidence": 1 + }, + "com.mybrand.churn_risk": { + "value": "low", + "confidence": 0 + } + } +} +``` + +An identity is made up of thousands of attributes defined by Lexer, our clients and partners. + +When a contribution is made the changes become available to the client and their partners according to the [namespace](#namespaces) policies defined. + +An attribute is defined by a: + +Property | Description | +---------|-------------| +name | The name of an attribute. Prefixed by the designated [namespace](#namespaces) +value | The value of the attribute. A range of data types are allowed +confidence | The confidence score given by the contributor + +### Name + +An attribute name must be created following the formula `.` i.e. `com.mybrand.products`. + +When selecting a name for an attribute rely on the following guidelines: + +* A name should only contain `A-Za-z0-9._` characters +* Should answer the question `What is Sarah's ?` or `What are Sarah's `. i.e. `What is Sarah's age?` or `What are Sarah's upcoming trips?` + + + +Any contributions to attributes with names that conflict with the [namespace](#namespaces) policy will be rejected. + + +### Values + +The API supports any values supported by the [JSON](http://json.org/) specification: + +* Strings: `"hello world"` +* Numbers: `123.45` +* Objects: `{"make": "Tesla", "model": "S"}` +* Arrays: `["hello", "world", 123.45, {"make": "Tesla"}]` + +If you wish to merge existing attribute values with a new value; for example the contents of an `array` or `object`; then you must first consume from the API and manage the merge yourself. + + + +### Confidence + +```ruby +# The following are the Ruby constants you should use +# to specify attribute confidence +Lexer::Identity::CONFIDENCE_INFERRED +Lexer::Identity::CONFIDENCE_CALCULATED +Lexer::Identity::CONFIDENCE_PROVIDED +``` + +Each attribute on an identity has a confidence score which is a constant defined by Lexer to help all clients understand the accuracy of the source or method of inference. + +Score |Description +------|----------- +0 |Attribute is of low confidence - the value is most likely generated using aggregate data. +1 |Attribute has been calculated using one or more other attributes using a validated function or equation. +2 |Value is provided via customer or business data. Is considered factual. + + +## Contributions + +```shell +curl https://identity.api.lexer.io/ \ + -XPOST \ + -H "Content-Type: application/json" \ + -d ' +{ + "api_token": "your-api-token", + "contributor_token": "your-contrib-token", + "links": { + "email": "joe.blog@mybrand.com", + "mobile": "+61404000000" + }, + "attributes": { + "com.mybrand.age": { + "value": 32, + "confidence": 2 + } + } +}' + +# Result +# {"id": "862d10d5..."} +``` + +```ruby +Lexer::Identity.configure do |config| + config.api_token = 'lexer-api-token' + config.contributor_token = 'lexer-contrib-token' +end + +links = { + email: 'joe.blog@mybrand.com', + mobile: '+61404000000', +} + +attributes = { + 'com.mybrand.age': { + value: 32, + confidence: Lexer::Identity::CONFIDENCE_PROVIDED + } +} + +identity = Lexer::Identity.enrich(links: links, attributes: attributes) +# + +identity.id +# 862d10d5... + +identity.attributes +# nil +``` + +A contribution is the process of writing links and/or attributes to an new or existing identity. + +The presence of a valid `contributor_token` in the input payload instructs the API to create or update a unique identity. Generally, two or more links, must be provided in order for an identity to be created. + +Unless a consumer token is provided only a Lexer ID will be returned upon a successful contribution to the API, otherwise an [error](#status-codes) will be returned. + +## Consumption + +```shell +curl https://identity.api.lexer.io/ \ + -XPOST \ + -H "Content-Type: application/json" \ + -d ' +{ + "api_token": "your-api-token", + "consumer_token": "your-consumer-token", + "links": { + "email": "joe.blog@mybrand.com", + "mobile": "+61404000000" + } +}' + +# Result +# {"id": "862d10d5...", "attributes": {"com.mybrand.age": {"value": [32], "confidence": 2, "updated_at":"2015-06-23T11:51:16Z"}}} +``` + +```ruby +Lexer::Identity.configure do |config| + config.api_token = 'lexer-api-token' + config.consumer_token = 'lexer-consumer-token' +end + +links = { + email: "joe.blog@mybrand.com", + mobile: "+61404000000", +} + +identity = Lexer::Identity.enrich(links: links) +# {...}}> + +identity.id +# 862d10d5... + +identity.attributes +# {"com.mybrand.age"=>{"value"=>[32], "confidence"=>2, "updated_at"=>"2015-06-23T11:56:26Z"}} +``` + +A consumption is the process of reading attributes from an existing identity. + +The presence of a valid `consumer_token` in the input payload instructs the API to return all attributes made available to the requester via the namespace policies defined on the account. + +A `consumer_token` can be paired with a `contributor_token` which will result in a write then read procedure on the matched identity. + + +## Status Codes + +```json +{"error": "403 Forbidden"} +``` + +HTTP status codes are returned to indicate the success or failure of a request. In addition, error messages are returned via a JSON object response. + +HTTP Status | Description +------------|-------------- +200 OK|An existing Identity was found and returned. +201 Created|A new Identity has been created. A Lexer ID will be returned. +400 Bad Request|The payload contained invalid data. +403 Forbidden|Your request has been denied due to an invalid/missing `api_token` and or `contributor_token`/`consumer_token`. +404 Not Found|The Lexer ID provided alongside a `consumer_token` was not found. +406 Not Acceptable|There were not enough valid `links` provided alongside a `contributor_token` for an Identity to be created. +500 Internal Server Error|An internal server error occurred. + diff --git a/source/includes/_publish.md b/source/includes/_publish.md new file mode 100644 index 00000000000..d9c856c2375 --- /dev/null +++ b/source/includes/_publish.md @@ -0,0 +1,5 @@ +# Publish API + +TODO - Write Publish API documentation + +cURL + Ruby Gem diff --git a/source/index.md b/source/index.md index ed5f6d63d0e..bde5c77f250 100644 --- a/source/index.md +++ b/source/index.md @@ -1,168 +1,49 @@ --- -title: API Reference +title: Lexer - Developers language_tabs: - shell - ruby - - python toc_footers: - - Sign Up for a Developer Key - - Documentation Powered by Slate + - Find out more about Lexer + - (Docs Powered by Slate) includes: - - errors + - content + - activity + - chatbot + - identities search: true --- # Introduction -Welcome to the Kittn API! You can use our API to access Kittn API endpoints, which can get information on various cats, kittens, and breeds in our database. +Welcome to the Lexer API documentation. -We have language bindings in Shell, Ruby, and Python! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right. +We currently offer the following APIs to our clients: -This example API documentation page was created with [Slate](http://github.com/tripit/slate). Feel free to edit it and use it as a base for your own API's documentation. +- **Content**: read social and news content. -# Authentication +- **Activity**: read customer service team performance metrics. -> To authorize, use this code: +- **Chatbot**: integrate your chatbot into Engage. -```ruby -require 'kittn' +- **Identity**: read and write Identity data. -api = Kittn::APIClient.authorize!('meowmeowmeow') -``` +All of our APIs communicate via HTTPS and JSON data. -```python -import kittn -api = kittn.authorize('meowmeowmeow') -``` +## Fair Use -```shell -# With shell, you can just pass the correct header with each request -curl "api_endpoint_here" - -H "Authorization: meowmeowmeow" -``` +Lexer operates a fair use policy on all of its APIs. -> Make sure to replace `meowmeowmeow` with your API key. +Refer to your project's terms of service for details on rate limiting, performance limitations, maintenance windows and SLAs. -Kittn uses API keys to allow access to the API. You can register a new Kittn API key at our [developer portal](http://example.com/developers). +## Support -Kittn expects for the API key to be included in all API requests to the server in a header that looks like the following: +Our team are here to help you build an integration with any of our products, so please don't hesitate to reach out! Get in contact via live chat within the Hub or [email](mailto:support@lexer.io). -`Authorization: meowmeowmeow` - - -# Kittens - -## Get All Kittens - -```ruby -require 'kittn' - -api = Kittn::APIClient.authorize!('meowmeowmeow') -api.kittens.get -``` - -```python -import kittn - -api = kittn.authorize('meowmeowmeow') -api.kittens.get() -``` - -```shell -curl "http://example.com/api/kittens" - -H "Authorization: meowmeowmeow" -``` - -> The above command returns JSON structured like this: - -```json -[ - { - "id": 1, - "name": "Fluffums", - "breed": "calico", - "fluffiness": 6, - "cuteness": 7 - }, - { - "id": 2, - "name": "Isis", - "breed": "unknown", - "fluffiness": 5, - "cuteness": 10 - } -] -``` - -This endpoint retrieves all kittens. - -### HTTP Request - -`GET http://example.com/kittens` - -### Query Parameters - -Parameter | Default | Description ---------- | ------- | ----------- -include_cats | false | If set to true, the result will also include cats. -available | true | If set to false, the result will include kittens that have already been adopted. - - - -## Get a Specific Kitten - -```ruby -require 'kittn' - -api = Kittn::APIClient.authorize!('meowmeowmeow') -api.kittens.get(2) -``` - -```python -import kittn - -api = kittn.authorize('meowmeowmeow') -api.kittens.get(2) -``` - -```shell -curl "http://example.com/api/kittens/3" - -H "Authorization: meowmeowmeow" -``` - -> The above command returns JSON structured like this: - -```json -{ - "id": 2, - "name": "Isis", - "breed": "unknown", - "fluffiness": 5, - "cuteness": 10 -} -``` - -This endpoint retrieves a specific kitten. - - - -### HTTP Request - -`GET http://example.com/kittens/` - -### URL Parameters - -Parameter | Description ---------- | ----------- -ID | The ID of the cat to retrieve diff --git a/source/layouts/layout.erb b/source/layouts/layout.erb index 36ae0f95f81..871ba55b3ec 100644 --- a/source/layouts/layout.erb +++ b/source/layouts/layout.erb @@ -13,6 +13,7 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. %> +<%= favicon_tag 'images/favicon.png' %> <% language_tabs = current_page.data.language_tabs %> diff --git a/source/stylesheets/_normalize.css b/source/stylesheets/_normalize.css index 46f646a5c00..1bce3459e60 100644 --- a/source/stylesheets/_normalize.css +++ b/source/stylesheets/_normalize.css @@ -417,6 +417,7 @@ optgroup { */ table { + font-size: 14px; border-collapse: collapse; border-spacing: 0; } diff --git a/source/stylesheets/_variables.scss b/source/stylesheets/_variables.scss index 4c9bae05ee1..184c80c87c9 100644 --- a/source/stylesheets/_variables.scss +++ b/source/stylesheets/_variables.scss @@ -23,31 +23,32 @@ under the License. // BACKGROUND COLORS //////////////////// -$nav-bg: #393939; -$examples-bg: #393939; -$code-bg: #292929; -$code-annotation-bg: #1c1c1c; -$nav-subitem-bg: #262626; -$nav-active-bg: #2467af; -$lang-select-border: #000; -$lang-select-bg: #222; -$lang-select-active-bg: $examples-bg; // feel free to change this to blue or something -$lang-select-pressed-bg: #111; // color of language tab bg when mouse is pressed -$main-bg: #eaf2f6; -$aside-notice-bg: #8fbcd4; -$aside-warning-bg: #c97a7e; -$aside-success-bg: #6ac174; -$search-notice-bg: #c97a7e; +$nav-bg: #333; // #333333; +$examples-bg: #333; // #393939; +$code-bg: #444; // #292929; +$code-annotation-bg: #F2F7F7; // #1c1c1c; +$nav-subitem-bg: #444; // #262626; +$nav-active-bg: #00b3b7; // #00b3b7; +$lang-select-border: #333; // #000; +$lang-select-bg: #222; // #cccccc; +$lang-select-active-bg: #333; // $examples-bg; +$lang-select-pressed-bg: #333; // #111; +$main-bg: #fff; // #eeeeee; +$block-border: #CDD4D3; +$aside-notice-bg: #F2F7F7; // #8fbcd4; +$aside-warning-bg: #0ff; // #c97a7e; +$aside-success-bg: #fff; // #6ac174; +$search-notice-bg: #fff; // #c97a7e; // TEXT COLORS //////////////////// -$main-text: #333; // main content text color -$nav-text: #fff; -$nav-active-text: #fff; -$lang-select-text: #fff; // color of unselected language tab text -$lang-select-active-text: #fff; // color of selected language tab text -$lang-select-pressed-text: #fff; // color of language tab text when mouse is pressed +$main-text: #333; // #333; // main content text color +$nav-text: #fff; // #fff; +$nav-active-text: #fff; // #fff; +$lang-select-text: #fff; // #fff; // color of unselected language tab text +$lang-select-active-text: #fff; // #fff; // color of selected language tab text +$lang-select-pressed-text: #fff; // #fff; // color of language tab text when mouse is pressed // SIZES @@ -60,7 +61,7 @@ $nav-padding: 15px; // padding to left and right of navbar $nav-v-padding: 10px; // padding used vertically around search boxes and results $nav-indent: 10px; // extra padding for ToC subitems $code-annotation-padding: 13px; // padding inside code annotations -$h1-margin-bottom: 21px; // padding under the largest header tags +$h1-margin-bottom: 10px; // padding under the largest header tags $tablet-width: 930px; // min width before reverting to tablet size $phone-width: $tablet-width - $nav-width; // min width before reverting to mobile size @@ -68,13 +69,13 @@ $phone-width: $tablet-width - $nav-width; // min width before reverting to mobil // FONTS //////////////////// %default-font { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: Verdana, Arial, sans-serif; font-size: 13px; } %header-font { @extend %default-font; - font-weight: bold; + font-weight: normal; } %code-font { @@ -86,11 +87,11 @@ $phone-width: $tablet-width - $nav-width; // min width before reverting to mobil // OTHER //////////////////// -$nav-active-shadow: #000; -$nav-footer-border-color: #666; -$nav-embossed-border-top: #000; -$nav-embossed-border-bottom: #939393; -$main-embossed-text-shadow: 0px 1px 0px #fff; +$nav-active-shadow: none; +$nav-footer-border-color: none; +$nav-embossed-border-top: none; +$nav-embossed-border-bottom: none; +$main-embossed-text-shadow: none; $search-box-border-color: #666; diff --git a/source/stylesheets/screen.css.scss b/source/stylesheets/screen.css.scss index d64b3239574..d1a6e1361b5 100644 --- a/source/stylesheets/screen.css.scss +++ b/source/stylesheets/screen.css.scss @@ -48,23 +48,23 @@ html, body { width: 20px; } -@mixin embossed-bg { - @include background( - linear-gradient(top, - rgba(#000, 0.2), - rgba(#000, 0) 8px), - linear-gradient(bottom, - rgba(#000, 0.2), - rgba(#000, 0) 8px), - linear-gradient(top, - rgba($nav-embossed-border-top, 1), - rgba($nav-embossed-border-top, 0) 1.5px), - linear-gradient(bottom, - rgba($nav-embossed-border-bottom, 1), - rgba($nav-embossed-border-bottom, 0) 1.5px), - $nav-subitem-bg - ); -} +// @mixin embossed-bg { +// @include background( +// linear-gradient(top, +// rgba(#000, 0.2), +// rgba(#000, 0) 8px), +// linear-gradient(bottom, +// rgba(#000, 0.2), +// rgba(#000, 0) 8px), +// linear-gradient(top, +// rgba($nav-embossed-border-top, 1), +// rgba($nav-embossed-border-top, 0) 1.5px), +// linear-gradient(bottom, +// rgba($nav-embossed-border-bottom, 1), +// rgba($nav-embossed-border-bottom, 0) 1.5px), +// $nav-subitem-bg +// ); +// } .tocify-wrapper { @include transition(left ease-in-out 0.3s); @@ -78,7 +78,7 @@ html, body { width: $nav-width; background-color: $nav-bg; font-size: 13px; - font-weight: bold; + // font-weight: bold; // language selector for mobile devices .lang-selector { @@ -137,7 +137,7 @@ html, body { margin-bottom: 1em; } - @include embossed-bg; + // @include embossed-bg; li { margin: 1em $nav-padding; @@ -199,7 +199,7 @@ html, body { } // for embossed look: - @include embossed-bg; + // @include embossed-bg; &>li:last-child { box-shadow: none; // otherwise it'll overflow out of the subheader } @@ -208,7 +208,7 @@ html, body { .toc-footer { padding: 1em 0; margin-top: 1em; - border-top: 1px dashed $nav-footer-border-color; + border: none; li,a { color: $nav-text; @@ -247,7 +247,7 @@ html, body { z-index: 100; color: #000; text-decoration: none; - font-weight: bold; + // font-weight: bold; opacity: 0.7; line-height: 16px; img { @@ -299,7 +299,7 @@ html, body { .lang-selector { background-color: $lang-select-bg; width: 100%; - font-weight: bold; + // font-weight: bold; a { display: block; float:left; @@ -336,6 +336,8 @@ html, body { // to place content above the dark box position: relative; z-index: 30; + + padding-bottom: 100px; &:after { content: ''; @@ -357,6 +359,12 @@ html, body { padding-left: $main-padding + 15px; } + &>p>a, td>a { + color: #000; + text-decoration: none; + border-bottom: 1px solid #00b3b7; + } + // the div is the tocify hidden div for placeholding stuff &>h1, &>h2, &>div { clear:both; @@ -365,15 +373,13 @@ html, body { h1 { @extend %header-font; font-size: 30px; - padding-top: 0.5em; - padding-bottom: 0.5em; - border-bottom: 1px solid #ccc; + margin-bottom: $h1-margin-bottom; - margin-top: 2em; - border-top: 1px solid #ddd; - @include background-image( - linear-gradient(top, #fff, #f9f9f9) - ); + margin-top: $h1-margin-bottom * 6; + + padding-bottom: $h1-margin-bottom; + + border-bottom: 1px solid $block-border; } h1:first-child, div:first-child + h1 { @@ -384,14 +390,13 @@ html, body { h2 { @extend %header-font; font-size: 20px; - margin-top: 4em; - margin-bottom: 0; - border-top: 1px solid #ccc; - padding-top: 1.2em; - padding-bottom: 1.2em; - @include background-image( - linear-gradient(top, rgba(#fff,0.4), rgba(#fff, 0)) - ); + + margin-top: $h1-margin-bottom * 4; + margin-bottom: $h1-margin-bottom / 2; + + padding-bottom: $h1-margin-bottom / 2; + + border-bottom: 1px solid $block-border; } // h2s right after h1s should bump right up @@ -403,10 +408,11 @@ html, body { h3, h4, h5, h6 { @extend %header-font; - font-size: 12px; + font-size: 13px; + font-weight: bold; margin-top: 2.5em; margin-bottom: 0.8em; - text-transform: uppercase; + // text-transform: uppercase; } h4, h5, h6 { @@ -452,7 +458,7 @@ html, body { } dt { - font-weight: bold; + // font-weight: bold; } dd { @@ -470,7 +476,7 @@ html, body { code { background-color: rgba(0,0,0,0.05); - padding: 3px; + padding: 3px 6px; border-radius: 3px; @extend %break-words; @extend %code-font; @@ -484,20 +490,22 @@ html, body { aside { padding-top: 1em; padding-bottom: 1em; - @include text-shadow(0 1px 0 lighten($aside-notice-bg, 15%)); + margin-top: 1.5em; margin-bottom: 1.5em; + background: $aside-notice-bg; + border-top: 1px solid $block-border; + border-bottom: 1px solid $block-border; + line-height: 1.6; &.warning { background-color: $aside-warning-bg; - @include text-shadow(0 1px 0 lighten($aside-warning-bg, 15%)); } &.success { background-color: $aside-success-bg; - @include text-shadow(0 1px 0 lighten($aside-success-bg, 15%)); } } @@ -547,7 +555,7 @@ html, body { clear:right; @include box-sizing(border-box); - @include text-shadow(0px 1px 2px rgba(0,0,0,0.4)); + // @include text-shadow(0px 1px 2px rgba(0,0,0,0.4)); @extend %right-col; @@ -556,7 +564,7 @@ html, body { a { color: #fff; text-decoration: none; - border-bottom: dashed 1px #ccc; + border-bottom: solid 1px #ccc; } } @@ -567,11 +575,11 @@ html, body { blockquote { &>p { background-color: $code-annotation-bg; - border-radius: 5px; + border-radius: 3px; padding: $code-annotation-padding; - color: #ccc; - border-top: 1px solid #000; - border-bottom: 1px solid #404040; + color: $main-text; + // border-top: 1px solid #000; + // border-bottom: 1px solid #404040; } } }