Repository Public MIT Selected
1{#2 ─────────────────────────────────────────────3 SPB Git — Personal Git Platform4 ─────────────────────────────────────────────5 Author : Simon-Pierre Boucher6 Contact : contact@spboucher.ai7 File : src/web/views/api.njk8 Purpose : API reference — public read endpoints, git over HTTPS, raw files, archives, feeds, token-gated writes9 License : MIT © Simon-Pierre Boucher10 ─────────────────────────────────────────────11#}{% extends "layout.njk" %}12{% import "components/ui.njk" as ui %}13{% macro ep(method, path, desc, href=null) -%}14<tr><td><span class="method method-{{ method | lower }}">{{ method }}</span></td><td class="ep-path">{% if href %}<a href="{{ href }}">{{ path }}</a>{% else %}{{ path }}{% endif %}</td><td>{{ desc }}</td></tr>15{%- endmacro %}16{% block content %}17<section class="page-head">18 <p class="eyebrow"><span class="eyebrow-rule" aria-hidden="true"></span>About · API</p>19 <h1 class="page-title">Machine-readable, by default</h1>20 <p class="page-lede">Everything shown on this site is available as JSON, as raw files or over git itself. Reads are public and need no key; writes require the owner's personal access token.</p>21</section>22<div class="prose-layout">23 <nav class="prose-nav" aria-label="On this page">24 <p class="toc-title">On this page</p>25 <ol><li><a href="#git">Git over HTTPS</a></li><li><a href="#read">Read endpoints</a></li><li><a href="#files">Files, archives, feeds</a></li><li><a href="#write">Write endpoints</a></li><li><a href="#limits">Limits and errors</a></li></ol>26 </nav>27 <article class="markdown-body prose">28 <h2 id="git">Git over HTTPS</h2>29 <p>Every repository is served with the Git smart HTTP protocol. Clone and fetch are anonymous; push uses HTTP Basic with the user <code>spb</code> and a personal access token as the password.</p>30 <pre class="snippet" tabindex="0"><span class="prompt">$</span>git clone {{ publicUrl }}/{{ sample }}.git31<span class="prompt">$</span>git ls-remote {{ publicUrl }}/{{ sample }}.git</pre>3233 <h2 id="read">Read endpoints</h2>34 <p>Base URL <code>{{ publicUrl }}/api/v1</code>. Responses are JSON; errors use the envelope <code>{"error": {"code", "message"}}</code>.</p>35 <table class="ep-table">36 <thead><tr><th>Method</th><th>Path</th><th>Returns</th></tr></thead>37 <tbody>38 {{ ep('GET', '/api/v1/repos', 'Every repository with its overview (description, topics, languages, counts, last push).', '/api/v1/repos') }}39 {{ ep('GET', '/api/v1/repos/:name', 'One repository overview.', '/api/v1/repos/' + sample) }}40 {{ ep('GET', '/api/v1/repos/:name/languages', 'Bytes and percentages per language at HEAD.', '/api/v1/repos/' + sample + '/languages') }}41 {{ ep('GET', '/api/v1/repos/:name/commits?ref=&page=', 'Commit history, 40 per page, with diff statistics.', '/api/v1/repos/' + sample + '/commits') }}42 {{ ep('GET', '/api/v1/repos/:name/tree?ref=&path=', 'One directory level of the tree at a ref.', '/api/v1/repos/' + sample + '/tree') }}43 {{ ep('GET', '/api/v1/repos/:name/releases', 'Tags with their attached release assets and checksums.', '/api/v1/repos/' + sample + '/releases') }}44 {{ ep('GET', '/api/v1/search?q=&scope=&repo=&limit=', 'Scoped search: all, repos, files, commits, branches or readmes.', '/api/v1/search?q=readme&limit=5') }}45 {{ ep('GET', '/api/v1/stats', 'Site totals: repositories, commits, streaks, languages.', '/api/v1/stats') }}46 {{ ep('GET', '/healthz', 'Version, uptime, repository count, cache footprint.', '/healthz') }}47 </tbody>48 </table>4950 <h2 id="files">Files, archives, feeds</h2>51 <table class="ep-table">52 <thead><tr><th>Method</th><th>Path</th><th>Returns</th></tr></thead>53 <tbody>54 {{ ep('GET', '/raw/:repo/:ref/:path', 'The file as stored, streamed. HTML is served as plain text.') }}55 {{ ep('GET', '/archive/:repo/:ref.zip', 'A zip snapshot of the tree at a branch, tag or commit.') }}56 {{ ep('GET', '/archive/:repo/:ref.tar.gz', 'The same snapshot as a gzipped tarball.') }}57 {{ ep('GET', '/releases/:repo/:tag/:asset', 'A release asset; the sha256 is in the X-Checksum-Sha256 header.') }}58 {{ ep('GET', '/feed.atom', 'Atom feed of the latest pushes and tags.', '/feed.atom') }}59 {{ ep('GET', '/sitemap.xml', 'Sitemap of every repository page.', '/sitemap.xml') }}60 {{ ep('GET', '/og/:repo.png', 'The social card of a repository.') }}61 </tbody>62 </table>6364 <h2 id="write">Write endpoints</h2>65 <p>Owner only: send <code>Authorization: Bearer <token></code>. The <a href="/spbgit">spbgit</a> command line wraps all of them.</p>66 <table class="ep-table">67 <thead><tr><th>Method</th><th>Path</th><th>Does</th></tr></thead>68 <tbody>69 {{ ep('POST', '/api/v1/repos', 'Create a repository.') }}70 {{ ep('PATCH', '/api/v1/repos/:name', 'Update description, topics, homepage, pinned, research, default branch.') }}71 {{ ep('DELETE', '/api/v1/repos/:name', 'Soft-delete a repository (recoverable).') }}72 {{ ep('PUT', '/api/v1/repos/:name/releases/:tag/assets/:asset', 'Upload a release asset (streamed to disk).') }}73 {{ ep('DELETE', '/api/v1/repos/:name/releases/:tag/assets/:asset', 'Remove a release asset.') }}74 {{ ep('POST', '/api/v1/tokens', 'Mint a personal access token.') }}75 {{ ep('GET', '/api/v1/tokens', 'List tokens (labels and last use, never the secret).') }}76 {{ ep('DELETE', '/api/v1/tokens/:id', 'Revoke a token.') }}77 {{ ep('GET', '/api/v1/whoami', 'Check that a token is valid.') }}78 </tbody>79 </table>8081 <h2 id="limits">Limits and errors</h2>82 <ul>83 <li>Public endpoints are limited to 200 requests per minute per IP address; beyond that the answer is <code>429</code> with the code <code>rate_limited</code>.</li>84 <li>Search queries are capped at 120 characters and <code>limit</code> at 50 results per group.</li>85 <li>Unknown repositories and refs answer <code>404</code> with <code>not_found</code> or <code>ref_not_found</code>.</li>86 <li>Definitions of every count returned by <code>/api/v1/stats</code> are on the <a href="/about/metrics">metrics page</a>.</li>87 </ul>88 </article>89</div>90{% endblock %}91