KB Articles

Your knowledge base is accessible via the regular API, as well as through a special jsonp action so you can request and embed articles directly into your HTML.

Articles Listing

> curl -H "Accept: application/vnd.tender-v1+json" "https://USER:PASS@api.tenderapp.com/foosupport/faqs"
{
  "offset": 0,
  "total": 3,
  "per_page": 30,
  "faqs": [
    {Article}, {Article}, etc
  ]
}

Search articles

> curl -H "Accept: application/vnd.tender-v1+json" "https://USER:PASS@api.tenderapp.com/foosupport/faqs/search?query=monkeys"
{
  "offset": 0,
  "total": 3,
  "per_page": 30,
  "faqs": [
    {Article}, {Article}, etc
  ]
}

Articles from a specific section

> curl -H "Accept: application/vnd.tender-v1+json" "https://USER:PASS@api.tenderapp.com/help/faqs?section_id=1234"
{
  "offset": 0,
  "total": 3,
  "per_page": 30,
  "faqs": [
    {Article}, {Article}, etc
  ]
}
  • section_id: The ID of the section in which to filter articles by

Single Article

> curl -H "Accept: application/vnd.tender-v1+json" "https://USER:PASS@api.tenderapp.com/help/faqs/12345"
{
  "title": "Tender + Lighthouse discount",
  "permalink": "tender-lighthouse-discount",
  "keywords": "lighthouse discount",
  "body": "Stuff",
  "formatted_body": "<div><p>Stuff</p></div>",
  "html_href": "https://help.tenderapp.com/kb/discounts/tender-lighthouse-discount",
  "href": "https://api.tenderapp.com/help/faqs/6388",
  "section_href": "https://api.tenderapp.com/help/sections/2188",
  "published_at": "2038-01-01T08:00:00Z", # date in the future means this is a DRAFT
  "updated_at": "2009-12-03T00:28:58Z",
  "created_at": "2009-12-03T00:28:15Z"
}

Attributes

  • title - the name of the KB article.
  • permalink - the name used in article URLs. This is auto-generated from the name if not already provided.
  • keywords - The autosuggest keywords for this article.
  • body - The body content for the article.
  • formatted_body (readonly) - The HTML formatted body content.
  • html_href - Web URL for the article.
  • href - API URL for the article.
  • section_href (readonly) - API URL for the section.

Creating an article

You can POST to the faqs action to create a new KB article. Only support users can modify articles. If no published_at is given, the article is left in a draft state.

> curl -H "Accept: application/vnd.tender-v1+json" \
  -H "Content-Type: application/json" \
  -d '{"title":"MY TITLE", "keywords":"abc", "body":"MY BODY","published_at":"2010-01-01T08:00:00Z"}'
  "https://EMAIL:PASS@api.tenderapp.com/help/sections/:section_id/faqs"

Updating an article

You can PUT to the faqs resource to update it. Only support users can modify articles. If no published_at is given, the article is left in a draft state.

> curl -H "Accept: application/vnd.tender-v1+json" \
  -H "Content-Type: application/json" \
  -X PUT \
  -d '{"title":"MY TITLE"}'
  "https://EMAIL:PASS@api.tenderapp.com/help/faqs/12345"

Delete an article

You can DELETE to the faqs resource to delete an article. Only support users can delete articles. The return status will be 200 in case of success.

> curl -H "Accept: application/vnd.tender-v1+json" \
  -H "Content-Type: application/json" \
  -X DELETE \
  "https://EMAIL:PASS@api.tenderapp.com/help/faqs/12345"

Exporting all your KB articles at once

Here is a simple script to export all KB articles to one HTML file. You can then save it for safekeeping, or print it to a PDF in most modern browsers. It should work in all versions of ruby but requires the JSON gem to be present. Save it as a file (export.rb for example), and then you can run it with:

# Install the JSON gem (only needed for ruby 1.8.x)
gem install json

# Run the script
ruby ./export.rb

Here is the actual script. You will need to fill the top variables with your own parameters:

#!/usr/bin/env ruby

require "json"
require "time"

APIKEY = "YOUR API KEY"
EXPORT = "/tmp/export.html"
SITE   = "foobar"

def get_response(url)
  puts url
  res = `curl -sS -H "Accept: application/vnd.tender-v1+json" -H "X-Tender-Auth: #{APIKEY}" #{url}`
  JSON.parse(res)
end

body = "
<html>
  <head>
    <link href='http://twitter.github.io/bootstrap/assets/css/bootstrap.css' rel='stylesheet'>
    <style>
      body {margin:1em 2em;}
      hr.pagebreak {page-break-after: always; border: 7px solid #BBB}
    </style>
  </head>
  <body>
"

get_response("http://api.tenderapp.com/#{SITE}/sections")['sections'].each do |section|
  get_response("#{section['href']}/faqs")['faqs'].each do |faq|
    classes = []
    classes << 'beta' if faq['beta']
    classes << 'important' if faq['important']
    classes << 'draft' if Time.parse(faq['published_at']) > Time.now
    body << "<h1>#{section['title']} - #{faq['title']} #{classes.empty? ? "" : "(#{classes.join(", ")})"}</h1>"
    body << faq['formatted_body'].
      gsub(/"\/assets/, "\"http://#{SITE}.tenderapp.com/help/assets").
      gsub(/"\/help\/assets/, "\"http://#{SITE}.tenderapp.com/help/assets")
    body << "<hr class='pagebreak'>"
  end
end

File.open(EXPORT, "w") { |f| f.write body }
`open #{EXPORT}`

JSONP

First, define the callback in your javascript inside your own site's code. It must be named Tender.faq.

var Tender = { faq: function(kb){  /*... do things here ...*/ }}

Now, you can request an article directly like so:

<script src="http://your.tenderapp.com/kb/your-section/cool-article-name?format=json&jsonp=1"></script>

Here is a sample script that we use on our marketing site. In the html:

<a class="kb-load" href="#" data-kb-url="help.tenderapp.com/kb/foo/bar">Read the Bar article</a>

And javascript (uses jQuery and the magnificPopup library):

var domain = "help.tenderapp.com"; // replace with your own Tender url

/* first setup the callback */
Tender.faq = function(kb) {
  /* Generate a nice div with links back to the kb */
  var div = $("<div class='kb'></div>");
  var link = $("<a href=''></a>");
  link.attr('href', kb.html_href);
  link.text("From the Knowledge Base")
  div.append($("<h3 class='from_kb'></h3>").append(link));
  div.append($("<h1></h1>").text(kb.title));
  var body = $(kb.formatted_body);
  div.append(body);
  link = $("#" + kb.target);
  link.attr('href', link.attr('href'));
  link.magnificPopup({
    items: {
      type: 'inline',
      src: div
    }
  })
};

/* now attach the behavior to any links in the html */

$("a.kb-load").each(function(){
  /* dynamically create a script tag */
  var script = document.createElement("script");
  var src = $(this).attr("data-kb-url");
  /* generate a unique id for the link, so we know where to link */
  if (! this.id) this.id = "link-" + parseInt(Math.random() * 100000);
  /* since scripts are asymmetrically loaded, we need the link id */
  script.src = "///" + domain + "/kb/" + src + "?format=json&jsonp=1&target=" + this.id;

  var headTag = document.getElementsByTagName("head")[0];
  headTag.appendChild(script);
})