Your Code. Your Rules.

The git.eu API

Create an API token and call the git.eu REST API - authentication, the response envelope, and a JavaScript example.

The git.eu API

git.eu serves your repositories as JSON over HTTP. Every instance exposes the same API on its own host, under /api/v0: create, list, read, update and delete repositories from a script, a CI job, or a migration tool, with no browser and no session cookie.

v0 is a beta surface. It is not frozen - routes, fields and problem types can change without a compatibility shim. Today it covers repository CRUD; more surfaces follow.

This guide is the narrative introduction: create a token, make your first call, read the response, handle errors. The API Reference is the exhaustive, generated companion - every endpoint, every field, every problem type.

Before You Start

You needWhy
A git.eu account on an instanceThe API acts as you, on your own repositories.
A personal access token with the API access scopeEvery request is authenticated - see below.
Any HTTP client (curl, fetch, requests, Postman)The API is plain JSON over HTTPS - no SDK required.

Already using a token for git clone and push? That is the same kind of credential, but a different scope - read the next section before reusing it.

Create an API Token

  • Step 1 - Open Settings → Git Access → Tokens

    Token management lives in your account settings. The page also shows the exact base URL and authentication header for your own instance, ready to paste.

  • Step 2 - Name the token and pick its scopes

    Give the token a name that says where it runs (ci-deploy, laptop-migration) and set an expiry. The create form offers two scope checkboxes:

    ScopeWhat it allows
    Git accessgit clone, fetch and push over HTTPS. Checked by default.
    API accessCalls to the JSON API described in this guide.

    The two scopes are not interchangeable, and a token can hold one, the other, or both:

    • A token with Git access only is rejected by the API - every route answers 401.
    • A token with API access only cannot clone, fetch or push.

    For API use, tick API access. Tick Git access as well only if the same token really has to run git commands too - a narrower token is a smaller blast radius when it leaks.

  • Step 3 - Copy the token now

    The raw token value is shown once, on the confirmation screen, and never again. Copy it straight into your password manager, your CI secret store, or an environment variable. Lost it? Revoke it and create a new one - there is no way to display it a second time.

Creating tokens for git rather than for the API, or setting up the OAuth credential helper instead? See the Git Access guide.

Your First Call

List the repositories you own. The token goes in the Authorization header, read here from an environment variable so it never lands in your shell history:

export GITEU_TOKEN=paste-your-token-here

curl -H "Authorization: Bearer $GITEU_TOKEN" \
  https://<INSTANCE>.git.eu/api/v0/repos

A successful call returns 200 and a JSON envelope:

{
  "data": [
    {
      "owner": "<USERNAME>",
      "name": "my-repo",
      "displayName": "My Repo",
      "description": null,
      "isPrivate": false,
      "defaultBranch": "main",
      "createdAt": "2026-01-15T09:12:44.000Z",
      "updatedAt": "2026-02-03T17:40:02.000Z"
    }
  ],
  "error": null
}

What You Get Back

Every JSON body is the same envelope: exactly one of data and error carries a value, never both, never neither. So client code always looks in the same two places - no per-endpoint guessing, no "is this the payload or the error?" branch.

On failure, error holds an RFC 9457 problem object with type, title and status. Branch on type - it is the stable machine identifier. title is human-readable prose, localized to the reader's language, and will change.

{
  "data": null,
  "error": {
    "type": "not_found",
    "title": "Not found",
    "status": 404
  }
}

The statuses that surprise people:

StatusMeaning
401No token, or a token that is invalid, expired, revoked, or missing the API access scope. Returned on every route, public repositories included.
404The repository does not exist or you are not allowed to see it - deliberately indistinguishable, so the API never confirms that a private repository exists.
200 on a batch createAlways. A batch is a per-item report, not an all-or-nothing transaction - inspect each item's own outcome.
204A successful delete. Empty body: it is the one route without an envelope.

The full per-route list of problem types is in the API Reference.

JavaScript Example

Batch-create two repositories with Node 26's built-in fetch - no dependency to install. The first item sends only the required displayName; the second sets every optional field explicitly:

const BASE_URL = 'https://<INSTANCE>.git.eu/api/v0';
const token = process.env.GITEU_TOKEN;
if (!token) throw new Error('GITEU_TOKEN is not set');

const response = await fetch(`${BASE_URL}/repos/batch`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    repos: [
      { displayName: 'Scratch Pad' },
      {
        displayName: 'Team Handbook',
        slug: 'team-handbook',
        description: 'Onboarding notes and conventions.',
        isPrivate: true,
      },
    ],
  }),
});

const body = await response.json();
if (body.error) throw new Error(`${body.error.type}: ${body.error.title}`);

for (const item of body.data) {
  if (item.status === 'created') {
    console.log(`#${item.index} created: ${item.repo.owner}/${item.repo.name}`);
  } else {
    console.error(`#${item.index} failed: ${item.error.title}`);
  }
}

Two rules the example is built around:

  • A batch is a partial-success report. The response is 200 even when some items fail, so

always walk data and check each item's status. A failed item carries its own error problem object; the others are still created.

  • Omitted is not the same as explicit. An optional field you leave out falls back to your

own repository defaults from account settings. A value you send always wins - including isPrivate: false, which forces a public repository even when your default is private.

Migrating many repositories from another host in one run? A dedicated Python migration tool is in preparation; until it is published, the batch endpoint above is the supported path.

Token Security

An API token authenticates as you, with no second factor. Treat it exactly like a password:

  • Scope it down. If it only calls the API, leave Git access unchecked.
  • Set an expiry. A token that outlives the job it was created for is pure risk.
  • Keep it out of source. Read it from an environment variable or a CI secret store - never

commit it, never paste it into an issue, never hardcode it in an example.

  • Never put it in a URL. Query strings end up in shell history, proxy logs and error

messages. The Authorization header does not.

  • One token per consumer. Separate tokens per machine, per CI pipeline, per tool means you

revoke one thing, not everything.

  • Revoke on any doubt. Revocation is immediate, from Settings → Git Access → Tokens.

Create a fresh token and move on - rotating costs minutes, a leak costs more.

Next Steps

git CLI.

guide.

Ready to get started?

Create an API token