index api

David E. Wheeler edited this page Apr 28, 2011 · 9 revisions

Index API

The The entry point for all PGXN mirrors and API Servers is the index.json document, or "Index," at the root of the mirror server or API URL. Examples:

All clients must access this URI before any other in order to be able to construct the URIs for all other API calls. This is the only file that is guaranteed to be available at the same URI at all times.


The contents of the Index is a JSON object identifying all available APIs. An example from a mirror server:

   "download":  "/dist/{dist}/{version}/{dist}-{version}.zip",
   "readme":    "/dist/{dist}/{version}/README.txt",
   "meta":      "/dist/{dist}/{version}/META.json",
   "dist":      "/dist/{dist}.json",
   "extension": "/extension/{extension}.json",
   "user":      "/user/{user}.json",
   "tag":       "/tag/{tag}.json",
   "stats":     "/stats/{stats}.json",
   "mirrors":   "/meta/mirrors.json",
   "spec":      "/meta/spec.{format}"

PGXN API servers provide a superset of the mirror APIs; An example:

   "dist":       "/dist/{dist}.json",
   "download":   "/dist/{dist}/{version}/{dist}-{version}.zip",
   "extension":  "/extension/{extension}.json",
   "htmldoc":    "/dist/{dist}/{version}/{+docpath}.html",
   "meta":       "/dist/{dist}/{version}/META.json",
   "mirrors":    "/meta/mirrors.json",
   "readme":     "/dist/{dist}/{version}/README.txt",
   "search":     "/search/{in}/",
   "source":     "/src/{dist}/{dist}-{version}/",
   "spec":       "/meta/spec.{format}",
   "stats":      "/stats/{stats}.json",
   "tag":        "/tag/{tag}.json",
   "user":       "/user/{user}.json",
   "userlist":   "/users/{letter}.json"

The object keys name available REST APIs. The values are URI Templates, which must be evaluated to determine the URIs to make calls to the APIs. The ability to execute URI templates is crucial to the use of the PGXN mirror an API Server APIs. Here are some available libraries (source):


There are two types of variables currently used in PGXN URI templates:

Simple Expansion: {var}: A simple expansion. All characters not in the unreserved set of URI characters will be URI-encoded before expansion.

Reserved Expansion: {+var}: Exactly like simple expansion, except that all characters not in the set of unreserved or reserved characters will be encoded.

Effectively, this means that a value such as foo/bar will be encoded by simple expansion as foo%2Fbar, while reserved expansions will be expanded as foo/bar. At of this writing, the only reserved expansion variable in use is {+docpath} in the htmldoc template offered by the API server. All other templates use simple expansion variables.

Variable Reference

A complete list of all URI Templates used in Mirror and API Server Index document URI Templates.

  • {dist}: The lowercased name of a PGXN distribution.
  • {version}: A lowercased semantic version string.
  • {extension}: The lowercased name of a PGXN extension.
  • {user}: The lowercased nickname of a PGXN user.
  • {tag}: A lowercased tag name, or keyword.
  • {stats}: The name of a statistics file. Possible values are:
    • "dist"
    • "extension"
    • "user"
    • "tag"
    • "summary"
  • {format}: The format of a file. Possible values are:
    • "html"
    • "txt"
  • {+docpath}: The path to a documentation file, minus the file name suffix. That is, "foo/bar", but not "foo/bar.txt".
  • {in}: The name of a full text search index. Possible values are:
    • docs
    • dists
    • extensions
    • users
    • tags
  • {letter}: A single, lowercase ASCII character in the range of a-z.


Here's a very simple example in Perl of fetching the index JSON, parsing it, and compiling the templates:

use HTTP::Tiny;
use URI;
use JSON;

my $req = HTTP::Tiny->new;
my $url = URI->new('');
my $res = $req->get($url);
die "Request for $url failed: $res->{status}: $res->{reason}\n"
    unless $res->{success};
my $table = JSON->new->utf8->decode($res->{content});

To get the URI to download a the pair 1.1.0 distribution, create the URI from the download template:

use URI::Template;
my $tmpl = URI::Template->new($table->{download});
my $download_uri = $tmpl->process({
    dist    => 'pair',
    version => '1.1.0',

Consult the documentation for each individual API for list of relevant template variables.