Diffinery
Reference: REST API reference
Docs / Reference

REST API reference

Every REST API endpoint with its parameters, access rules and an example, generated from the server's router.

Every endpoint of the Diffinery REST API, generated from the server's router, so this list always matches what https://diffinery.com/api/v3 serves. The same information is available as an OpenAPI 3.1 document. For authentication, errors, pagination and GitHub compatibility, read the REST API guide.

Basics

  • Base URL: https://diffinery.com/api/v3
  • Authenticate with a personal access token: Authorization: Bearer dfy_... (token dfy_... and HTTP Basic with the token as the password work too). Create one under Settings → Access tokens.
  • Send and receive JSON. Errors are JSON objects with a message and a documentation_url, unknown paths included (404).
  • Reads of public repositories need no token. Every write needs a signed-in caller (401 otherwise) and, from a token, the write scope (403 otherwise). A token's scope also caps its role on a repository: read reads, write acts up to maintain, admin acts as admin. Each endpoint below says which scope it needs.
  • A private repository you can't see is a 404, whatever the method, so a read token's write to it doesn't reveal that it exists.
  • An archived repository refuses every write with 403 repository is archived (read-only), except unarchiving it (PATCH with archived: false), deleting it and watching it.
  • A workflow job's GITHUB_TOKEN follows the job's permissions: instead of token scopes: each endpoint needs its permission (contents, issues, pull-requests, actions and so on), and settings, secrets, variables, webhooks and branch protection are out of its reach. See Workflow permissions.
  • Paths, field names and status codes follow GitHub's REST API wherever Diffinery has the same feature, so most GitHub clients work with baseUrl set to the URL above.
  • 452 endpoints in 29 groups.

Endpoints by group

Meta

MethodPathSummary
GET/API root
GET/metaInstance metadata
GET/rate_limitGet rate limit status

API root

GET /api/v3

Names the API and links to these docs and the MCP endpoint.

Access: No authentication needed.

curl "https://diffinery.com/api/v3"

Instance metadata

GET /api/v3/meta

Whether this instance issues OIDC tokens to workflows, and the runner image its last deploy set (runner_image; each job reports the image it ran on as runner.image), and whether it tells search engines about changed public pages through IndexNow (indexnow: enabled, key_location and the time, URL count, IndexNow status and endpoint of the last_submission; see Site administration).

Access: No authentication needed.

curl "https://diffinery.com/api/v3/meta"

Get rate limit status

GET /api/v3/rate_limit

For GitHub clients that check their budget before calling. It always reports a full, constant budget (15000 core requests an hour). Diffinery's real limits are per minute (2,000 requests per account, 60 new repositories, issues, pull requests, comments and the like, 300 requests per IP address without signing in) and answer 429 with retry-after: 60; see /docs/reference/rest-api#rate-limits.

Access: No authentication needed.

curl "https://diffinery.com/api/v3/rate_limit"

Users

MethodPathSummary
GET/userGet the authenticated account
PUT/user/avatarSet your profile picture
DELETE/user/avatarRemove your profile picture
GET/user/orgsList your organizations
POST/user/orgsCreate an organization
GET/users/{login}Get an account

Get the authenticated account

GET /api/v3/user

Returns your account, including email and site_admin. Agents get their own account (type Bot).

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/user" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set your profile picture

PUT /api/v3/user/avatar

Diffinery only. The raw request body is the image (JPEG, PNG or WebP, at most 5 MB), not JSON. Returns the new avatar_url. A token needs write or admin scope and must not be limited to repositories. Audited.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X PUT "https://diffinery.com/api/v3/user/avatar" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove your profile picture

DELETE /api/v3/user/avatar

Diffinery only. Goes back to generated initials and returns the avatar_url. Same token rules as setting one. Audited.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X DELETE "https://diffinery.com/api/v3/user/avatar" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your organizations

GET /api/v3/user/orgs

Each organization carries your role in it (member, admin or owner).

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/user/orgs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an organization

POST /api/v3/user/orgs

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
loginstringyesOrganization login (letters, digits, - and _; no dots).
namestringnoDisplay name (default: the login).
curl -X POST "https://diffinery.com/api/v3/user/orgs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"login":"..."}'

Get an account

GET /api/v3/users/{login}

A user, organization or agent by login. A suspended person is 404 except to site administrators, who also see suspended_at and suspension_reason.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl "https://diffinery.com/api/v3/users/diffy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Organizations

MethodPathSummary
GET/invitationsList pending invitations to this instance
POST/invitationsInvite someone to this instance
DELETE/invitations/{id}Revoke an invitation to this instance
GET/orgs/{org}Get an organization
PATCH/orgs/{org}Update an organization
DELETE/orgs/{org}Delete an organization
PUT/orgs/{org}/avatarSet an organization's picture
DELETE/orgs/{org}/avatarRemove an organization's picture
GET/orgs/{org}/invitationsList an organization's pending invitations
POST/orgs/{org}/invitationsInvite someone to an organization
DELETE/orgs/{org}/invitations/{id}Revoke an organization invitation
GET/orgs/{org}/membersList organization members

List pending invitations to this instance

GET /api/v3/invitations

Site-wide invites only, not those to an organization or repository. Site admins only.

Access: A site administrator. Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Invite someone to this instance

POST /api/v3/invitations

A site-wide invite with no organization. Site admins only.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
emailstringyesEmail address to invite.
curl -X POST "https://diffinery.com/api/v3/invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email":"..."}'

Revoke an invitation to this instance

DELETE /api/v3/invitations/{id}

Site admins only. 404 when no pending site-wide invitation has this id. Audited.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/invitations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an organization

GET /api/v3/orgs/{org}

GitHub's organization object. Members, the organization's agents, agents of members, and site admins also get default_repository_permission, the organization's base permission (none, read, write or admin).

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update an organization

PATCH /api/v3/orgs/{org}

Organization owners (and site admins) only; admins and members get 403. Returns the updated organization. Every field is checked before anything is saved, so a bad value (422) changes nothing. Changing the base permission applies to every member right away; owners and admins always keep admin. Audited.

Access: An owner of the organization (or a site admin). Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
default_repository_permissionstringnoBase permission every member gets on the organization's repositories: none, read (the default for new organizations), write or admin.
namestringnoDisplay name. An empty value clears it, and pages show the login instead.
curl -X PATCH "https://diffinery.com/api/v3/orgs/acme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete an organization

DELETE /api/v3/orgs/{org}

Owners only (or site admins). Refused with 422 while the organization still owns repositories (transfer or delete them first), container images, or an import in progress. Its members, pending invitations, secrets and variables are removed, its agents disabled and their tokens revoked, and its login freed. Repositories transferred out of it keep redirecting from their old URLs. Audited. From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 202.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set an organization's picture

PUT /api/v3/orgs/{org}/avatar

Diffinery only. Organization owners (and site admins) only. The raw request body is the image (JPEG, PNG or WebP, at most 5 MB), not JSON. Returns the new avatar_url. A token needs write or admin scope and must not be limited to repositories. Audited.

Access: An owner of the organization (or a site admin). Tokens need the write scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/avatar" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove an organization's picture

DELETE /api/v3/orgs/{org}/avatar

Diffinery only. Organization owners (and site admins) only. Goes back to generated initials and returns the avatar_url. Audited.

Access: An owner of the organization (or a site admin). Tokens need the write scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/avatar" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List an organization's pending invitations

GET /api/v3/orgs/{org}/invitations

Owners and admins (or site admins). Each has an id to revoke it with.

Access: An owner or admin of the organization (or a site admin). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Invite someone to an organization

POST /api/v3/orgs/{org}/invitations

Emails an invite link. The response holds the link too, so you can share it yourself. Refused with 422 when the address already has a pending invitation to the organization (letter case doesn't matter) or belongs to a member. You can send at most 50 invitations in 24 hours (site admins aren't limited); more answer 429 you can send at most 50 invitations in 24 hours; try again later.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 201.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
emailstringyesEmail address to invite.
rolestringnomember (default), admin or owner.
curl -X POST "https://diffinery.com/api/v3/orgs/acme/invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email":"..."}'

Revoke an organization invitation

DELETE /api/v3/orgs/{org}/invitations/{id}

The link stops working and the address can be invited again. 404 when no pending invitation has this id. Audited.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/invitations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List organization members

GET /api/v3/orgs/{org}/members

Members only (or site admins). Each entry carries the member's role.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/members" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"
MethodPathSummary
GET/search/issuesSearch issues and pull requests
GET/search/repositoriesSearch repositories

Search issues and pull requests

GET /api/v3/search/issues

Searches the repositories you can read (only public ones without a token), at most 50 per query; incomplete_results is true when more were left out. Qualifiers: repo:, user:, org:, owner:, is:, type:, state:, draft:, label:, no:, author:, assignee:, head:, base:, in:, created:, updated:, closed: and sort:; others are searched as text. Only the first 1000 results are available, and every score is 1.

Access: No authentication needed.

Query parameters:

NameTypeRequiredDescription
qstringyesSearch query, at most 256 characters.
sortstringnocreated (default), updated or comments.
orderstringnodesc (default) or asc.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/search/issues"

Search repositories

GET /api/v3/search/repositories

Matches names, descriptions and topics of the repositories you can see (only public ones without a token). Qualifiers: user:, org:, owner:, repo:, topic:, is:public, is:private, archived: and in:name,description,topics. fork:, language:, stars:, forks:, size:, pushed: and created: are accepted but don't filter anything. Every score is 1.

Access: No authentication needed.

Query parameters:

NameTypeRequiredDescription
qstringyesSearch query, at most 256 characters.
sortstringnoupdated sorts by last push; anything else keeps the default order.
orderstringnoWith sort=updated: desc (default) or asc.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/search/repositories"

Repositories

MethodPathSummary
GET/orgs/{org}/reposList an organization's repositories
POST/orgs/{org}/reposCreate an organization repository
GET/repos/{owner}/{repo}Get a repository
PATCH/repos/{owner}/{repo}Update a repository
DELETE/repos/{owner}/{repo}Delete a repository
GET/repos/{owner}/{repo}/assigneesList assignable people
GET/repos/{owner}/{repo}/assignees/{login}Check if someone can be assigned
GET/repos/{owner}/{repo}/collaboratorsList collaborators
PUT/repos/{owner}/{repo}/collaborators/{login}Invite a collaborator, or change one's role
DELETE/repos/{owner}/{repo}/collaborators/{login}Remove a collaborator
POST/repos/{owner}/{repo}/dispatchesTrigger a repository_dispatch event
GET/repos/{owner}/{repo}/invitationsList pending repository invitations
DELETE/repos/{owner}/{repo}/invitations/{id}Revoke a repository invitation
GET/repos/{owner}/{repo}/languagesList languages
GET/repos/{owner}/{repo}/topicsGet topics
PUT/repos/{owner}/{repo}/topicsReplace topics
GET/user/reposList repositories you can access
POST/user/reposCreate a repository for yourself
GET/users/{login}/reposList an account's repositories

List an organization's repositories

GET /api/v3/orgs/{org}/repos

Only the ones you can see. A token limited to repositories lists only those repositories.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/repos" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an organization repository

POST /api/v3/orgs/{org}/repos

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 201.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
namestringyesRepository name.
descriptionstringnoShort description.
visibilitystringnoprivate (default) or public.
default_branchstringnoDefault branch name (default main).
curl -X POST "https://diffinery.com/api/v3/orgs/acme/repos" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'

Get a repository

GET /api/v3/repos/{owner}/{repo}

Includes your role (permissions.role) and repository statistics.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a repository

PATCH /api/v3/repos/{owner}/{repo}

Works on an archived repository too, so an admin can unarchive it with archived: false. Audited as repo.update, repo.archive or repo.unarchive. A new name renames the repository: its old name keeps redirecting (see the transfer endpoint), until a repository is created there again. 422 when the owner already has a repository with that name.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
namestringnoNew name.
descriptionstringnoNew description.
visibilitystringnoprivate or public.
default_branchstringnoNew default branch (must exist).
archivedbooleannoArchive (read-only) or unarchive.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a repository

DELETE /api/v3/repos/{owner}/{repo}

People only; agents can't delete repositories. Works on an archived repository too. Audited. From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List assignable people

GET /api/v3/repos/{owner}/{repo}/assignees

Collaborators with triage access or more, plus the owner when the owner is a user.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/assignees" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Check if someone can be assigned

GET /api/v3/repos/{owner}/{repo}/assignees/{login}

204 when login is the repository's owner or a collaborator with triage access or more, 404 otherwise.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
loginstringyesAccount login.
curl "https://diffinery.com/api/v3/repos/acme/website/assignees/diffy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List collaborators

GET /api/v3/repos/{owner}/{repo}/collaborators

Each entry carries role_name.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/collaborators" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Invite a collaborator, or change one's role

PUT /api/v3/repos/{owner}/{repo}/collaborators/{login}

As on GitHub, a person without access gets an invitation and has access once they accept it: the answer is 201 with the invitation (id, repository, invitee, inviter, permissions, expires_at), audited as repo.invite; asking again while it's pending changes its role. Agents, existing collaborators, members of the owning organization and yourself get the role at once: 204, audited as repo.collaborator.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
loginstringyesAccount login.

Body (JSON):

NameTypeRequiredDescription
permissionstringnoread, triage, write (default), maintain or admin; GitHub's pull and push work too.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/collaborators/diffy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove a collaborator

DELETE /api/v3/repos/{owner}/{repo}/collaborators/{login}

Audited as repo.collaborator.remove.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
loginstringyesAccount login.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/collaborators/diffy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Trigger a repository_dispatch event

POST /api/v3/repos/{owner}/{repo}/dispatches

Starts workflows on the default branch that run on: repository_dispatch with this type, and sends the repository_dispatch webhook. Fails with 422 on an empty repository, and with 429 when the repository already has 500 unfinished workflow runs.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
event_typestringyesEvent type, at most 100 characters.
client_payloadobjectnoData for workflows as github.event.client_payload: at most 10 top-level keys and 64 KB.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/dispatches" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"event_type":"..."}'

List pending repository invitations

GET /api/v3/repos/{owner}/{repo}/invitations

Invitations sent by email to people without an account. Each has an id to revoke it with.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Revoke a repository invitation

DELETE /api/v3/repos/{owner}/{repo}/invitations/{id}

The link stops working and the address can be invited again. 404 when no pending invitation to this repository has this id. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/invitations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List languages

GET /api/v3/repos/{owner}/{repo}/languages

Bytes of code per language on the default branch, largest first. Languages come from file extensions and a few well-known file names; vendored directories like node_modules and vendor are skipped.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/languages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get topics

GET /api/v3/repos/{owner}/{repo}/topics

Returns { names }.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/topics" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Replace topics

PUT /api/v3/repos/{owner}/{repo}/topics

Names are lower-cased and deduplicated. Each starts with a letter or digit and has at most 50 letters, digits and dashes; at most 20 topics. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
namesstring[]yesEvery topic the repository should have ([] clears them).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/topics" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"names":["..."]}'

List repositories you can access

GET /api/v3/user/repos

A token limited to repositories lists only those repositories.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/user/repos" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a repository for yourself

POST /api/v3/user/repos

An agent's repositories belong to its owner.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
namestringyesRepository name.
descriptionstringnoShort description.
visibilitystringnoprivate (default) or public.
default_branchstringnoDefault branch name (default main).
curl -X POST "https://diffinery.com/api/v3/user/repos" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'

List an account's repositories

GET /api/v3/users/{login}/repos

Only the ones you can see. A token limited to repositories lists only those repositories.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl "https://diffinery.com/api/v3/users/diffy/repos" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Contents

MethodPathSummary
GET/repos/{owner}/{repo}/contentsList the root directory
GET/repos/{owner}/{repo}/contents/{path}Get a file or directory
PUT/repos/{owner}/{repo}/contents/{path}Create or update a file
DELETE/repos/{owner}/{repo}/contents/{path}Delete a file
POST/repos/{owner}/{repo}/diffinery/commitsCommit several files at once
GET/repos/{owner}/{repo}/raw/{ref}/{path}Download a raw file
GET/repos/{owner}/{repo}/readmeGet the README
GET/repos/{owner}/{repo}/readme/{dir}Get a directory's README
GET/repos/{owner}/{repo}/tarballDownload a tarball
GET/repos/{owner}/{repo}/tarball/{ref}Download a tarball of a ref
GET/repos/{owner}/{repo}/zipballDownload a zip archive
GET/repos/{owner}/{repo}/zipball/{ref}Download a zip archive of a ref

List the root directory

GET /api/v3/repos/{owner}/{repo}/contents

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
refstringnoBranch, tag or commit (default: the default branch).
curl "https://diffinery.com/api/v3/repos/acme/website/contents" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a file or directory

GET /api/v3/repos/{owner}/{repo}/contents/{path}

A directory returns an array of entries; a file returns its content base64-encoded.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.

Query parameters:

NameTypeRequiredDescription
refstringnoBranch, tag or commit (default: the default branch).
curl "https://diffinery.com/api/v3/repos/acme/website/contents/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create or update a file

PUT /api/v3/repos/{owner}/{repo}/contents/{path}

Commits one file.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.

Body (JSON):

NameTypeRequiredDescription
messagestringyesCommit message.
contentstringyesNew content, base64-encoded.
branchstringnoBranch to commit to (default: the default branch).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/contents/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"...","content":"..."}'

Delete a file

DELETE /api/v3/repos/{owner}/{repo}/contents/{path}

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.

Body (JSON):

NameTypeRequiredDescription
messagestringyesCommit message.
branchstringnoBranch to commit to (default: the default branch).
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/contents/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"..."}'

Commit several files at once

POST /api/v3/repos/{owner}/{repo}/diffinery/commits

Diffinery only. Writes and deletes any number of files in one commit, without a git client. Pass expected_head_sha to fail instead of racing another writer. Push protection scans the new content as it does for git push: content that looks like a credential is refused with 422 and audited as api.blocked_secret. A repository admin who is a person can commit it anyway with an allow_secrets reason, audited as api.secret_bypassed and emailed to the repository's admins.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
branchstringyesBranch to commit to.
messagestringyesCommit message.
filesarrayyesChanges: { path, content, encoding: "utf-8" | "base64", mode: "100644" | "100755" } or { path, delete: true }.
basestringnoCreate branch from this ref when it doesn't exist.
expected_head_shastringnoFail with 409 if the branch has moved.
allow_secretsstringnoWhy a detected secret may be committed anyway (repository admins who are people; at most 200 characters are kept).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/commits" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"branch":"...","message":"...","files":[]}'

Download a raw file

GET /api/v3/repos/{owner}/{repo}/raw/{ref}/{path}

The file's bytes, served as text or application/octet-stream.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
pathstringyesPath inside the repository, or a ref name after refs/.
curl "https://diffinery.com/api/v3/repos/acme/website/raw/main/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get the README

GET /api/v3/repos/{owner}/{repo}/readme

The README in the root directory, base64-encoded like a file from the contents API. A Markdown README wins when there are several. Send Accept: application/vnd.github.raw for the raw bytes.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
refstringnoBranch, tag or commit (default: the default branch).
curl "https://diffinery.com/api/v3/repos/acme/website/readme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a directory's README

GET /api/v3/repos/{owner}/{repo}/readme/{dir}

Like the root README, for the directory dir.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
dirstringyesdir

Query parameters:

NameTypeRequiredDescription
refstringnoBranch, tag or commit (default: the default branch).
curl "https://diffinery.com/api/v3/repos/acme/website/readme/dir" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download a tarball

GET /api/v3/repos/{owner}/{repo}/tarball

A .tar.gz of the repository's files, served directly (GitHub redirects to a download host instead). Built once per commit, at most 20 new builds per repository per hour (429 after that); repositories with more than 24 MB of files can't be archived (413). Uses the default branch.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/tarball" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download a tarball of a ref

GET /api/v3/repos/{owner}/{repo}/tarball/{ref}

A .tar.gz of the repository's files, served directly (GitHub redirects to a download host instead). Built once per commit, at most 20 new builds per repository per hour (429 after that); repositories with more than 24 MB of files can't be archived (413).

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
curl "https://diffinery.com/api/v3/repos/acme/website/tarball/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download a zip archive

GET /api/v3/repos/{owner}/{repo}/zipball

A .zip (at most 65535 files) of the repository's files, served directly (GitHub redirects to a download host instead). Built once per commit, at most 20 new builds per repository per hour (429 after that); repositories with more than 24 MB of files can't be archived (413). Uses the default branch.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/zipball" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download a zip archive of a ref

GET /api/v3/repos/{owner}/{repo}/zipball/{ref}

A .zip (at most 65535 files) of the repository's files, served directly (GitHub redirects to a download host instead). Built once per commit, at most 20 new builds per repository per hour (429 after that); repositories with more than 24 MB of files can't be archived (413).

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
curl "https://diffinery.com/api/v3/repos/acme/website/zipball/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Releases

MethodPathSummary
GET/repos/{owner}/{repo}/releasesList releases
POST/repos/{owner}/{repo}/releasesCreate a release
GET/repos/{owner}/{repo}/releases/{id}Get a release
PATCH/repos/{owner}/{repo}/releases/{id}Update a release
DELETE/repos/{owner}/{repo}/releases/{id}Delete a release
GET/repos/{owner}/{repo}/releases/{id}/assetsList release assets
GET/repos/{owner}/{repo}/releases/{id}/reactionsList reactions to a release
POST/repos/{owner}/{repo}/releases/{id}/reactionsAdd a reaction to a release
DELETE/repos/{owner}/{repo}/releases/{id}/reactions/{reaction}Delete a reaction from a release
GET/repos/{owner}/{repo}/releases/assets/{id}Get a release asset
PATCH/repos/{owner}/{repo}/releases/assets/{id}Update a release asset
DELETE/repos/{owner}/{repo}/releases/assets/{id}Delete a release asset
POST/repos/{owner}/{repo}/releases/generate-notesGenerate release notes
GET/repos/{owner}/{repo}/releases/latestGet the latest release
GET/repos/{owner}/{repo}/releases/tags/{tag}Get a release by tag

List releases

GET /api/v3/repos/{owner}/{repo}/releases

Newest first. Drafts are included only for people with write access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/releases" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a release

POST /api/v3/repos/{owner}/{repo}/releases

A published release (not a draft) creates its tag at target_commitish when the tag doesn't exist, sends release webhooks and starts on: release workflows; a draft only sends the created webhook. 422 when the tag already has a published release. Upload assets to the release's upload_url. discussion_category_name is ignored. See Releases.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
tag_namestringyesTag to release.
target_commitishstringnoBranch, tag or commit for a new tag (default: the default branch).
namestringnoRelease title.
bodystringnoMarkdown notes, at most 125000 characters.
draftbooleannoSave as a draft.
prereleasebooleannoMark as a prerelease.
make_lateststringnotrue (default), false, or legacy (the newest by date).
generate_release_notesbooleannoAppend generated notes to body.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/releases" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tag_name":"..."}'

Get a release

GET /api/v3/repos/{owner}/{repo}/releases/{id}

Drafts are 404 for people without write access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/releases/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a release

PATCH /api/v3/repos/{owner}/{repo}/releases/{id}

Send only what changes. Setting draft to false publishes the release (creating its tag if needed); setting it back to true unpublishes it. Sends release webhooks.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
tag_namestringnoNew tag.
target_commitishstringnoBranch, tag or commit for a new tag.
namestringnoRelease title.
bodystringnoMarkdown notes, at most 125000 characters.
draftbooleannoDraft or published.
prereleasebooleannoMark as a prerelease.
make_lateststringnotrue, false or legacy.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/releases/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a release

DELETE /api/v3/repos/{owner}/{repo}/releases/{id}

Deletes its assets too; the tag stays. Sends the release webhook.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/releases/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List release assets

GET /api/v3/repos/{owner}/{repo}/releases/{id}/assets

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/releases/1/assets" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reactions to a release

GET /api/v3/repos/{owner}/{repo}/releases/{id}/reactions

Drafts are hidden from people without write access, and so are their reactions.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
contentstringnoOnly reactions with this content.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/releases/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a reaction to a release

POST /api/v3/repos/{owner}/{repo}/releases/{id}/reactions

Needs a signed-in account. Returns 201 for a new reaction, or 200 with the existing one when you had already reacted with that content.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
contentstringyes+1, -1, laugh, confused, heart, hooray, rocket or eyes.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/releases/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"..."}'

Delete a reaction from a release

DELETE /api/v3/repos/{owner}/{repo}/releases/{id}/reactions/{reaction}

Your own reactions, or anyone's with admin access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
reactionstringyesreaction
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/releases/1/reactions/reaction" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a release asset

GET /api/v3/repos/{owner}/{repo}/releases/assets/{id}

The asset's metadata, or the file itself with Accept: application/octet-stream.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/releases/assets/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a release asset

PATCH /api/v3/repos/{owner}/{repo}/releases/assets/{id}

state is accepted and ignored.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
namestringnoNew file name (unique within the release).
labelstringnoDisplay label.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/releases/assets/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a release asset

DELETE /api/v3/repos/{owner}/{repo}/releases/assets/{id}

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/releases/assets/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Generate release notes

POST /api/v3/repos/{owner}/{repo}/releases/generate-notes

Builds notes from the pull requests merged since the previous release, with categories from .github/release.yml (or .yaml). Nothing is saved; returns { name, body }.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
tag_namestringyesTag for the release.
target_commitishstringnoUsed when the tag doesn't exist yet (default: the default branch).
previous_tag_namestringnoStart from this tag (default: the newest earlier published release).
configuration_file_pathstringnoConfig file to use instead of .github/release.yml.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/releases/generate-notes" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tag_name":"..."}'

Get the latest release

GET /api/v3/repos/{owner}/{repo}/releases/latest

The release marked latest, or else the newest published release that isn't a prerelease. 404 when there is none.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/releases/latest" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a release by tag

GET /api/v3/repos/{owner}/{repo}/releases/tags/{tag}

Published releases only; drafts aren't found by tag.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
tagstringyestag
curl "https://diffinery.com/api/v3/repos/acme/website/releases/tags/tag" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Git database

MethodPathSummary
POST/repos/{owner}/{repo}/git/blobsCreate a blob
GET/repos/{owner}/{repo}/git/blobs/{sha}Get a blob
POST/repos/{owner}/{repo}/git/commitsCreate a Git commit
GET/repos/{owner}/{repo}/git/commits/{sha}Get a Git commit
GET/repos/{owner}/{repo}/git/matching-refs/{ref}List matching references
GET/repos/{owner}/{repo}/git/ref/{ref}Get a reference
GET/repos/{owner}/{repo}/git/refsList all references
POST/repos/{owner}/{repo}/git/refsCreate a reference
GET/repos/{owner}/{repo}/git/refs/{path}List references
PATCH/repos/{owner}/{repo}/git/refs/{path}Update a reference
DELETE/repos/{owner}/{repo}/git/refs/{path}Delete a reference
POST/repos/{owner}/{repo}/git/tagsCreate a tag object
GET/repos/{owner}/{repo}/git/tags/{sha}Get a tag object
POST/repos/{owner}/{repo}/git/treesCreate a tree
GET/repos/{owner}/{repo}/git/trees/{sha}Get a tree

Create a blob

POST /api/v3/repos/{owner}/{repo}/git/blobs

Push protection applies: content that looks like a credential is refused with 422. Returns { url, sha }.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
contentstringyesThe blob's content.
encodingstringnoutf-8 (default) or base64.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/git/blobs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"..."}'

Get a blob

GET /api/v3/repos/{owner}/{repo}/git/blobs/{sha}

Content is base64-encoded; send Accept: application/vnd.github.raw for the raw bytes.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha
curl "https://diffinery.com/api/v3/repos/acme/website/git/blobs/sha" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a Git commit

POST /api/v3/repos/{owner}/{repo}/git/commits

Writes a commit object; no branch moves until you update a reference. author and committer default to you. Commits made by agents carry a diffinery-agent header.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
messagestringyesCommit message.
treestringyesSHA of the commit's tree.
parentsstring[]noParent commit SHAs (none for a root commit).
authorobjectno{ name, email, date }.
committerobjectno{ name, email, date } (default: the author).
signaturestringnoSignature to store in the commit as given.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/git/commits" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"...","tree":"..."}'

Get a Git commit

GET /api/v3/repos/{owner}/{repo}/git/commits/{sha}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha
curl "https://diffinery.com/api/v3/repos/acme/website/git/commits/sha" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List matching references

GET /api/v3/repos/{owner}/{repo}/git/matching-refs/{ref}

Refs whose names start with refs/{ref}, like heads/feature or tags/v1.. Pull request refs appear only when ref starts with pull/.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 100, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/git/matching-refs/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a reference

GET /api/v3/repos/{owner}/{repo}/git/ref/{ref}

ref is the name after refs/, like heads/main or tags/v1.0, and must match exactly.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
curl "https://diffinery.com/api/v3/repos/acme/website/git/ref/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List all references

GET /api/v3/repos/{owner}/{repo}/git/refs

Every branch, tag and other ref, without pull request refs.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 100, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/git/refs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a reference

POST /api/v3/repos/{owner}/{repo}/git/refs

Branch protection and agent rules apply as they do to a push.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
refstringyesFull ref name, like refs/heads/feature.
shastringyesCommit to point at.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/git/refs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ref":"...","sha":"..."}'

List references

GET /api/v3/repos/{owner}/{repo}/git/refs/{path}

Every ref under refs/{path}, for example heads or tags/v1.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.
curl "https://diffinery.com/api/v3/repos/acme/website/git/refs/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a reference

PATCH /api/v3/repos/{owner}/{repo}/git/refs/{path}

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.

Body (JSON):

NameTypeRequiredDescription
shastringyesNew target commit.
forcebooleannoAllow a non-fast-forward update.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/git/refs/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sha":"..."}'

Delete a reference

DELETE /api/v3/repos/{owner}/{repo}/git/refs/{path}

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
pathstringyesPath inside the repository, or a ref name after refs/.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/git/refs/README.md" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a tag object

POST /api/v3/repos/{owner}/{repo}/git/tags

Writes an annotated tag object only; create its refs/tags/... reference with POST /repos/{owner}/{repo}/git/refs to publish it.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
tagstringyesTag name.
objectstringyesSHA of the object to tag.
messagestringnoTag message.
typestringnocommit, tree, blob or tag; must match the object (default: its type).
taggerobjectno{ name, email, date } (default: you).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/git/tags" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tag":"...","object":"..."}'

Get a tag object

GET /api/v3/repos/{owner}/{repo}/git/tags/{sha}

verification.verified is always false.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha
curl "https://diffinery.com/api/v3/repos/acme/website/git/tags/sha" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a tree

POST /api/v3/repos/{owner}/{repo}/git/trees

Applies the entries on top of base_tree. An entry with content creates a blob (push protection applies); one with sha: null deletes the path. type is ignored: the mode decides. At most 10000 entries per request.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
treearrayyesEntries: { path, mode, sha } or { path, mode, content }. mode is 100644 (default), 100755, 040000, 160000 or 120000.
base_treestringnoTree to start from (default: an empty tree).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/git/trees" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tree":[]}'

Get a tree

GET /api/v3/repos/{owner}/{repo}/git/trees/{sha}

sha may be a tree, a commit or a ref. truncated is true when a recursive listing stopped at 100000 entries.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha

Query parameters:

NameTypeRequiredDescription
recursivestringnoAny value but 0 or false lists every entry below, not just the top level.
curl "https://diffinery.com/api/v3/repos/acme/website/git/trees/sha" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Branches and tags

MethodPathSummary
GET/repos/{owner}/{repo}/branchesList branches
GET/repos/{owner}/{repo}/branches/{branch}Get a branch
POST/repos/{owner}/{repo}/mergesMerge a branch
GET/repos/{owner}/{repo}/tagsList tags

List branches

GET /api/v3/repos/{owner}/{repo}/branches

Each branch says whether it is protected and the default.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/branches" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a branch

GET /api/v3/repos/{owner}/{repo}/branches/{branch}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
branchstringyesBranch name (for protection rules: a branch name or pattern).
curl "https://diffinery.com/api/v3/repos/acme/website/branches/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Merge a branch

POST /api/v3/repos/{owner}/{repo}/merges

Merges head into the base branch with a merge commit. Returns 201 with the commit, 204 when base already contains head, 409 on a conflict and 404 when either doesn't exist. Branch protection and agent rules apply as they do to a push.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
basestringyesBranch to merge into.
headstringyesBranch, tag or commit to merge.
commit_messagestringnoCommit message (default: Merge {head} into {base}).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/merges" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"base":"...","head":"..."}'

List tags

GET /api/v3/repos/{owner}/{repo}/tags

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/tags" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Commit statuses

MethodPathSummary
GET/repos/{owner}/{repo}/commits/{ref}/statusGet the combined status
GET/repos/{owner}/{repo}/commits/{ref}/statusesList commit statuses
GET/repos/{owner}/{repo}/deployments/{id}/statuses/{status}Get a deployment status
GET/repos/{owner}/{repo}/statuses/{ref}List commit statuses for a ref
POST/repos/{owner}/{repo}/statuses/{sha}Create a commit status

Get the combined status

GET /api/v3/repos/{owner}/{repo}/commits/{ref}/status

The latest status per context and an overall state: failure if any is error or failure, pending if any is pending or there are none, else success. Check runs aren't included.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoStatuses per page (default 100, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/main/status" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List commit statuses

GET /api/v3/repos/{owner}/{repo}/commits/{ref}/statuses

Every status for the commit, newest first, including older ones for the same context.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/main/statuses" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a deployment status

GET /api/v3/repos/{owner}/{repo}/deployments/{id}/statuses/{status}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
statusstringyesstatus
curl "https://diffinery.com/api/v3/repos/acme/website/deployments/1/statuses/status" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List commit statuses for a ref

GET /api/v3/repos/{owner}/{repo}/statuses/{ref}

Same as GET /repos/{owner}/{repo}/commits/{ref}/statuses.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/statuses/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a commit status

POST /api/v3/repos/{owner}/{repo}/statuses/{sha}

sha may also be a branch or tag. Statuses show with the checks, and a required check in branch protection can name a context; one account's status never replaces another's for that. At most 1000 statuses per commit and context. Sends the status webhook. See Checks and statuses.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha

Body (JSON):

NameTypeRequiredDescription
statestringyeserror, failure, pending or success.
target_urlstringnohttp(s) link to details.
descriptionstringnoShort description (cut at 1024 characters).
contextstringnoLabel that tells statuses apart (default default).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/statuses/sha" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

Checks

MethodPathSummary
POST/repos/{owner}/{repo}/check-runsCreate or update a check run
GET/repos/{owner}/{repo}/check-runs/{id}Get a check run
PATCH/repos/{owner}/{repo}/check-runs/{id}Update a check run
GET/repos/{owner}/{repo}/check-runs/{id}/annotationsList check run annotations
GET/repos/{owner}/{repo}/check-suites/{id}Get a check suite
GET/repos/{owner}/{repo}/check-suites/{id}/check-runsList a check suite's check runs
GET/repos/{owner}/{repo}/commits/{ref}/check-runsList check runs for a commit
GET/repos/{owner}/{repo}/commits/{ref}/check-suitesList check suites for a commit

Create or update a check run

POST /api/v3/repos/{owner}/{repo}/check-runs

For external CI and integrations. A check with the same name on the same commit is updated. Required checks in branch protection can name it.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
namestringyesCheck name.
head_shastringyesCommit the check is for.
statusstringnoqueued (default), in_progress or completed.
conclusionstringnoWith completed: success, failure, neutral, cancelled, skipped or timed_out.
details_urlstringnoLink to more detail.
outputobjectno{ title, summary }.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/check-runs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"...","head_sha":"..."}'

Get a check run

GET /api/v3/repos/{owner}/{repo}/check-runs/{id}

id is the numeric id, Diffinery's own, or the id of the Actions job that reports it (a job's check_run_url points here).

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/check-runs/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a check run

PATCH /api/v3/repos/{owner}/{repo}/check-runs/{id}

Only the account that created the check run can update it, and runs from Diffinery Actions can't be changed. A conclusion completes the run. Annotations add to the existing ones (50 per request, 1000 in all).

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
namestringnoNew name.
statusstringnoqueued, in_progress, completed, waiting, requested or pending.
conclusionstringnoaction_required, cancelled, failure, neutral, success, skipped, stale or timed_out.
details_urlstringnohttp(s) link to more detail.
external_idstringnoYour own reference for the run.
started_atstringnoISO timestamp.
completed_atstringnoISO timestamp.
outputobjectno{ title, summary, text, annotations }.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/check-runs/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List check run annotations

GET /api/v3/repos/{owner}/{repo}/check-runs/{id}/annotations

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/check-runs/1/annotations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a check suite

GET /api/v3/repos/{owner}/{repo}/check-suites/{id}

id is a workflow run id or app-{app}-{sha}.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/check-suites/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a check suite's check runs

GET /api/v3/repos/{owner}/{repo}/check-suites/{id}/check-runs

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/check-suites/1/check-runs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List check runs for a commit

GET /api/v3/repos/{owner}/{repo}/commits/{ref}/check-runs

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/main/check-runs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List check suites for a commit

GET /api/v3/repos/{owner}/{repo}/commits/{ref}/check-suites

Diffinery derives check suites from check runs: one per workflow run, and one per app (id app-{app}-{sha}) for external check runs. head_branch is always null and pull_requests empty.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/main/check-suites" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Commits

MethodPathSummary
GET/repos/{owner}/{repo}/commitsList commits
GET/repos/{owner}/{repo}/commits/{ref}Get a commit
GET/repos/{owner}/{repo}/commits/{sha}/pullsList pull requests for a commit
GET/repos/{owner}/{repo}/compare/{spec}Compare two refs
GET/repos/{owner}/{repo}/pulls/{number}/commitsList a pull request's commits

List commits

GET /api/v3/repos/{owner}/{repo}/commits

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
shastringnoBranch, tag or commit to start from (default: the default branch).
pathstringnoOnly commits that touch this path.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/commits" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a commit

GET /api/v3/repos/{owner}/{repo}/commits/{ref}

The commit with its diff.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
refstringyesBranch, tag or commit SHA.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List pull requests for a commit

GET /api/v3/repos/{owner}/{repo}/commits/{sha}/pulls

Pull requests whose head or merge commit is this commit, plus open pull requests (the 50 newest) that contain it. 422 when the commit doesn't exist.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
shastringyessha

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/commits/sha/pulls" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Compare two refs

GET /api/v3/repos/{owner}/{repo}/compare/{spec}

spec is base...head.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
specstringyesTwo refs as base...head.
curl "https://diffinery.com/api/v3/repos/acme/website/compare/main...feature" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a pull request's commits

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/commits

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/commits" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Branch protection

MethodPathSummary
GET/repos/{owner}/{repo}/branches/{branch}/protectionGet a protection rule
PUT/repos/{owner}/{repo}/branches/{branch}/protectionCreate or replace a protection rule
DELETE/repos/{owner}/{repo}/branches/{branch}/protectionDelete a protection rule

Get a protection rule

GET /api/v3/repos/{owner}/{repo}/branches/{branch}/protection

branch is the rule's pattern.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
branchstringyesBranch name (for protection rules: a branch name or pattern).
curl "https://diffinery.com/api/v3/repos/acme/website/branches/main/protection" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create or replace a protection rule

PUT /api/v3/repos/{owner}/{repo}/branches/{branch}/protection

branch is a branch name or pattern. People only: agents and workflow tokens can't change protection. allowAgentAutoMerge (boolean) lets agents land pull requests through auto-merge or the merge queue; turning it on or off is audited as repo.protection.agent_auto_merge. agentAutoMergeWithoutApproval (boolean, needs allowAgentAutoMerge) lets those landings go through on green required checks without a person's approval, audited as repo.protection.agent_approval_waiver. autoMergeAgents (agent logins, needs allowAgentAutoMerge) has Diffinery turn auto-merge on by itself, as the agent, for pull requests those agents open, mark ready or push to, with autoMergeMethod (merge, squash or rebase) for how they merge; the answer stores them as { id, login }, and changes are audited as repo.protection.agent_auto_merge_rule. See the branch protection guide for every field.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
branchstringyesBranch name (for protection rules: a branch name or pattern).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/branches/main/protection" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a protection rule

DELETE /api/v3/repos/{owner}/{repo}/branches/{branch}/protection

Audited as repo.protection.delete.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
branchstringyesBranch name (for protection rules: a branch name or pattern).
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/branches/main/protection" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Issues

MethodPathSummary
GET/repos/{owner}/{repo}/issuesList issues and pull requests
POST/repos/{owner}/{repo}/issuesCreate an issue
GET/repos/{owner}/{repo}/issues/{number}Get an issue
PATCH/repos/{owner}/{repo}/issues/{number}Update an issue
POST/repos/{owner}/{repo}/issues/{number}/assigneesAdd assignees
DELETE/repos/{owner}/{repo}/issues/{number}/assigneesRemove assignees
GET/repos/{owner}/{repo}/issues/{number}/commentsList comments
POST/repos/{owner}/{repo}/issues/{number}/commentsAdd a comment
GET/repos/{owner}/{repo}/issues/{number}/eventsList an issue's events
GET/repos/{owner}/{repo}/issues/{number}/labelsList an issue's labels
POST/repos/{owner}/{repo}/issues/{number}/labelsAdd labels to an issue
PUT/repos/{owner}/{repo}/issues/{number}/labelsReplace an issue's labels
DELETE/repos/{owner}/{repo}/issues/{number}/labelsRemove all labels from an issue
DELETE/repos/{owner}/{repo}/issues/{number}/labels/{name}Remove a label from an issue
PUT/repos/{owner}/{repo}/issues/{number}/lockLock a conversation
DELETE/repos/{owner}/{repo}/issues/{number}/lockUnlock a conversation
GET/repos/{owner}/{repo}/issues/{number}/reactionsList reactions to an issue
POST/repos/{owner}/{repo}/issues/{number}/reactionsAdd a reaction to an issue
DELETE/repos/{owner}/{repo}/issues/{number}/reactions/{reaction}Delete a reaction from an issue
GET/repos/{owner}/{repo}/issues/{number}/timelineList an issue's timeline
GET/repos/{owner}/{repo}/issues/commentsList comments in a repository
GET/repos/{owner}/{repo}/issues/comments/{id}Get a comment
PATCH/repos/{owner}/{repo}/issues/comments/{id}Edit a comment
DELETE/repos/{owner}/{repo}/issues/comments/{id}Delete a comment
GET/repos/{owner}/{repo}/issues/comments/{id}/reactionsList reactions to a comment
POST/repos/{owner}/{repo}/issues/comments/{id}/reactionsAdd a reaction to a comment
DELETE/repos/{owner}/{repo}/issues/comments/{id}/reactions/{reaction}Delete a reaction from a comment
GET/repos/{owner}/{repo}/issues/eventsList events in a repository
GET/repos/{owner}/{repo}/issues/events/{id}Get an event
GET/repos/{owner}/{repo}/labelsList labels
POST/repos/{owner}/{repo}/labelsCreate a label
GET/repos/{owner}/{repo}/labels/{name}Get a label
PATCH/repos/{owner}/{repo}/labels/{name}Update a label
DELETE/repos/{owner}/{repo}/labels/{name}Delete a label
GET/repos/{owner}/{repo}/milestonesList milestones
POST/repos/{owner}/{repo}/milestonesCreate a milestone
GET/repos/{owner}/{repo}/milestones/{number}Get a milestone
PATCH/repos/{owner}/{repo}/milestones/{number}Update a milestone

List issues and pull requests

GET /api/v3/repos/{owner}/{repo}/issues

As on GitHub, this list includes pull requests. The total is in the X-Total-Count header.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
statestringnoopen (default), closed or all.
labelsstringnoOnly items with this label.
creatorstringnoOnly items opened by this login.
milestonestringnoA milestone number, none (no milestone) or * (any milestone).
qstringnoText search in titles.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an issue

POST /api/v3/repos/{owner}/{repo}/issues

Needs a signed-in caller, also on a public repository. As on GitHub, labels and assignees from a caller without triage access are dropped without an error.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
titlestringyesTitle.
bodystringnoMarkdown body.
labelsstring[]noLabel names.
assigneesstring[]noLogins.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"..."}'

Get an issue

GET /api/v3/repos/{owner}/{repo}/issues/{number}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update an issue

PATCH /api/v3/repos/{owner}/{repo}/issues/{number}

The author can edit their own issue or pull request. As on GitHub, labels, assignees and milestone from a caller without triage access are dropped without an error.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
titlestringnoNew title.
bodystringnoNew body.
statestringnoopen or closed.
state_reasonstringnoWhy it was closed, like completed or not_planned.
labelsstring[]noReplace the labels.
assigneesstring[]noReplace the assignees.
milestoneintegernoMilestone number, or null to remove the milestone. Ignored without triage access. Checked before anything is saved: 422 when it isn't a whole number or null, or when no milestone has that number.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/issues/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add assignees

POST /api/v3/repos/{owner}/{repo}/issues/{number}/assignees

Adds to the current assignees, at most 10 in all. Logins aren't checked against who can be assigned. Returns the issue.

Access: Triage access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
assigneesstring[]noLogins to add.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues/42/assignees" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove assignees

DELETE /api/v3/repos/{owner}/{repo}/issues/{number}/assignees

Returns the issue.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
assigneesstring[]noLogins to remove.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/42/assignees" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List comments

GET /api/v3/repos/{owner}/{repo}/issues/{number}/comments

Conversation comments on an issue or pull request (not review comments).

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
sincestringnoOnly comments updated at or after this ISO timestamp.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a comment

POST /api/v3/repos/{owner}/{repo}/issues/{number}/comments

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
bodystringyesMarkdown body.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues/42/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

List an issue's events

GET /api/v3/repos/{owner}/{repo}/issues/{number}/events

Labels, assignments, state changes, locks, review requests and the like, oldest first.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42/events" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List an issue's labels

GET /api/v3/repos/{owner}/{repo}/issues/{number}/labels

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add labels to an issue

POST /api/v3/repos/{owner}/{repo}/issues/{number}/labels

Labels that don't exist yet are created. At most 100 per issue. Returns the issue's labels.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
labelsstring[]yesLabel names ({ name } objects, or a bare array as the body, work too).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues/42/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"labels":["..."]}'

Replace an issue's labels

PUT /api/v3/repos/{owner}/{repo}/issues/{number}/labels

Labels that don't exist yet are created; [] removes them all. Returns the issue's labels.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
labelsstring[]yesLabel names ({ name } objects, or a bare array as the body, work too).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/issues/42/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"labels":["..."]}'

Remove all labels from an issue

DELETE /api/v3/repos/{owner}/{repo}/issues/{number}/labels

Access: Triage access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/42/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove a label from an issue

DELETE /api/v3/repos/{owner}/{repo}/issues/{number}/labels/{name}

Returns the labels left. 404 when the issue doesn't have it.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/42/labels/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Lock a conversation

PUT /api/v3/repos/{owner}/{repo}/issues/{number}/lock

While locked, only people with triage access can comment, review or react.

Access: Triage access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
lock_reasonstringnooff-topic, too heated, resolved or spam.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/issues/42/lock" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Unlock a conversation

DELETE /api/v3/repos/{owner}/{repo}/issues/{number}/lock

Access: Triage access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/42/lock" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reactions to an issue

GET /api/v3/repos/{owner}/{repo}/issues/{number}/reactions

Works for pull requests too.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
contentstringnoOnly reactions with this content.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a reaction to an issue

POST /api/v3/repos/{owner}/{repo}/issues/{number}/reactions

Needs a signed-in account, and triage access when the conversation is locked. Returns 201 for a new reaction, or 200 with the existing one when you had already reacted with that content.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
contentstringyes+1, -1, laugh, confused, heart, hooray, rocket or eyes.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues/42/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"..."}'

Delete a reaction from an issue

DELETE /api/v3/repos/{owner}/{repo}/issues/{number}/reactions/{reaction}

Your own reactions, or anyone's with admin access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
reactionstringyesreaction
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/42/reactions/reaction" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List an issue's timeline

GET /api/v3/repos/{owner}/{repo}/issues/{number}/timeline

Events, comments (commented) and reviews (reviewed) together, oldest first.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/42/timeline" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List comments in a repository

GET /api/v3/repos/{owner}/{repo}/issues/comments

Conversation comments on every issue and pull request.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
sincestringnoOnly comments updated at or after this ISO timestamp.
sortstringnocreated (default) or updated.
directionstringnoasc (default) or desc.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a comment

GET /api/v3/repos/{owner}/{repo}/issues/comments/{id}

id is the numeric id or Diffinery's own.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Edit a comment

PATCH /api/v3/repos/{owner}/{repo}/issues/comments/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
bodystringyesNew Markdown body.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

Delete a comment

DELETE /api/v3/repos/{owner}/{repo}/issues/comments/{id}

Your own comments, or anyone's with maintain access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reactions to a comment

GET /api/v3/repos/{owner}/{repo}/issues/comments/{id}/reactions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
contentstringnoOnly reactions with this content.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a reaction to a comment

POST /api/v3/repos/{owner}/{repo}/issues/comments/{id}/reactions

Needs a signed-in account, and triage access when the conversation is locked. Returns 201 for a new reaction, or 200 with the existing one when you had already reacted with that content.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
contentstringyes+1, -1, laugh, confused, heart, hooray, rocket or eyes.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"..."}'

Delete a reaction from a comment

DELETE /api/v3/repos/{owner}/{repo}/issues/comments/{id}/reactions/{reaction}

Your own reactions, or anyone's with admin access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
reactionstringyesreaction
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/issues/comments/1/reactions/reaction" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List events in a repository

GET /api/v3/repos/{owner}/{repo}/issues/events

Events on every issue and pull request, newest first, each with its issue.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/events" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an event

GET /api/v3/repos/{owner}/{repo}/issues/events/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/issues/events/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List labels

GET /api/v3/repos/{owner}/{repo}/labels

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a label

POST /api/v3/repos/{owner}/{repo}/labels

422 when a label with that name exists; change one with PATCH /repos/{owner}/{repo}/labels/{name}.

Access: Triage access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
namestringyesLabel name, at most 100 characters.
colorstringno6-digit hex color, with or without # (default ededed).
descriptionstringnoDescription.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/labels" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'

Get a label

GET /api/v3/repos/{owner}/{repo}/labels/{name}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.
curl "https://diffinery.com/api/v3/repos/acme/website/labels/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a label

PATCH /api/v3/repos/{owner}/{repo}/labels/{name}

Renaming it renames it on every issue too.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
new_namestringnoNew name.
colorstringno6-digit hex color, with or without #.
descriptionstringnoDescription.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/labels/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a label

DELETE /api/v3/repos/{owner}/{repo}/labels/{name}

Also removes it from every issue.

Access: Triage access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/labels/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List milestones

GET /api/v3/repos/{owner}/{repo}/milestones

Every milestone in the state you ask for (no paging), ordered by due date (milestones without one last), then by number. The id is the milestone number. Milestones come from GitHub imports or are created with the endpoint below; the web UI sets an issue's milestone but doesn't create milestones.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
statestringnoopen (default), closed or all. Anything else is 422.
curl "https://diffinery.com/api/v3/repos/acme/website/milestones" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a milestone

POST /api/v3/repos/{owner}/{repo}/milestones

New milestones are open unless state is closed. There is no endpoint to delete a milestone.

Access: Triage access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
titlestringyes1 to 255 characters.
descriptionstringnoAt most 65,536 characters.
statestringnoopen (default) or closed.
due_onstringnoISO 8601 timestamp, or null.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/milestones" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"..."}'

Get a milestone

GET /api/v3/repos/{owner}/{repo}/milestones/{number}

number is the milestone number. 404 milestone not found.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/milestones/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a milestone

PATCH /api/v3/repos/{owner}/{repo}/milestones/{number}

Send only the fields you change. Closing records closed_at; reopening clears it.

Access: Triage access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
titlestringno1 to 255 characters.
descriptionstringnoAt most 65,536 characters.
statestringnoopen or closed.
due_onstringnoISO 8601 timestamp, or null to clear it.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/milestones/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Pull requests

MethodPathSummary
GET/repos/{owner}/{repo}/pullsList pull requests
POST/repos/{owner}/{repo}/pullsOpen a pull request
GET/repos/{owner}/{repo}/pulls/{number}Get a pull request
PATCH/repos/{owner}/{repo}/pulls/{number}Update a pull request
PUT/repos/{owner}/{repo}/pulls/{number}/auto-mergeEnable auto-merge
DELETE/repos/{owner}/{repo}/pulls/{number}/auto-mergeDisable auto-merge
GET/repos/{owner}/{repo}/pulls/{number}/commentsList review comments
POST/repos/{owner}/{repo}/pulls/{number}/commentsCreate a review comment
POST/repos/{owner}/{repo}/pulls/{number}/comments/{id}/repliesReply to a review comment
GET/repos/{owner}/{repo}/pulls/{number}/diffinery/agent-reviewGet a pull request's agent review
POST/repos/{owner}/{repo}/pulls/{number}/diffinery/agent-reviewAsk for an agent review
GET/repos/{owner}/{repo}/pulls/{number}/filesList changed files
GET/repos/{owner}/{repo}/pulls/{number}/mergeCheck mergeability
PUT/repos/{owner}/{repo}/pulls/{number}/mergeMerge a pull request
GET/repos/{owner}/{repo}/pulls/{number}/requested_reviewersList requested reviewers
POST/repos/{owner}/{repo}/pulls/{number}/requested_reviewersRequest reviewers
DELETE/repos/{owner}/{repo}/pulls/{number}/requested_reviewersRemove requested reviewers
GET/repos/{owner}/{repo}/pulls/{number}/reviewsList reviews
POST/repos/{owner}/{repo}/pulls/{number}/reviewsSubmit a review
GET/repos/{owner}/{repo}/pulls/{number}/reviews/{id}Get a review
PUT/repos/{owner}/{repo}/pulls/{number}/reviews/{id}/dismissalsDismiss a review
PUT/repos/{owner}/{repo}/pulls/{number}/update-branchUpdate a pull request's branch
GET/repos/{owner}/{repo}/pulls/commentsList review comments in a repository
GET/repos/{owner}/{repo}/pulls/comments/{id}Get a review comment
PATCH/repos/{owner}/{repo}/pulls/comments/{id}Edit a review comment
DELETE/repos/{owner}/{repo}/pulls/comments/{id}Delete a review comment
GET/repos/{owner}/{repo}/pulls/comments/{id}/reactionsList reactions to a review comment
POST/repos/{owner}/{repo}/pulls/comments/{id}/reactionsAdd a reaction to a review comment
DELETE/repos/{owner}/{repo}/pulls/comments/{id}/reactions/{reaction}Delete a reaction from a review comment

List pull requests

GET /api/v3/repos/{owner}/{repo}/pulls

The total is in the X-Total-Count header.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
statestringnoopen (default), closed or all.
labelsstringnoOnly pull requests with this label.
creatorstringnoOnly pull requests opened by this login.
qstringnoText search in titles.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Open a pull request

POST /api/v3/repos/{owner}/{repo}/pulls

A workflow's GITHUB_TOKEN can open one only when the repository allows workflows to create pull requests (can_approve_pull_request_reviews, see PUT /repos/{owner}/{repo}/actions/permissions/workflow); otherwise 403.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
titlestringyesTitle.
headstringyesBranch with the changes (owner:branch also works).
basestringnoBranch to merge into (default: the default branch).
bodystringnoMarkdown description.
intentstringnoDiffinery: what the change is meant to do, shown to reviewers.
draftbooleannoOpen as a draft.
reviewersstring[]noLogins to request reviews from.
auto_mergebooleannoDiffinery: true turns on auto-merge as it opens, false keeps it off where your setting would turn it on. When asked for and it stayed off (for example, the base branch has no required checks), the answer's auto_merge_skipped says why. See /docs/collaboration/merge-on-green.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"...","head":"..."}'

Get a pull request

GET /api/v3/repos/{owner}/{repo}/pulls/{number}

Includes mergeable, mergeable_state, merge_blockers (why it can't merge yet), approvals, required_approvals and checks.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a pull request

PATCH /api/v3/repos/{owner}/{repo}/pulls/{number}

The author, or anyone with triage access. base isn't supported and is ignored. A merged pull request can't be reopened. A title or body change sends a pull_request edited event. draft is a Diffinery extension (GitHub only offers it through GraphQL): the author or anyone with write access can set it on an open pull request. It records a ready_for_review or convert_to_draft timeline event and sends the pull_request webhook with the action ready_for_review or converted_to_draft.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
titlestringnoNew title.
bodystringnoNew description.
statestringnoopen or closed.
draftbooleannofalse marks it ready for review; true converts it back to a draft.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/pulls/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Enable auto-merge

PUT /api/v3/repos/{owner}/{repo}/pulls/{number}/auto-merge

Diffinery's REST form of GitHub's enablePullRequestAutoMerge. Diffinery merges the pull request by itself as soon as every rule of its base branch is met (required checks on the head, approvals from people, linear history), as the caller, never bypassing anything; into a branch with a merge queue it adds it to the queue instead. Returns { state, auto_merge, merge_commit_sha }: state is enabled (waiting), queued or merged (it was ready). The pull request's auto_merge shows it until then. A push to the head branch by anyone else, or converting the pull request to a draft, turns it off. 422 for a draft, a closed or merged pull request, or one already in the merge queue. Agents and workflow tokens may use it on the default branch or a protected one only when its rule sets allowAgentAutoMerge (else 403) and has at least one required check (else 422); a workflow token needs contents: write. Audited as pull_request.auto_merge_enabled, and the merge as pull_request.auto_merged.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
merge_methodstringnomerge, squash or rebase (default: the queue's method, squash where linear history is required, else merge).
commit_titlestringnoTitle of the merge or squash commit.
commit_messagestringnoBody of the merge or squash commit.
delete_branchbooleannoDelete the head branch once auto-merge lands the pull request, directly or through the queue (never the default branch or a protected one). 422 delete_branch must be a boolean otherwise.
shastringnoTurn auto-merge on only if the head is still this commit (409 if it moved).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/pulls/42/auto-merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Disable auto-merge

DELETE /api/v3/repos/{owner}/{repo}/pulls/{number}/auto-merge

GitHub's disablePullRequestAutoMerge. Anyone with write access may turn it off, whoever turned it on; a workflow token needs contents: write. 204 even when it was off, which records nothing. Otherwise it records an auto_merge_disabled event, sends a pull_request webhook with that action, and is audited as pull_request.auto_merge_disabled.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/pulls/42/auto-merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List review comments

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/comments

Line comments from reviews.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a review comment

POST /api/v3/repos/{owner}/{repo}/pulls/{number}/comments

Adds one line comment as its own COMMENTED review, on the current head; commit_id is ignored and position is read as a line number, not a diff position. Multi-line comments aren't supported. With in_reply_to, replies to that comment instead. 422 on a closed pull request.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
bodystringyesMarkdown body.
pathstringnoFile path (required unless replying).
lineintegernoLine number (required unless replying).
sidestringnoRIGHT (default) or LEFT.
positionintegernoUsed as line when line is missing.
commit_idstringnoAccepted and ignored.
in_reply_tointegernoReview comment id to reply to; its path and line are used.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/42/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

Reply to a review comment

POST /api/v3/repos/{owner}/{repo}/pulls/{number}/comments/{id}/replies

Adds a reply on the same line, as its own COMMENTED review.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
bodystringyesMarkdown body.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/42/comments/1/replies" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

Get a pull request's agent review

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/diffinery/agent-review

The pull request's review task (each review is a run of it), the last reviewed head (reviewed_sha) and every finding: id, path, line, side, severity (blocking or not_blocking), title, body, suggestion, state (open, fixed or dismissed), fixed_in and the review comment_id. Needs write access.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/diffinery/agent-review" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Ask for an agent review

POST /api/v3/repos/{owner}/{repo}/pulls/{number}/diffinery/agent-review

Reviews the pull request now, or once its current review ends, whatever the trigger setting. People with write access only (any of their tokens); agents can't ask. 422 when agent review is off; 429 past a daily limit (the repository's, or 20 reviews of one pull request in 24 hours). Audited as review.request.

Access: Write access to the repository. Tokens need the write scope. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/42/diffinery/agent-review" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List changed files

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/files

Each file with its status, additions, deletions and patch.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/files" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Check mergeability

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/merge

Whether the pull request can merge now, and if not, the blockers.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Merge a pull request

PUT /api/v3/repos/{owner}/{repo}/pulls/{number}/merge

Fails with 405 and the blockers when protection rules aren't met, and with 405 when a merge commit is asked for on a branch that requires linear history (without merge_method, such a branch squashes). A branch that requires a merge queue answers 405 too: add the pull request to the queue instead. A repository admin (a person, not an agent or a workflow) can bypass, when the rule doesn't include administrators, there are no conflicts and the pull request isn't a draft. Each flag covers only what it names: bypass_rules: true skips unmet rules and linear history, and bypass_merge_queue: true skips only the queue. A bypass that skipped an unmet rule, linear history or the queue is audited as pull_request.merge_bypassed. Agents can't merge into the default branch or a protected branch themselves (unless the rule sets agentsMayMerge); where it sets allowAgentAutoMerge they turn on auto-merge (PUT .../auto-merge) instead.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
merge_methodstringnomerge, squash or rebase.
commit_titlestringnoTitle of the merge or squash commit.
commit_messagestringnoBody of the merge or squash commit.
shastringnoFail if the head has moved from this commit.
delete_branchbooleannoDelete the head branch after merging.
bypass_merge_queuebooleannoMerge directly even when a queue is required (admins). Doesn't skip unmet rules; send bypass_rules too for that.
bypass_rulesbooleannoMerge even though protection rules (including linear history) aren't met (admins). Without it, an admin's merge is blocked like anyone else's.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/pulls/42/merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List requested reviewers

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/requested_reviewers

Returns { users, teams }; teams is always empty.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/requested_reviewers" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Request reviewers

POST /api/v3/repos/{owner}/{repo}/pulls/{number}/requested_reviewers

The author, or anyone with triage access. Team reviewers aren't supported: a non-empty team_reviewers fails with 422. Sends the pull_request webhook (review_requested). Returns the pull request.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
reviewersstring[]noLogins.
team_reviewersstring[]noMust be empty or absent.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/42/requested_reviewers" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove requested reviewers

DELETE /api/v3/repos/{owner}/{repo}/pulls/{number}/requested_reviewers

The author, or anyone with triage access. Teams aren't supported. Returns the pull request.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
reviewersstring[]noLogins to remove.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/pulls/42/requested_reviewers" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reviews

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/reviews

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/reviews" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Submit a review

POST /api/v3/repos/{owner}/{repo}/pulls/{number}/reviews

Only people's approvals count toward required approvals: agents' and workflows' don't. A workflow's GITHUB_TOKEN can approve or request changes only when the repository allows it (can_approve_pull_request_reviews); otherwise 403.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
eventstringnoAPPROVE, REQUEST_CHANGES or COMMENT (default).
bodystringnoReview summary.
commentsarraynoLine comments: { path, line, side: "LEFT" | "RIGHT", body }.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/42/reviews" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a review

GET /api/v3/repos/{owner}/{repo}/pulls/{number}/reviews/{id}

id is the numeric id or Diffinery's own.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/42/reviews/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Dismiss a review

PUT /api/v3/repos/{owner}/{repo}/pulls/{number}/reviews/{id}/dismissals

Only approvals and change requests can be dismissed. Needs maintain access; agents and the pull request's author can't dismiss. event is ignored. Returns the review.

Access: Maintain access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
messagestringyesWhy the review is dismissed.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/pulls/42/reviews/1/dismissals" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"..."}'

Update a pull request's branch

PUT /api/v3/repos/{owner}/{repo}/pulls/{number}/update-branch

Merges the base branch into the head branch right away, then answers 202 as GitHub does. 422 when the base has no new commits, on a conflict, or when expected_head_sha doesn't match. Branch protection and agent rules apply to the head branch.

Access: Write access to the repository. Tokens need the write scope. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
expected_head_shastringnoFail unless the head branch is at this commit.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/pulls/42/update-branch" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List review comments in a repository

GET /api/v3/repos/{owner}/{repo}/pulls/comments

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
sincestringnoOnly comments updated at or after this ISO timestamp.
sortstringnocreated (default) or updated.
directionstringnoasc (default) or desc.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/comments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a review comment

GET /api/v3/repos/{owner}/{repo}/pulls/comments/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Edit a review comment

PATCH /api/v3/repos/{owner}/{repo}/pulls/comments/{id}

Your own comments, or anyone's with maintain access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
bodystringyesNew Markdown body.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

Delete a review comment

DELETE /api/v3/repos/{owner}/{repo}/pulls/comments/{id}

Your own comments, or anyone's with maintain access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reactions to a review comment

GET /api/v3/repos/{owner}/{repo}/pulls/comments/{id}/reactions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
contentstringnoOnly reactions with this content.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a reaction to a review comment

POST /api/v3/repos/{owner}/{repo}/pulls/comments/{id}/reactions

Needs a signed-in account, and triage access when the conversation is locked. Returns 201 for a new reaction, or 200 with the existing one when you had already reacted with that content.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
contentstringyes+1, -1, laugh, confused, heart, hooray, rocket or eyes.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1/reactions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"..."}'

Delete a reaction from a review comment

DELETE /api/v3/repos/{owner}/{repo}/pulls/comments/{id}/reactions/{reaction}

Your own reactions, or anyone's with admin access.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
reactionstringyesreaction
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/pulls/comments/1/reactions/reaction" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Merge queue

MethodPathSummary
GET/repos/{owner}/{repo}/merge-queue/{branch}Get a branch's merge queue
PUT/repos/{owner}/{repo}/pulls/{number}/merge-queueAdd a pull request to the merge queue
DELETE/repos/{owner}/{repo}/pulls/{number}/merge-queueRemove a pull request from the merge queue

Get a branch's merge queue

GET /api/v3/repos/{owner}/{repo}/merge-queue/{branch}

Diffinery only (GitHub exposes this through GraphQL). Settings and every entry with its merge group and checks.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
branchstringyesBranch name (for protection rules: a branch name or pattern).
curl "https://diffinery.com/api/v3/repos/acme/website/merge-queue/main" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Add a pull request to the merge queue

PUT /api/v3/repos/{owner}/{repo}/pulls/{number}/merge-queue

Diffinery only. Returns 201 with the entry when queued.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
merge_methodstringnomerge, squash or rebase (default: the queue's method).
delete_branchbooleannoDelete the head branch once merged.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/pulls/42/merge-queue" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove a pull request from the merge queue

DELETE /api/v3/repos/{owner}/{repo}/pulls/{number}/merge-queue

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/pulls/42/merge-queue" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Deployments

MethodPathSummary
GET/repos/{owner}/{repo}/deploymentsList deployments
POST/repos/{owner}/{repo}/deploymentsCreate a deployment
GET/repos/{owner}/{repo}/deployments/{id}Get a deployment
DELETE/repos/{owner}/{repo}/deployments/{id}Delete a deployment
GET/repos/{owner}/{repo}/deployments/{id}/statusesList deployment statuses
POST/repos/{owner}/{repo}/deployments/{id}/statusesCreate a deployment status

List deployments

GET /api/v3/repos/{owner}/{repo}/deployments

Newest first. Each filter matches exactly.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
shastringnoFull commit SHA.
refstringnoRef, as given when the deployment was created.
taskstringnoTask name.
environmentstringnoEnvironment name.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/deployments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a deployment

POST /api/v3/repos/{owner}/{repo}/deployments

Unless required_contexts is [], every check and status on the commit (or each context you name) must have passed, else 409; checks and statuses reported by agents don't count toward the default set. Creates the environment if needed and sends the deployment webhook. Environment names are case-insensitive: an existing environment keeps its spelling, and any spelling of production is a production environment. auto_merge is ignored. See Environments.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
refstringyesBranch, tag or commit to deploy.
taskstringnoTask name (default deploy).
payloadobjectnoExtra data for the deployer (a string is kept as is).
environmentstringnoEnvironment name (default production).
descriptionstringnoShort description.
transient_environmentbooleannoTransient deployments aren't made inactive by later successful ones.
production_environmentbooleannoDefault: true when the environment is production.
required_contextsstring[]noContexts that must have passed; [] skips the check.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/deployments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ref":"..."}'

Get a deployment

GET /api/v3/repos/{owner}/{repo}/deployments/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/deployments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a deployment

DELETE /api/v3/repos/{owner}/{repo}/deployments/{id}

Refused with 422 while its latest status is success, unless it is the only deployment in its environment. Deletes its statuses too.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/deployments/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List deployment statuses

GET /api/v3/repos/{owner}/{repo}/deployments/{id}/statuses

Newest first.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/deployments/1/statuses" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a deployment status

POST /api/v3/repos/{owner}/{repo}/deployments/{id}/statuses

A success status marks older successful deployments to the same environment inactive (except transient and production ones) unless auto_inactive is false. A different environment moves the deployment there. Sends the deployment_status webhook.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
statestringyeserror, failure, inactive, in_progress, queued, pending or success.
log_urlstringnohttp(s) link to the deployment's output.
target_urlstringnoOlder name for log_url, used when log_url is missing.
environment_urlstringnohttp(s) link to the deployed environment.
descriptionstringnoShort description (cut at 140 characters).
environmentstringnoMove the deployment to this environment.
auto_inactivebooleannofalse keeps older deployments active (default true).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/deployments/1/statuses" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

Environments

MethodPathSummary
GET/repos/{owner}/{repo}/environmentsList environments
GET/repos/{owner}/{repo}/environments/{env}Get an environment
PUT/repos/{owner}/{repo}/environments/{env}Create or update an environment
DELETE/repos/{owner}/{repo}/environments/{env}Delete an environment
GET/repos/{owner}/{repo}/environments/{env}/deployment-branch-policiesList deployment branch policies
POST/repos/{owner}/{repo}/environments/{env}/deployment-branch-policiesCreate a deployment branch policy
DELETE/repos/{owner}/{repo}/environments/{env}/deployment-branch-policies/{id}Delete a deployment branch policy
GET/repos/{owner}/{repo}/environments/{env}/secretsList environment secrets
GET/repos/{owner}/{repo}/environments/{env}/secrets/{name}Get an environment secret
PUT/repos/{owner}/{repo}/environments/{env}/secrets/{name}Set an environment secret
DELETE/repos/{owner}/{repo}/environments/{env}/secrets/{name}Delete an environment secret
GET/repos/{owner}/{repo}/environments/{env}/variablesList environment variables
POST/repos/{owner}/{repo}/environments/{env}/variablesCreate an environment variable
GET/repos/{owner}/{repo}/environments/{env}/variables/{name}Get an environment variable
PATCH/repos/{owner}/{repo}/environments/{env}/variables/{name}Update an environment variable
DELETE/repos/{owner}/{repo}/environments/{env}/variables/{name}Delete an environment variable

List environments

GET /api/v3/repos/{owner}/{repo}/environments

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/environments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an environment

GET /api/v3/repos/{owner}/{repo}/environments/{env}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create or update an environment

PUT /api/v3/repos/{owner}/{repo}/environments/{env}

People only; agents can't change environments. Required reviewers and a wait timer hold a job that names the environment before anything starts, until a reviewer approves and the timer has passed. Fields left out keep their values. Audited. See Required reviewers and wait timers.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Body (JSON):

NameTypeRequiredDescription
deployment_branch_policyobjectno{ protected_branches, custom_branch_policies } with exactly one true, or null to allow every ref.
wait_timerintegernoMinutes a job waits before it deploys, 0 to 43200.
reviewersarraynoUp to 6 people with access, as {type: "User", id} (the numeric id the API shows) or {type: "User", login}. Never agents; Diffinery has no teams. [] or null removes them.
prevent_self_reviewbooleannoWhoever started a run (or an earlier attempt, or owns the agent that did) can't approve it.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/environments/env" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete an environment

DELETE /api/v3/repos/{owner}/{repo}/environments/{env}

Deletes its secrets and variables too. People only. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/environments/env" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List deployment branch policies

GET /api/v3/repos/{owner}/{repo}/environments/{env}/deployment-branch-policies

The branch and tag patterns of an environment with custom_branch_policies.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env/deployment-branch-policies" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a deployment branch policy

POST /api/v3/repos/{owner}/{repo}/environments/{env}/deployment-branch-policies

The environment must have custom_branch_policies. Tag patterns never match tags last pushed by an agent. People only. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Body (JSON):

NameTypeRequiredDescription
namestringyesBranch or tag name pattern, like release/*.
typestringnobranch (default) or tag.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/environments/env/deployment-branch-policies" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'

Delete a deployment branch policy

DELETE /api/v3/repos/{owner}/{repo}/environments/{env}/deployment-branch-policies/{id}

People only. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/environments/env/deployment-branch-policies/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List environment secrets

GET /api/v3/repos/{owner}/{repo}/environments/{env}/secrets

Names and dates only; values are never returned.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env/secrets" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an environment secret

GET /api/v3/repos/{owner}/{repo}/environments/{env}/secrets/{name}

Name and dates only.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set an environment secret

PUT /api/v3/repos/{owner}/{repo}/environments/{env}/secrets/{name}

People only. Names are upper-cased, and GITHUB_ names are refused. The value is encrypted at rest; GitHub's sealed-box encrypted_value isn't supported. The first secret on an environment without a branch policy limits it to protected branches. Returns 201 for a new secret and 204 for a replaced one. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
valuestringyesSecret value.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/environments/env/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value":"..."}'

Delete an environment secret

DELETE /api/v3/repos/{owner}/{repo}/environments/{env}/secrets/{name}

People only. Audited.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/environments/env/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List environment variables

GET /api/v3/repos/{owner}/{repo}/environments/{env}/variables

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 10, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an environment variable

POST /api/v3/repos/{owner}/{repo}/environments/{env}/variables

409 when it exists. Names are upper-cased, and GITHUB_ names are refused. People only. Audited as environment.variable.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv

Body (JSON):

NameTypeRequiredDescription
namestringyesVariable name.
valuestringyesVariable value.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/environments/env/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"...","value":"..."}'

Get an environment variable

GET /api/v3/repos/{owner}/{repo}/environments/{env}/variables/{name}

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.
curl "https://diffinery.com/api/v3/repos/acme/website/environments/env/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update an environment variable

PATCH /api/v3/repos/{owner}/{repo}/environments/{env}/variables/{name}

People only. Renaming onto a name that exists fails with 409. Audited as environment.variable.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
namestringnoNew name (renames the variable).
valuestringnoNew value.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/environments/env/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete an environment variable

DELETE /api/v3/repos/{owner}/{repo}/environments/{env}/variables/{name}

People only. Audited as environment.variable.delete.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
envstringyesenv
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/environments/env/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Actions secrets and variables

MethodPathSummary
GET/orgs/{org}/actions/secretsList organization secrets
GET/orgs/{org}/actions/secrets/{name}Get an organization secret
PUT/orgs/{org}/actions/secrets/{name}Set an organization secret
DELETE/orgs/{org}/actions/secrets/{name}Delete an organization secret
GET/orgs/{org}/actions/secrets/{name}/repositoriesList a secret's selected repositories
PUT/orgs/{org}/actions/secrets/{name}/repositoriesReplace a secret's selected repositories
PUT/orgs/{org}/actions/secrets/{name}/repositories/{repoId}Add a repository to a secret's selection
DELETE/orgs/{org}/actions/secrets/{name}/repositories/{repoId}Remove a repository from a secret's selection
GET/orgs/{org}/actions/variablesList organization variables
POST/orgs/{org}/actions/variablesCreate an organization variable
GET/orgs/{org}/actions/variables/{name}Get an organization variable
PATCH/orgs/{org}/actions/variables/{name}Update an organization variable
DELETE/orgs/{org}/actions/variables/{name}Delete an organization variable
GET/repos/{owner}/{repo}/actions/secretsList repository secrets
PUT/repos/{owner}/{repo}/actions/secrets/{name}Set a repository secret
DELETE/repos/{owner}/{repo}/actions/secrets/{name}Delete a repository secret
GET/repos/{owner}/{repo}/actions/variablesList repository variables
POST/repos/{owner}/{repo}/actions/variablesCreate a repository variable
GET/repos/{owner}/{repo}/actions/variables/{name}Get a repository variable
PUT/repos/{owner}/{repo}/actions/variables/{name}Set a repository variable
PATCH/repos/{owner}/{repo}/actions/variables/{name}Update a repository variable
DELETE/repos/{owner}/{repo}/actions/variables/{name}Delete a repository variable

List organization secrets

GET /api/v3/orgs/{org}/actions/secrets

Names, update times and visibility (all, private or selected), never values.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/actions/secrets" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an organization secret

GET /api/v3/orgs/{org}/actions/secrets/{name}

Its name, update time and visibility, never the value. 404 when there is no such secret.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
curl "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set an organization secret

PUT /api/v3/orgs/{org}/actions/secrets/{name}

Creates or updates the secret. visibility says which of the organization's repositories get it: all (the default for a new secret), private (private and internal ones) or selected (those in selected_repository_ids). An update without them keeps the secret's visibility and selection. Names are upper-cased and must match [A-Z_][A-Z0-9_]*. People only. Audited as org.secret.set. See /docs/actions/secrets-and-variables#organization-secrets.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
valuestringyesSecret value.
visibilitystringnoall, private or selected (422 otherwise).
selected_repository_idsinteger[]noWith selected: the repositories' numeric ids. An id that isn't one of the organization's repositories gets 422.
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value":"..."}'

Delete an organization secret

DELETE /api/v3/orgs/{org}/actions/secrets/{name}

People only. 404 when the organization has no secret with this name. Audited as org.secret.delete.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a secret's selected repositories

GET /api/v3/orgs/{org}/actions/secrets/{name}/repositories

{ total_count, repositories } for a secret with visibility: selected; 409 the secret's visibility isn't selected otherwise.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
curl "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website/repositories" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Replace a secret's selected repositories

PUT /api/v3/orgs/{org}/actions/secrets/{name}/repositories

Only for a secret with visibility: selected (409 otherwise). A repository that leaves the selection stops getting the secret from its next job. Audited as org.secret.repositories.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
selected_repository_idsinteger[]yesEvery repository that should get the secret.
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website/repositories" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"selected_repository_ids":"..."}'

Add a repository to a secret's selection

PUT /api/v3/orgs/{org}/actions/secrets/{name}/repositories/{repoId}

Only for a secret with visibility: selected (409 otherwise). repoId is the repository's numeric id. Audited as org.secret.repository.add.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
repoIdstringyesrepoId
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website/repositories/repoId" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove a repository from a secret's selection

DELETE /api/v3/orgs/{org}/actions/secrets/{name}/repositories/{repoId}

Only for a secret with visibility: selected (409 otherwise). The repository stops getting the secret from its next job. Audited as org.secret.repository.remove.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
repoIdstringyesrepoId
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/actions/secrets/website/repositories/repoId" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List organization variables

GET /api/v3/orgs/{org}/actions/variables

Actions variables shared by every repository of the organization: workflows read them as vars.NAME, and a repository variable with the same name wins. Returns total_count and every variable (no paging) with name, value, visibility (always all), created_at and updated_at. Organization owners and admins who are people (agents get 403 organization admins only); anyone outside the organization gets 404.

Access: An owner or admin of the organization (or a site admin). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/actions/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an organization variable

POST /api/v3/orgs/{org}/actions/variables

Creates the variable, or replaces the value of one with that name (GitHub answers 409 instead). Names are stored upper-cased; they must start with a letter or _, contain only letters, digits and _, and not start with GITHUB_ (422 invalid variable name). Values are strings of at most 49,152 characters (422 value must be a string of at most 48 KB). GitHub's visibility and selected_repository_ids are ignored: every repository of the organization gets the variable. People only. Audited as org.variable_set.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 201.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
namestringyesVariable name.
valuestringyesVariable value, at most 49,152 characters.
curl -X POST "https://diffinery.com/api/v3/orgs/acme/actions/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"...","value":"..."}'

Get an organization variable

GET /api/v3/orgs/{org}/actions/variables/{name}

name is matched in upper case. 404 variable not found. Organization owners and admins who are people.

Access: An owner or admin of the organization (or a site admin). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
curl "https://diffinery.com/api/v3/orgs/acme/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update an organization variable

PATCH /api/v3/orgs/{org}/actions/variables/{name}

Sets the value, creating the variable if it doesn't exist. Renaming isn't supported: a name in the body is ignored. Same name and value rules as creating. People only. Audited as org.variable_set.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
valuestringyesNew value, at most 49,152 characters.
curl -X PATCH "https://diffinery.com/api/v3/orgs/acme/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value":"..."}'

Delete an organization variable

DELETE /api/v3/orgs/{org}/actions/variables/{name}

404 when the organization has no variable with this name, and nothing is audited. People only. Audited as org.variable_delete.

Access: An owner or admin of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List repository secrets

GET /api/v3/repos/{owner}/{repo}/actions/secrets

Names and update times only; values are never returned.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/secrets" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set a repository secret

PUT /api/v3/repos/{owner}/{repo}/actions/secrets/{name}

People only. The value is encrypted at rest. GitHub's sealed-box encrypted_value isn't supported; send value over HTTPS. Audited as repo.secret.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
valuestringyesSecret value.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/actions/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value":"..."}'

Delete a repository secret

DELETE /api/v3/repos/{owner}/{repo}/actions/secrets/{name}

People only. Audited as repo.secret.delete.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/secrets/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List repository variables

GET /api/v3/repos/{owner}/{repo}/actions/variables

The repository's own variables. Workflows in an organization's repositories also see the organization's variables (GET /orgs/{org}/actions/variables), and a repository variable with the same name wins.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a repository variable

POST /api/v3/repos/{owner}/{repo}/actions/variables

409 when the repository already has a variable with this name. An organization variable of the same name doesn't count, and the repository's wins in workflows. Names are stored upper-cased. People only. Audited as repo.variable.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
namestringyesVariable name.
valuestringyesVariable value.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/variables" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"...","value":"..."}'

Get a repository variable

GET /api/v3/repos/{owner}/{repo}/actions/variables/{name}

404 for a name only the organization has. created_at and updated_at are always null.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set a repository variable

PUT /api/v3/repos/{owner}/{repo}/actions/variables/{name}

Diffinery's form: creates the variable or replaces its value. GitHub clients use POST and PATCH. Names are stored upper-cased. People only. Audited as repo.variable.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
valuestringyesVariable value.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value":"..."}'

Update a repository variable

PATCH /api/v3/repos/{owner}/{repo}/actions/variables/{name}

404 when the repository has no variable with this name; organization variables aren't changed here. People only. Renaming onto a name that exists fails with 409. Audited as repo.variable.set.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
namestringnoNew name (renames the variable).
valuestringnoNew value.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a repository variable

DELETE /api/v3/repos/{owner}/{repo}/actions/variables/{name}

People only. Names are matched without regard to letter case. Audited as repo.variable.delete.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/variables/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Actions artifacts and caches

MethodPathSummary
GET/repos/{owner}/{repo}/actions/artifactsList artifacts
GET/repos/{owner}/{repo}/actions/artifacts/{id}Get an artifact
DELETE/repos/{owner}/{repo}/actions/artifacts/{id}Delete an artifact
GET/repos/{owner}/{repo}/actions/artifacts/{id}/{format}Download an artifact
GET/repos/{owner}/{repo}/actions/cache/usageGet cache usage
GET/repos/{owner}/{repo}/actions/cachesList caches
DELETE/repos/{owner}/{repo}/actions/cachesDelete caches by key
DELETE/repos/{owner}/{repo}/actions/caches/{id}Delete a cache
GET/repos/{owner}/{repo}/actions/runs/{runId}/artifactsList a run's artifacts

List artifacts

GET /api/v3/repos/{owner}/{repo}/actions/artifacts

Every artifact in the repository, newest first. Each has a numeric id, name, size_in_bytes, digest (sha256:... when the uploader sent one), created_at, expires_at, expired, an archive_download_url, and workflow_run (its id is the run number). An artifact past its retention stays listed with expired: true for 90 more days; its content is already deleted. Returns { total_count, artifacts }.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
namestringnoOnly artifacts with exactly this name.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/artifacts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an artifact

GET /api/v3/repos/{owner}/{repo}/actions/artifacts/{id}

id is the artifact's numeric id. Expired artifacts are returned too, with expired: true.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/artifacts/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete an artifact

DELETE /api/v3/repos/{owner}/{repo}/actions/artifacts/{id}

Deletes the artifact and its content, expired or not; it no longer counts toward the repository's artifact quota. 404 when there is no artifact with that id. Audited as actions.artifact.delete.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/artifacts/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download an artifact

GET /api/v3/repos/{owner}/{repo}/actions/artifacts/{id}/{format}

format must be zip (anything else is 404). Redirects with 302 to a signed URL that works for 10 minutes and needs no token; follow redirects (curl -L). The content is a zip, or the file itself for an artifact uploaded as a single unzipped file. 410 Artifact has expired once the artifact has expired.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope. Success: 302.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
formatstringyesArchive format: zip.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/artifacts/1/zip" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get cache usage

GET /api/v3/repos/{owner}/{repo}/actions/cache/usage

full_name, active_caches_size_in_bytes and active_caches_count of the saved entries. A repository keeps up to 10 GB of caches; see Limits.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/cache/usage" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List caches

GET /api/v3/repos/{owner}/{repo}/actions/caches

Saved cache entries; uploads in progress aren't listed. Each has a numeric id, key, version, ref (the ref it was saved for, like refs/heads/main), size_in_bytes, created_at and last_accessed_at. Returns { total_count, actions_caches }.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
keystringnoOnly entries whose key starts with this.
refstringnoOnly entries saved for this full ref, like refs/heads/main.
sortstringnolast_accessed_at (default), created_at or size_in_bytes.
directionstringnodesc (default) or asc.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/caches" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete caches by key

DELETE /api/v3/repos/{owner}/{repo}/actions/caches

Deletes every entry whose key is exactly key (all versions), or only those saved for ref. Returns the deleted entries as { total_count, actions_caches }. 422 key is required without key, 404 when nothing matched. Audited as actions.cache.delete.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
keystringyesThe exact cache key.
refstringnoOnly entries saved for this full ref, like refs/heads/main.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/caches" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a cache

DELETE /api/v3/repos/{owner}/{repo}/actions/caches/{id}

By the entry's numeric id. 404 when there is none. Audited as actions.cache.delete.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/caches/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a run's artifacts

GET /api/v3/repos/{owner}/{repo}/actions/runs/{runId}/artifacts

Newest first, in the same shape as GET /repos/{owner}/{repo}/actions/artifacts. runId is the run's id, or its number (github.run_id in workflows), which covers every attempt of the run. Expired artifacts are listed with expired: true; their content is gone.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
runIdstringyesWorkflow run id, or the run number (github.run_id).

Query parameters:

NameTypeRequiredDescription
namestringnoOnly artifacts with exactly this name.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/42/artifacts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Actions

MethodPathSummary
GET/repos/{owner}/{repo}/actions/jobs/{id}Get a job
GET/repos/{owner}/{repo}/actions/jobs/{id}/logsGet a job's logs
POST/repos/{owner}/{repo}/actions/jobs/{id}/rerunRe-run a job
GET/repos/{owner}/{repo}/actions/permissions/workflowGet workflow token permissions
PUT/repos/{owner}/{repo}/actions/permissions/workflowSet workflow token permissions
GET/repos/{owner}/{repo}/actions/runnersList self-hosted runners
DELETE/repos/{owner}/{repo}/actions/runners/{id}Remove a self-hosted runner
POST/repos/{owner}/{repo}/actions/runners/claimClaim a job for a self-hosted runner
POST/repos/{owner}/{repo}/actions/runners/registerRegister a self-hosted runner
POST/repos/{owner}/{repo}/actions/runners/registration-tokenCreate a runner registration token
GET/repos/{owner}/{repo}/actions/runsList workflow runs
GET/repos/{owner}/{repo}/actions/runs/{id}Get a workflow run
GET/repos/{owner}/{repo}/actions/runs/{id}/approvalsList a run's deployment reviews
GET/repos/{owner}/{repo}/actions/runs/{id}/attempts/{attempt}Get a run attempt
POST/repos/{owner}/{repo}/actions/runs/{id}/cancelCancel a run
GET/repos/{owner}/{repo}/actions/runs/{id}/jobsList a run's jobs
GET/repos/{owner}/{repo}/actions/runs/{id}/logsDownload a run's logs
DELETE/repos/{owner}/{repo}/actions/runs/{id}/logsDelete a run's logs
GET/repos/{owner}/{repo}/actions/runs/{id}/pending_deploymentsList the environments a run waits on
POST/repos/{owner}/{repo}/actions/runs/{id}/pending_deploymentsApprove or reject a run's pending deployments
POST/repos/{owner}/{repo}/actions/runs/{id}/rerunRe-run a workflow run
POST/repos/{owner}/{repo}/actions/runs/{id}/rerun-failed-jobsRe-run a run's failed jobs
GET/repos/{owner}/{repo}/actions/workflowsList workflows
GET/repos/{owner}/{repo}/actions/workflows/{workflow}Get a workflow
POST/repos/{owner}/{repo}/actions/workflows/{workflow}/dispatchesRun a workflow (workflow_dispatch)
GET/repos/{owner}/{repo}/actions/workflows/{workflow}/runsList a workflow's runs

Get a job

GET /api/v3/repos/{owner}/{repo}/actions/jobs/{id}

The job with its steps. GitHub's job fields, plus Diffinery's own: runner (the hosted container's image, location and instance; null on a self-hosted runner) and placementTries (how many times a hosted job went back in line before a runner took it: no free container, or a runner on a replaced image) and restarts (how many times it started over because the platform replaced its runner before its steps ran). See /docs/actions/runners.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/jobs/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a job's logs

GET /api/v3/repos/{owner}/{repo}/actions/jobs/{id}/logs

Plain text, one timestamped line each, or JSON with format=json.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Query parameters:

NameTypeRequiredDescription
formatstringnojson for an array of { t, text } lines.
afterintegernoOnly lines after this sequence number (for following a live log).
curl "https://diffinery.com/api/v3/repos/acme/website/actions/jobs/1/logs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Re-run a job

POST /api/v3/repos/{owner}/{repo}/actions/jobs/{id}/rerun

Starts a new attempt of the job's run that runs this job (this matrix leg) and every job that depends on it; the other jobs are kept from the earlier attempt as they were. Answers { run_id }, the new attempt's id. 409 when the run hasn't finished. A workflow's GITHUB_TOKEN can't re-run workflows (403).

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
enable_debug_loggingbooleannoAccepted and ignored.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/jobs/1/rerun" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get workflow token permissions

GET /api/v3/repos/{owner}/{repo}/actions/permissions/workflow

The defaults for the GITHUB_TOKEN of the repository's workflows (GitHub's "Workflow permissions" setting). default_workflow_permissions is what a job without permissions: gets: read (contents and packages read, nothing else) or write (read and write on every scope except id-token). can_approve_pull_request_reviews says whether job tokens may open pull requests and approve or request changes. agent_runs_use_secrets (a Diffinery addition, false by default) says whether runs of code an agent wrote get the repository's and organization's secrets. New repositories start with read and false; repositories created before the setting existed have write and false. See Workflow permissions.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/permissions/workflow" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set workflow token permissions

PUT /api/v3/repos/{owner}/{repo}/actions/permissions/workflow

Send only what changes. People only: agents get 403 only people can change what workflows are allowed to do. Applies to jobs that start afterwards. Each change is audited as repo.actions_workflow_settings. Even when allowed, a workflow's approval never counts toward required approvals.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
default_workflow_permissionsstringnoread or write.
can_approve_pull_request_reviewsbooleannoAllow workflows' GITHUB_TOKEN to open pull requests and to approve or request changes.
agent_runs_use_secretsbooleannoGive runs of code an agent wrote (an agent triggered the run, pushed its branch last, or opened or pushed to its pull request) the repository's and organization's secrets. Default false.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/actions/permissions/workflow" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List self-hosted runners

GET /api/v3/repos/{owner}/{repo}/actions/runners

GitHub's shape: { total_count, runners }, each with id, name, os, status (online when it polled in the last 90 seconds, otherwise offline), busy, ephemeral and labels.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runners" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove a self-hosted runner

DELETE /api/v3/repos/{owner}/{repo}/actions/runners/{id}

Its runner token stops working at once. A job it is running carries on with its own job token. Audited as runner.remove.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/runners/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Claim a job for a self-hosted runner

POST /api/v3/repos/{owner}/{repo}/actions/runners/claim

Used by diffinery runner. Send the runner's drn_ token and an empty body: the runner offers the name and labels it registered with. Only registered runners claim: a personal token, even a repository admin's, gets 403 personal tokens can't claim jobs; register this runner: .... Returns 204 when no queued job matches the labels, otherwise the job with a fresh job token. See /docs/actions/runners.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runners/claim" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Register a self-hosted runner

POST /api/v3/repos/{owner}/{repo}/actions/runners/register

Trades a registration token for the runner's own drn_ token, shown once, which can claim this repository's jobs and nothing else. No Authorization header: the registration token is the credential. A wrong or expired token, or a repository that doesn't exist, gets 401 invalid or expired registration token. At most 100 runners per repository and 20 labels per runner (429 past the runner limit). Returns { id, name, labels, ephemeral, token }. Audited as runner.register, with the admin who created the registration token as the actor.

Access: No authentication needed. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
registration_tokenstringyesA drg_ token from POST .../actions/runners/registration-token.
namestringnoRunner name (default runner).
labelsstring[]noLabels the runner offers, matched against runs-on.
ephemeralbooleannotrue for a single job: the runner's token stops working once it takes a job, and the runner is removed when the job finishes.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runners/register" \
  -H "Content-Type: application/json" \
  -d '{"registration_token":"..."}'

Create a runner registration token

POST /api/v3/repos/{owner}/{repo}/actions/runners/registration-token

As on GitHub: a drg_ token that registers any number of self-hosted runners with this repository for an hour. Returns { token, expires_at }. People only: agents, job tokens and sandbox tokens get 403 only repository admins can add self-hosted runners. Audited as runner.registration_token. See /docs/actions/runners#manage-runners.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runners/registration-token" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List workflow runs

GET /api/v3/repos/{owner}/{repo}/actions/runs

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
workflowstringnoWorkflow file path.
branchstringnoHead branch.
statusstringnoRun status or conclusion.
eventstringnoTriggering event.
head_shastringnoHead commit.
per_pageintegernoResults per page (default 25, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a workflow run

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}

The run with its jobs. id is the run's id, or its number (github.run_id in workflows), which picks the latest attempt.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a run's deployment reviews

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}/approvals

Each reviewer's decision, with the environment and comment.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/approvals" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a run attempt

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}/attempts/{attempt}

Re-runs are stored as separate runs with the same run number; this returns attempt attempt of the run's number.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
attemptstringyesattempt
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/attempts/attempt" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Cancel a run

POST /api/v3/repos/{owner}/{repo}/actions/runs/{id}/cancel

Access: Write access to the repository. Tokens need the write scope. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/cancel" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a run's jobs

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}/jobs

Each job as GET .../actions/jobs/{id} returns it, with runner, placementTries and restarts.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/jobs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Download a run's logs

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}/logs

A zip with one text file per job. Jobs past 24 MB of logs in total are left out.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/logs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a run's logs

DELETE /api/v3/repos/{owner}/{repo}/actions/runs/{id}/logs

Deletes every job's log and step summary for good; the run, its jobs, checks and artifacts stay. Only for a finished run (409 otherwise). An agent can delete only the logs of runs that didn't run on the default branch or a protected branch, and a workflow's GITHUB_TOKEN can't delete logs (403). Audited as repo.actions.logs.delete.

Access: Write access to the repository. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/logs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List the environments a run waits on

GET /api/v3/repos/{owner}/{repo}/actions/runs/{id}/pending_deployments

Environments whose required reviewers or wait timer hold the run's jobs, with current_user_can_approve for the caller. See Required reviewers and wait timers.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/pending_deployments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Approve or reject a run's pending deployments

POST /api/v3/repos/{owner}/{repo}/actions/runs/{id}/pending_deployments

Only a listed reviewer, signed in or with a write token: never an agent, a workflow's token or a sandbox token (403). With prevent_self_review, not whoever started the run (403). One decision per environment and run counts; 422 when nothing waits. Approved jobs start once their wait timer has passed; rejected ones fail. Returns the deployments of the jobs that were waiting. Audited as deployment.approve or deployment.reject.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
environment_idsarrayyesIds of the environments to decide.
statestringyesapproved or rejected.
commentstringnoShown with the decision and in the audit log.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/pending_deployments" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"environment_ids":[],"state":"..."}'

Re-run a workflow run

POST /api/v3/repos/{owner}/{repo}/actions/runs/{id}/rerun

Starts a new attempt that runs every job again. Answers { run_id }, the new attempt's id. A workflow's GITHUB_TOKEN can't re-run workflows (403).

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
enable_debug_loggingbooleannoAccepted and ignored.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/rerun" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Re-run a run's failed jobs

POST /api/v3/repos/{owner}/{repo}/actions/runs/{id}/rerun-failed-jobs

Starts a new attempt that runs the jobs and matrix legs that failed, were cancelled or timed out, and every job that depends on them. The others are kept from the earlier attempt as they were, with their logs and artifacts. Answers { run_id }, the new attempt's id. 409 this run has no failed jobs to re-run, or when the run hasn't finished. A workflow's GITHUB_TOKEN can't re-run workflows (403).

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
enable_debug_loggingbooleannoAccepted and ignored.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/runs/1/rerun-failed-jobs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List workflows

GET /api/v3/repos/{owner}/{repo}/actions/workflows

Each workflow file with its triggers, and parse errors for invalid ones (state: invalid).

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/workflows" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a workflow

GET /api/v3/repos/{owner}/{repo}/actions/workflows/{workflow}

workflow is the file path or file name; the response's id is the path. created_at and updated_at are the time of the request, not of the file.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
workflowstringyesWorkflow file path (URL-encoded) or file name.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/workflows/ci.yml" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Run a workflow (workflow_dispatch)

POST /api/v3/repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches

workflow is the file path or name, URL-encoded, like .github%2Fworkflows%2Fdeploy.yml or deploy.yml. Returns the new run's id. Fails with 429 when the repository already has 500 unfinished workflow runs.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
workflowstringyesWorkflow file path (URL-encoded) or file name.

Body (JSON):

NameTypeRequiredDescription
refstringyesBranch or tag to run on.
inputsobjectnoValues for on.workflow_dispatch.inputs.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/actions/workflows/ci.yml/dispatches" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ref":"..."}'

List a workflow's runs

GET /api/v3/repos/{owner}/{repo}/actions/workflows/{workflow}/runs

No Link header; page with total_count.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
workflowstringyesWorkflow file path (URL-encoded) or file name.

Query parameters:

NameTypeRequiredDescription
branchstringnoHead branch.
statusstringnoRun status or conclusion.
eventstringnoTriggering event.
head_shastringnoHead commit.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/repos/acme/website/actions/workflows/ci.yml/runs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Webhooks

MethodPathSummary
GET/repos/{owner}/{repo}/hooksList webhooks
POST/repos/{owner}/{repo}/hooksCreate a webhook
DELETE/repos/{owner}/{repo}/hooks/{id}Delete a webhook

List webhooks

GET /api/v3/repos/{owner}/{repo}/hooks

Secrets are never returned.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/hooks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a webhook

POST /api/v3/repos/{owner}/{repo}/hooks

config.url must be https:// to a public host: localhost, single-label, .local and .internal names, private, loopback and link-local addresses get 422 webhook URL must be a public host, and Diffinery's own host 422 webhook URL can't point at Diffinery itself. At most 20 webhooks per repository (422). Audited as repo.webhook.create.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
configobjectyes{ url, secret }. The secret signs each delivery (X-Hub-Signature-256).
eventsstring[]noEvent names, or ["*"] (default) for all.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/hooks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"config":{}}'

Delete a webhook

DELETE /api/v3/repos/{owner}/{repo}/hooks/{id}

Audited as repo.webhook.delete.

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/hooks/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Packages

MethodPathSummary
GET/orgs/{owner}/packagesList an organization's packages
GET/orgs/{owner}/packages/{type}/{name}Get one of an organization's packages
PATCH/orgs/{owner}/packages/{type}/{name}Update one of an organization's packages
DELETE/orgs/{owner}/packages/{type}/{name}Delete one of an organization's packages
GET/orgs/{owner}/packages/{type}/{name}/versionsList package versions
GET/orgs/{owner}/packages/{type}/{name}/versions/{id}Get a package version
DELETE/orgs/{owner}/packages/{type}/{name}/versions/{id}Delete a package version
GET/repos/{owner}/{repo}/packagesList a repository's packages
GET/user/packagesList your packages
GET/user/packages/{type}/{name}Get one of your packages
PATCH/user/packages/{type}/{name}Update one of your packages
DELETE/user/packages/{type}/{name}Delete one of your packages
GET/user/packages/{type}/{name}/versionsList package versions
GET/user/packages/{type}/{name}/versions/{id}Get a package version
DELETE/user/packages/{type}/{name}/versions/{id}Delete a package version
GET/users/{owner}/packagesList a user's packages
GET/users/{owner}/packages/{type}/{name}Get one of a user's packages
PATCH/users/{owner}/packages/{type}/{name}Update one of a user's packages
DELETE/users/{owner}/packages/{type}/{name}Delete one of a user's packages
GET/users/{owner}/packages/{type}/{name}/versionsList package versions
GET/users/{owner}/packages/{type}/{name}/versions/{id}Get a package version
DELETE/users/{owner}/packages/{type}/{name}/versions/{id}Delete a package version

List an organization's packages

GET /api/v3/orgs/{owner}/packages

Only packages you can pull.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
curl "https://diffinery.com/api/v3/orgs/acme/packages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get one of an organization's packages

GET /api/v3/orgs/{owner}/packages/{type}/{name}

type is container.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
curl "https://diffinery.com/api/v3/orgs/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update one of an organization's packages

PATCH /api/v3/orgs/{owner}/packages/{type}/{name}

Change its visibility or the repository it is linked to.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
visibilitystringnoprivate or public.
repositorystringnoRepository name to link, or null to unlink.
curl -X PATCH "https://diffinery.com/api/v3/orgs/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete one of an organization's packages

DELETE /api/v3/orgs/{owner}/packages/{type}/{name}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List package versions

GET /api/v3/orgs/{owner}/packages/{type}/{name}/versions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.

Query parameters:

NameTypeRequiredDescription
statestringnotagged for tagged versions only.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/orgs/acme/packages/container/website/versions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a package version

GET /api/v3/orgs/{owner}/packages/{type}/{name}/versions/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/orgs/acme/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a package version

DELETE /api/v3/orgs/{owner}/packages/{type}/{name}/versions/{id}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a repository's packages

GET /api/v3/repos/{owner}/{repo}/packages

Container images linked to the repository.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/packages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your packages

GET /api/v3/user/packages

Only packages you can pull.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/user/packages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get one of your packages

GET /api/v3/user/packages/{type}/{name}

type is container.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.
curl "https://diffinery.com/api/v3/user/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update one of your packages

PATCH /api/v3/user/packages/{type}/{name}

Change its visibility or the repository it is linked to.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
visibilitystringnoprivate or public.
repositorystringnoRepository name to link, or null to unlink.
curl -X PATCH "https://diffinery.com/api/v3/user/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete one of your packages

DELETE /api/v3/user/packages/{type}/{name}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/user/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List package versions (GET /user/packages/type/name/versions)

GET /api/v3/user/packages/{type}/{name}/versions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.

Query parameters:

NameTypeRequiredDescription
statestringnotagged for tagged versions only.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/user/packages/container/website/versions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a package version (GET /user/packages/type/name/versions/id)

GET /api/v3/user/packages/{type}/{name}/versions/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/user/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a package version (DELETE /user/packages/type/name/versions/id)

DELETE /api/v3/user/packages/{type}/{name}/versions/{id}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/user/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List a user's packages

GET /api/v3/users/{owner}/packages

Only packages you can pull.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
curl "https://diffinery.com/api/v3/users/acme/packages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get one of a user's packages

GET /api/v3/users/{owner}/packages/{type}/{name}

type is container.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
curl "https://diffinery.com/api/v3/users/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update one of a user's packages

PATCH /api/v3/users/{owner}/packages/{type}/{name}

Change its visibility or the repository it is linked to.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.

Body (JSON):

NameTypeRequiredDescription
visibilitystringnoprivate or public.
repositorystringnoRepository name to link, or null to unlink.
curl -X PATCH "https://diffinery.com/api/v3/users/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete one of a user's packages

DELETE /api/v3/users/{owner}/packages/{type}/{name}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
curl -X DELETE "https://diffinery.com/api/v3/users/acme/packages/container/website" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List package versions (GET /users/owner/packages/type/name/versions)

GET /api/v3/users/{owner}/packages/{type}/{name}/versions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.

Query parameters:

NameTypeRequiredDescription
statestringnotagged for tagged versions only.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/users/acme/packages/container/website/versions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a package version (GET /users/owner/packages/type/name/versions/id)

GET /api/v3/users/{owner}/packages/{type}/{name}/versions/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/users/acme/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a package version (DELETE /users/owner/packages/type/name/versions/id)

DELETE /api/v3/users/{owner}/packages/{type}/{name}/versions/{id}

Access: Admin access to the repository (or to the package). Tokens need the admin scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
typestringyesPackage type: container.
namestringyesName.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/users/acme/packages/container/website/versions/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Imports

MethodPathSummary
DELETE/diffinery/admin/linked-accounts/{id}Clear anyone's GitHub link
GET/diffinery/importsList your imports
POST/diffinery/importsStart a GitHub import
GET/diffinery/imports/{id}Get an import
POST/diffinery/imports/{id}/agent/completeReport a Git transfer's result (import agent)
POST/diffinery/imports/{id}/agent/progressReport Git transfer progress (import agent)
GET/diffinery/imports/{id}/agent/specGet a Git transfer spec (import agent)
POST/diffinery/imports/{id}/cancelCancel an import
POST/diffinery/imports/{id}/claimClaim an import's Git transfer (local development)
POST/diffinery/imports/{id}/retryRetry an import
POST/diffinery/imports/{id}/selectionChoose repositories for a draft import
GET/diffinery/user/linked-accountsList your linked GitHub accounts
DELETE/diffinery/user/linked-accounts/{id}Unlink a GitHub account
POST/diffinery/user/linked-accounts/githubLink a GitHub account
POST/diffinery/user/linked-accounts/github/challengeGet a GitHub link code
DELETE /api/v3/diffinery/admin/linked-accounts/{id}

For example after an account changes hands. id is the link id from GET /diffinery/user/linked-accounts of the account that owns it; there is no endpoint that lists other people's links. 404 link not found, 403 site admin only. Audited as account.link_cleared.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/admin/linked-accounts/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your imports

GET /api/v3/diffinery/imports

The imports you started, newest first, at most 100. Repository imports that belong to an organization import aren't listed separately; read them through the organization import's children.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/imports" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Start a GitHub import

POST /api/v3/diffinery/imports

Imports one GitHub repository (source), or many repositories of a GitHub organization or user (source_owner), on the server, and returns the import (status: queued). Git history with LFS objects is copied in a container; issues and pull requests (with their numbers), comments, reviews, labels, milestones, branch protection, Actions variables, deployment environments and releases come through GitHub's REST API. Secret values are never read: only secret names are listed in summary, for a person to set by hand. People can import into their own account or an organization they own or administer (site administrators: any user or organization). An agent can import only where its owner may (the owner's own account or an organization the owner owns or administers; an organization's agent, only into that organization), and only when its policy allows write; its imports always use secrets: stop and skip Actions variables and environments. Needs a write or admin token (403 starting an import needs a token with write or admin scope), or a browser session. At most one organization import and three repository imports run at a time per account and per target (429), and a source repository larger than IMPORT_MAX_REPO_KB (default 10 GB, by GitHub's reported size) is refused with 422. Other errors: 422 <owner>/<name> already exists; choose another name, 422 GitHub repository <source> was not found or the token cannot read it, 422 GitHub rejected the token (expired or revoked?), 429 when GitHub's rate limit is reached, 502 could not reach GitHub: .... Audited as import.create. See Migrate from GitHub.

Access: Any active account (a token, or a browser session). Tokens need the write scope. Success: 201.

Body (JSON):

NameTypeRequiredDescription
sourcestringnoOne repository: owner/name, a github.com or GitHub Enterprise URL, or an SSH remote such as git@github.com:owner/name.git. Send either source or source_owner.
source_ownerstringnoA GitHub organization or user: imports its repositories (private ones too when the token can see them).
ownerstringyesThe Diffinery user or organization that will own the new repositories.
namestringnosource only: the new repository's name. Default: the GitHub name. It must not exist yet.
visibilitystringnokeep (default: public stays public, private and internal become private), private or public. internal is accepted and means private.
github_tokenstringnoA GitHub token that can read the source, at most 400 characters. Needed for private repositories; Actions variables, secret names and branch protection need a token with admin access to the source. Encrypted at rest, used only by this import, deleted when it ends, never returned.
github_api_urlstringnoGitHub Enterprise Server: the REST API base, such as https://ghe.example.com/api/v3 (default https://api.github.com). Must be HTTPS on a public host. Required, on the same host as source, when source names an Enterprise host and you send github_token.
optionsobjectnoWhat to copy; each is true by default: issues (issues and pull requests with comments and reviews), labels (labels and milestones), branch_protection, variables (Actions variables, secret names and deployment environments), releases, lfs. Plus secrets: bypass (default: credentials found in old history are imported with an audited push protection bypass, which needs a person with admin on the target and an admin token or browser session) or stop (the import fails). Unknown keys are refused with 422.
repositoriesstring[]nosource_owner only: the repository names to import, at most 1,000. Default: every repository (up to 1,000).
exclude_forksbooleannosource_owner only: skip forks (default false).
exclude_archivedbooleannosource_owner only: skip archived repositories (default false).
concurrencyintegernosource_owner only: repositories imported at the same time, 1 to 8 (default 3).
curl -X POST "https://diffinery.com/api/v3/diffinery/imports" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"owner":"..."}'

Get an import

GET /api/v3/diffinery/imports/{id}

Readable by the person or agent who started it, by people who could start an import into the same target (the account itself, or the organization's owners and admins), and by site administrators; others get 404 import not found. Fields: kind (repository or organization), status (draft, queued, running, succeeded, failed or cancelled), attempt, source, target, visibility, options, steps (each with name, title, status, message, count and times), git (the transfer's phase, message, chunks, bytes and tries), summary (counts, secret names, variables, environments, releases, push protection findings, linked and imported people), warnings, error and timestamps. An organization import adds children (each repository import's id, source, target, status, current step and error), and a draft adds candidates. Credentials are never included. Poll until status is succeeded, failed or cancelled.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/imports/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Report a Git transfer's result (import agent)

POST /api/v3/diffinery/imports/{id}/agent/complete

Internal: the import agent reports the result (branches, tags, pull request heads, LFS objects, push protection findings, warnings). Revokes the push token and wakes the import's workflow. Same credential rules as the spec. 204.

Access: Any active account (a token, or a browser session). Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/agent/complete" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Report Git transfer progress (import agent)

POST /api/v3/diffinery/imports/{id}/agent/progress

Internal: the import agent reports its phase, a message, and the chunks and bytes pushed so far. Same credential rules as the spec. 204.

Access: Any active account (a token, or a browser session). Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/agent/progress" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a Git transfer spec (import agent)

GET /api/v3/diffinery/imports/{id}/agent/spec

Internal: called by the import container with the import's own push token, which works only on Git, Git LFS and these agent endpoints. Says what to clone and where to push, and includes the GitHub token, so no other credential is accepted (403 this token does not belong to this import, or 403 this push token is no longer current for the import for a token from an earlier try; 409 this import is not running).

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/imports/1/agent/spec" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Cancel an import

POST /api/v3/diffinery/imports/{id}/cancel

Stops a draft, queued or running import (409 the import already <status> otherwise): ends its workflow and container and revokes its push tokens. Cancelling an organization import cancels its unfinished repository imports. A repository the import already created is kept with what was copied so far, and is unlocked. Anyone who can read the import can cancel it. Audited as import.cancel.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/cancel" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Claim an import's Git transfer (local development)

POST /api/v3/diffinery/imports/{id}/claim

Only when the Worker runs with IMPORT_GIT_AGENT=external (the dev environment, where containers don't run); 404 otherwise. Whoever started the import gets { token }, a push token for the transfer, and runs the runner image's import mode by hand with DIFFINERY_API_URL, DIFFINERY_IMPORT_ID and DIFFINERY_IMPORT_TOKEN. 409 this import is not waiting for an agent.

Access: Any active account (a token, or a browser session). Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/claim" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Retry an import

POST /api/v3/diffinery/imports/{id}/retry

Runs a failed or cancelled import again as a new attempt (409 only failed or cancelled imports can be retried otherwise), with the same options. Only whoever started it can retry it (404 for anyone else), except that a person who may import into the target can also retry an import an agent started. A repository import inside an organization import can't be retried on its own (422 retry the organization import this repository belongs to); retrying the organization import re-runs its failed and cancelled repositories, except those that failed because the target name was taken. The GitHub token was deleted when the import ended, so send github_token again for a private source. The retry resumes into the repository the import created, and fails if someone else has written to it since (repository already holds content not written by this import; start a new import). An agent can't retry once the repository exists (403 an agent cannot retry an import after the repository was created; a person who administers <owner> must retry it). Audited as import.retry.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 202.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
github_tokenstringnoA GitHub token for this attempt (optional; at most 400 characters).
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/retry" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Choose repositories for a draft import

POST /api/v3/diffinery/imports/{id}/selection

An organization import started from the web form waits as a draft with its candidates until its repositories are chosen; this starts it. Names are matched to the candidates ignoring case, and names that aren't candidates are dropped. 422 choose at least one repository, 409 this import has already started. Only whoever started it (404 for anyone else). Imports started through this API or MCP never wait as drafts. Unstarted drafts are cancelled after 7 days. Audited as import.create.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 202.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
repositoriesstring[]yesNames of the repositories to import, at most 1,000.
curl -X POST "https://diffinery.com/api/v3/diffinery/imports/1/selection" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"repositories":["..."]}'

List your linked GitHub accounts

GET /api/v3/diffinery/user/linked-accounts

Each link has id, host (github.com or the Enterprise host), apiBase, login, externalId (GitHub's numeric user id) and createdAt. Imports attribute a GitHub user's issues, pull requests, comments, reviews and releases to the Diffinery account linked to that user id on the same API base. Everyone else is imported as a mannequin: login github:<login>, type: "Mannequin", linking to the GitHub profile.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/user/linked-accounts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"
DELETE /api/v3/diffinery/user/linked-accounts/{id}

Removes one of your own links (an id that isn't yours changes nothing). Imports that already ran keep their attribution. Audited as account.unlink_github.

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/user/linked-accounts/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"
POST /api/v3/diffinery/user/linked-accounts/github

Step 2: reads the GitHub user's public profile and public gists without a token on the same API base, and links the account when one of the first 100 public gists GitHub lists for the user has your nonce in its description or in a file (file contents are read for at most 20 gists). Returns { id, host, login }. 422 create a PUBLIC gist whose description or a file contains <nonce>, then try again, 422 GitHub user <login> was not found, 409 GitHub user <login> is linked to another Diffinery account, 429 when GitHub's rate limit is reached. People only. Audited as account.link_github.

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
loginstringyesYour GitHub username.
api_urlstringnoThe same API base you used for the challenge. Default: github.com.
curl -X POST "https://diffinery.com/api/v3/diffinery/user/linked-accounts/github" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"login":"..."}'
POST /api/v3/diffinery/user/linked-accounts/github/challenge

Step 1 of linking a GitHub account without a token: returns nonce (diffinery-link- and 32 hex characters, the same each time for your account and host), apiBase, host and gistsUrl. Put the nonce in the description or a file of a public gist of the GitHub account, then call POST /diffinery/user/linked-accounts/github. People only (403 only people can link GitHub accounts).

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories.

Body (JSON):

NameTypeRequiredDescription
api_urlstringnoGitHub Enterprise REST API base, such as https://ghe.example.com/api/v3. Default: github.com.
curl -X POST "https://diffinery.com/api/v3/diffinery/user/linked-accounts/github/challenge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Status page

MethodPathSummary
GET/diffinery/admin/status/incidentsList status incidents
POST/diffinery/admin/status/incidentsOpen a status incident
POST/diffinery/admin/status/incidents/{id}/updatesPost an update to a status incident
GET/diffinery/statusGet the instance's status

List status incidents

GET /api/v3/diffinery/admin/status/incidents

Incidents on the status page, newest first, resolved or not: id, title, impact, state, components, created_by, created_at, updated_at, resolved_at, updates (each with id, state, body, author and created_at, newest first) and html_url. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoAt most this many (default 50, up to 200).
curl "https://diffinery.com/api/v3/diffinery/admin/status/incidents" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Open a status incident

POST /api/v3/diffinery/admin/status/incidents

Opens an incident with its first update and answers with it. While it isn't resolved, its impact sets the status of each component it names: critical is a major outage, major a partial outage, minor degraded performance and maintenance under maintenance. Recorded in the audit log as status_incident.create. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
titlestringyesOne line, up to 200 characters.
impactstringyesminor, major, critical or maintenance.
componentsarrayyesAt least one of web, git, actions, agents, packages and email.
statestringyesinvestigating, identified, monitoring or resolved.
bodystringyesThe first update, plain text up to 5,000 characters. It is public.
curl -X POST "https://diffinery.com/api/v3/diffinery/admin/status/incidents" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"...","impact":"...","components":[],"state":"...","body":"..."}'

Post an update to a status incident

POST /api/v3/diffinery/admin/status/incidents/{id}/updates

Adds an update and moves the incident to its state; resolved resolves it, and any other state reopens a resolved incident. Answers with the incident. Recorded in the audit log as status_incident.resolve when it resolves the incident and status_incident.update otherwise. 404 when there is no such incident, or for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 201.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
statestringyesinvestigating, identified, monitoring or resolved.
bodystringyesPlain text up to 5,000 characters. It is public.
curl -X POST "https://diffinery.com/api/v3/diffinery/admin/status/incidents/1/updates" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"...","body":"..."}'

Get the instance's status

GET /api/v3/diffinery/status

The status page as JSON, shaped like Statuspage's summary: status (indicator: none, minor, major, critical or maintenance, and a description), components (id, name, status: operational, under_maintenance, degraded_performance, partial_outage or major_outage, and a note when a kill switch or a database failure set it), incidents (the unresolved ones, newest first, each with its updates, newest first) and updated_at. Cached for 30 seconds. See Status page.

Access: No authentication needed.

curl "https://diffinery.com/api/v3/diffinery/status"

Notifications and email

MethodPathSummary
GET/diffinery/admin/early-accessList early access requests
GET/diffinery/admin/early-access/{id}Get an early access request
PATCH/diffinery/admin/early-access/{id}Decline an early access request, or put it back
DELETE/diffinery/admin/early-access/{id}Delete an early access request
POST/diffinery/admin/early-access/{id}/inviteInvite an early access request
GET/diffinery/admin/emailEmail delivery status
GET/diffinery/admin/email/suppressionsList suppressed email addresses
PUT/diffinery/admin/email/suppressions/{email}Suppress an email address
DELETE/diffinery/admin/email/suppressions/{email}Remove an address from the suppression list
POST/diffinery/admin/emails/samplesSend yourself every email template
GET/diffinery/admin/errorsList unexpected server errors
GET/diffinery/admin/errors/{id}Get a server error by its request ID
GET/diffinery/admin/indexnowIndexNow submissions
GET/diffinery/admin/schedulerWorkflow scheduler state
GET/diffinery/admin/security-reportsList security reports
GET/diffinery/admin/security-reports/{id}Get a security report
PATCH/diffinery/admin/security-reports/{id}Triage or resolve a security report
GET/diffinery/emailsList emails sent to you
POST/diffinery/emails/digestSend yourself the morning digest now
POST/diffinery/emails/testSend yourself a test email
GET/diffinery/notification-settingsGet your notification settings
PUT/diffinery/notification-settingsUpdate your notification settings
GET/notificationsList notifications
PUT/notificationsMark all notifications as read
GET/repos/{owner}/{repo}/subscriptionGet your watch setting
PUT/repos/{owner}/{repo}/subscriptionWatch or ignore a repository
DELETE/repos/{owner}/{repo}/subscriptionStop watching a repository

List early access requests

GET /api/v3/diffinery/admin/early-access

Requests sent through /early-access, newest first: id, state (unconfirmed until the address follows the emailed link, then confirmed, invited or declined), email, name, company, use_case, hosting (github, gitlab, bitbucket, azure, self-hosted, other, none or null), confirmed_at, invite_id, decided_by, decided_at, created_at, updated_at and html_url. 404 for anyone but a site administrator. See Early access.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Query parameters:

NameTypeRequiredDescription
statestringnoOnly requests in this state: confirmed, unconfirmed, invited or declined.
qstringnoOnly requests whose address, name, company or use contains this text.
per_pageintegernoAt most this many (default 100, up to 500).
pageintegernoPage number, from 1.
curl "https://diffinery.com/api/v3/diffinery/admin/early-access" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an early access request

GET /api/v3/diffinery/admin/early-access/{id}

One request, as in the list. 404 when there is none, or for anyone but a site administrator.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/admin/early-access/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Decline an early access request, or put it back

PATCH /api/v3/diffinery/admin/early-access/{id}

declined declines it; confirmed puts a declined request back (as unconfirmed if its address never confirmed). Nobody is emailed. Recorded in the audit log as early_access.decline or early_access.restore. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
statestringyesdeclined, or confirmed to put a declined request back.
curl -X PATCH "https://diffinery.com/api/v3/diffinery/admin/early-access/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

Delete an early access request

DELETE /api/v3/diffinery/admin/early-access/{id}

Removes the request, for someone who asks for their data to be removed. An invitation already sent from it stays; revoke it separately. Recorded in the audit log as early_access.delete, without the request's content or address. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/admin/early-access/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Invite an early access request

POST /api/v3/diffinery/admin/early-access/{id}/invite

Sends the request's address the instance's usual invitation email (it works once for 14 days) and marks the request invited. An address that already has a pending instance invitation keeps it; one that already belongs to an active account is refused (422). Recorded in the audit log as early_access.invite, and invite.create when a new invitation is sent. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/admin/early-access/1/invite" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Email delivery status

GET /api/v3/diffinery/admin/email

Whether sending is configured, whether the signed bounce and complaint endpoint is on (event_intake), and counts for the last 24 hours.

Access: A site administrator. Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/admin/email" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List suppressed email addresses

GET /api/v3/diffinery/admin/email/suppressions

Newest first: email, reason (hard-bounce, complaint or manual), detail, source (cloudflare, webhook, send or admin), created_by and created_at.

Access: A site administrator. Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/diffinery/admin/email/suppressions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Suppress an email address

PUT /api/v3/diffinery/admin/email/suppressions/{email}

Diffinery sends nothing to it until it is removed. Recorded in the audit log.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
emailstringyesemail

Body (JSON):

NameTypeRequiredDescription
notestringnoWhy, kept with the entry.
curl -X PUT "https://diffinery.com/api/v3/diffinery/admin/email/suppressions/email" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Remove an address from the suppression list

DELETE /api/v3/diffinery/admin/email/suppressions/{email}

Whatever put it there. 404 when it isn't suppressed. Recorded in the audit log.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
emailstringyesemail
curl -X DELETE "https://diffinery.com/api/v3/diffinery/admin/email/suppressions/email" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Send yourself every email template

POST /api/v3/diffinery/admin/emails/samples

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Body (JSON):

NameTypeRequiredDescription
onlystring[]noOnly these sample ids.
curl -X POST "https://diffinery.com/api/v3/diffinery/admin/emails/samples" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List unexpected server errors

GET /api/v3/diffinery/admin/errors

The newest answers with a 5xx status, newest first: id (the request_id the answer carried, also in its x-request-id header), at, method, route, path, status, message and stack. The newest 500 are kept. No request bodies, query strings or headers are kept, and tokens in a message are masked.

Access: A site administrator. Tokens need the read scope.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoAt most this many (default 100, up to 500).
curl "https://diffinery.com/api/v3/diffinery/admin/errors" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a server error by its request ID

GET /api/v3/diffinery/admin/errors/{id}

The error a 5xx answer with this request_id recorded; 404 once it is no longer among the newest 500.

Access: A site administrator. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/admin/errors/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

IndexNow submissions

GET /api/v3/diffinery/admin/indexnow

What this instance has told search engines through IndexNow: enabled (and off_reason when it isn't), key_location, how many site_pages and public repositories it tracks, how many are queued, retry_at (set after IndexNow refused or couldn't be reached), repositories_checked_at, and the newest submissions (at, urls, status from IndexNow or null when unreachable, endpoint (the host that answered), ms, error, and the first 50 paths). See Search engines.

Access: A site administrator. Tokens need the read scope.

Query parameters:

NameTypeRequiredDescription
per_pageintegernoSubmissions to return (default 50, up to 200).
curl "https://diffinery.com/api/v3/diffinery/admin/indexnow" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Workflow scheduler state

GET /api/v3/diffinery/admin/scheduler

tick_minutes, last_tick_at (when the last check finished), covered_until (the last minute whose schedules were started) and next_tick_at (null when the timer isn't set). Tells a scheduler that stopped ticking from a run that failed to start.

Access: A site administrator. Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/admin/scheduler" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List security reports

GET /api/v3/diffinery/admin/security-reports

Private vulnerability reports sent through /security/report, newest first: id, state (new, triaged or resolved), summary, details, area, reply_to, reporter (a login, or null when not signed in), note, updated_by, updated_at, created_at and html_url. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Query parameters:

NameTypeRequiredDescription
statestringnoOnly reports in this state: new, triaged or resolved.
per_pageintegernoAt most this many (default 100, up to 500).
curl "https://diffinery.com/api/v3/diffinery/admin/security-reports" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a security report

GET /api/v3/diffinery/admin/security-reports/{id}

One report, as in the list. 404 when there is none, or for anyone but a site administrator.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/admin/security-reports/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Triage or resolve a security report

PATCH /api/v3/diffinery/admin/security-reports/{id}

Sets the report's state and note (a missing or empty note clears it). Recorded in the audit log as security_report.triage, security_report.resolve or security_report.reopen. 404 for anyone but a site administrator.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
statestringyestriaged, resolved, or new to reopen it.
notestringnoFor the other site administrators, up to 2,000 characters.
curl -X PATCH "https://diffinery.com/api/v3/diffinery/admin/security-reports/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

List emails sent to you

GET /api/v3/diffinery/emails

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Query parameters:

NameTypeRequiredDescription
kindstringnoOnly this kind of email.
sincestringnoISO timestamp.
per_pageintegernoAt most this many (default 50).
allstringno1 for everyone's (site admins).
curl "https://diffinery.com/api/v3/diffinery/emails" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Send yourself the morning digest now

POST /api/v3/diffinery/emails/digest

Your Today digest, sent now even when the digest is off or has nothing in it, covering what happened since the last one. At most 3 an hour; more answer 429. See /docs/agents/today#the-morning-digest.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X POST "https://diffinery.com/api/v3/diffinery/emails/digest" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Send yourself a test email

POST /api/v3/diffinery/emails/test

At most 5 an hour; more answer 429 you can send at most 5 test emails an hour; try again later.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X POST "https://diffinery.com/api/v3/diffinery/emails/test" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your notification settings

GET /api/v3/diffinery/notification-settings

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/notification-settings" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update your notification settings

PUT /api/v3/diffinery/notification-settings

Send only the groups you want to change. The morning digest is digest: email (on or off), hour (0 to 23), timeZone (an IANA time zone such as Europe/Istanbul or UTC) and weekends; 422 for an hour or time zone it can't use. See /docs/agents/today#the-morning-digest.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X PUT "https://diffinery.com/api/v3/diffinery/notification-settings" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List notifications

GET /api/v3/notifications

A token limited to repositories answers 403 this token is limited to repositories and can't read notifications, since notifications cover every repository.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Query parameters:

NameTypeRequiredDescription
allbooleannotrue to include read ones.
curl "https://diffinery.com/api/v3/notifications" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Mark all notifications as read

PUT /api/v3/notifications

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 205.

curl -X PUT "https://diffinery.com/api/v3/notifications" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your watch setting

GET /api/v3/repos/{owner}/{repo}/subscription

404 when you only get participating notifications (the default), as on GitHub.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/subscription" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Watch or ignore a repository

PUT /api/v3/repos/{owner}/{repo}/subscription

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
subscribedbooleannotrue for all activity, false for participating only.
ignoredbooleannotrue to ignore the repository.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/subscription" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Stop watching a repository

DELETE /api/v3/repos/{owner}/{repo}/subscription

Back to participating notifications.

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope. Success: 204.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/subscription" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Tokens and agents

MethodPathSummary
GET/diffinery/agentsList your agents
POST/diffinery/agentsCreate an agent
DELETE/diffinery/agents/{login}Disable an agent
PUT/diffinery/agents/{login}/auto-mergeTurn auto-merge on or off for an agent's pull requests
POST/diffinery/agents/{login}/tokensCreate a token for an agent
GET/diffinery/tokensList your tokens
POST/diffinery/tokensCreate a token
DELETE/diffinery/tokens/{id}Revoke a token

List your agents

GET /api/v3/diffinery/agents

Agents you own, and agents of organizations you administer.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/agents" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create an agent

POST /api/v3/diffinery/agents

People, from a browser session only (no token can create a token). Returns the agent and its first token (write scope, 90 days, unless you say otherwise). Unknown scopes or an empty list fail with 422. From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: Any active account (a token, or a browser session). No token can call it: it needs a browser session. Success: 201.

Body (JSON):

NameTypeRequiredDescription
loginstringyesAgent login.
namestringnoDisplay name.
orgstringnoOrganization that owns the agent (default: you).
policyobjectnoAgent policy.
tokenobjectno{ scopes, expires_in_days } for the first token.
auto_mergebooleannoTurn on auto-merge for the pull requests it opens (see PUT /diffinery/agents/{login}/auto-merge).
curl -X POST "https://diffinery.com/api/v3/diffinery/agents" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"login":"..."}'

Disable an agent

DELETE /api/v3/diffinery/agents/{login}

Its tokens stop working.

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/agents/diffy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Turn auto-merge on or off for an agent's pull requests

PUT /api/v3/diffinery/agents/{login}/auto-merge

The agent's owner, or an owner or admin of the organization that owns it. Diffinery then turns on auto-merge, as the agent, for each pull request it opens; it lands only as the agent's own auto-merge would (the repository must allow agents' auto-merge, or the agent may merge what a person approved), and a workflow change still needs a person. Same body as PUT /diffinery/auto-merge. Audited as agent.auto_merge.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.

Body (JSON):

NameTypeRequiredDescription
enabledbooleanyesOn or off.
merge_methodstringnodefault, merge, squash or rebase.
curl -X PUT "https://diffinery.com/api/v3/diffinery/agents/diffy/auto-merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true}'

Create a token for an agent

POST /api/v3/diffinery/agents/{login}/tokens

From a browser session only (no token can create a token): the agent's owner, or an owner or admin of the organization that owns it. Default scope write; unknown scopes or an empty list fail with 422. Audited as agent.token.create. From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: Any active account (a token, or a browser session). No token can call it: it needs a browser session. Success: 201.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.

Body (JSON):

NameTypeRequiredDescription
namestringnoToken name.
scopesstring[]noread, write (default) and/or admin.
expires_in_daysintegernoLifetime in days.
curl -X POST "https://diffinery.com/api/v3/diffinery/agents/diffy/tokens" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your tokens

GET /api/v3/diffinery/tokens

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/tokens" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a token

POST /api/v3/diffinery/tokens

From a browser session only: no token can create a token. The token value is returned once. Unknown scopes or an empty list fail with 422, and so does a repository you can't see (unknown repository owner/name). From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: Any active account (a token, or a browser session). No token can call it: it needs a browser session. Success: 201.

Body (JSON):

NameTypeRequiredDescription
namestringyesA name to recognise it by.
scopesstring[]noread, write (default) and/or admin.
repositoriesstring[]noRestrict to these owner/name repositories (only ones you can see).
expires_in_daysintegernoLifetime in days.
curl -X POST "https://diffinery.com/api/v3/diffinery/tokens" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'

Revoke a token

DELETE /api/v3/diffinery/tokens/{id}

Access: Any active account (a token, or a browser session). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/tokens/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Sandboxes

MethodPathSummary
POST/repos/{owner}/{repo}/diffinery/sandboxesStart a sandbox
POST/repos/{owner}/{repo}/diffinery/sandboxes/{id}/{action}Use a sandbox

Start a sandbox

POST /api/v3/repos/{owner}/{repo}/diffinery/sandboxes

A container with the repository checked out, for agents to build and test in.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
refstringnoBranch, tag or commit to check out (default: the default branch).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/sandboxes" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Use a sandbox

POST /api/v3/repos/{owner}/{repo}/diffinery/sandboxes/{id}/{action}

action is exec (run a command), read or write (files), or close.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
actionstringyesAction to take.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/sandboxes/1/exec" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Other

MethodPathSummary
GET/admin/accounts/{login}/actions-suspensionGet an account's Actions suspension
PUT/admin/accounts/{login}/actions-suspensionSuspend Actions for an account
DELETE/admin/accounts/{login}/actions-suspensionLift an account's Actions suspension
GET/admin/accounts/{login}/quotasGet an account's quotas and usage
PATCH/admin/accounts/{login}/quotasChange an account's quotas
GET/admin/hosted-compute-pauseGet the hosted compute pause
PUT/admin/hosted-compute-pausePause hosted compute
DELETE/admin/hosted-compute-pauseResume hosted compute
GET/admin/reportsList reports
GET/admin/reports/{id}Get a report
PATCH/admin/reports/{id}Resolve or reopen a report
GET/admin/repos/{owner}/{repo}/actions-suspensionGet a repository's Actions suspension
PUT/admin/repos/{owner}/{repo}/actions-suspensionSuspend Actions for a repository
DELETE/admin/repos/{owner}/{repo}/actions-suspensionLift a repository's Actions suspension
GET/appList app
GET/app/installationsList installations
GET/app/installations/{id}Get a installation
DELETE/app/installations/{id}Delete a installation
POST/app/installations/{id}/access_tokensCreate a access token
PUT/app/installations/{id}/suspendedSet suspended
DELETE/app/installations/{id}/suspendedDelete suspended
GET/apps/{slug}Get a app
GET/diffinery/appsList apps
POST/diffinery/appsCreate a app
GET/diffinery/apps/{slug}Get a app
PATCH/diffinery/apps/{slug}Update a app
DELETE/diffinery/apps/{slug}Delete a app
POST/diffinery/apps/{slug}/installationsCreate a installation
GET/diffinery/apps/{slug}/keysList keys
POST/diffinery/apps/{slug}/keysCreate a key
DELETE/diffinery/apps/{slug}/keys/{keyId}Delete a key
GET/diffinery/auto-mergeYour auto-merge setting
PUT/diffinery/auto-mergeTurn auto-merge on or off for pull requests you open
GET/diffinery/emailYour email address and whether it is suppressed
POST/diffinery/email/verificationAsk for the email that turns email back on
GET/diffinery/installations/{id}Get a installation
PATCH/diffinery/installations/{id}Update a installation
DELETE/diffinery/installations/{id}Delete a installation
POST/diffinery/installations/{id}/accept_permissionsCreate a accept permission
PUT/diffinery/installations/{id}/suspendedSet suspended
DELETE/diffinery/installations/{id}/suspendedDelete suspended
GET/diffinery/model-keysList your model keys
PUT/diffinery/model-keys/{provider}Save a model key
DELETE/diffinery/model-keys/{provider}Delete a model key
GET/diffinery/model-usageGet your model usage
POST/diffinery/reportsReport content to the site administrators
GET/diffinery/tasksList your agent tasks
GET/diffinery/todayYour morning view
GET/installation/repositoriesList repositories
DELETE/installation/tokenDelete token
GET/orgs/{org}/blocksList the people an organization blocked
GET/orgs/{org}/blocks/{username}Check whether an organization blocked a person
PUT/orgs/{org}/blocks/{username}Block a person from an organization
DELETE/orgs/{org}/blocks/{username}Unblock a person from an organization
GET/orgs/{org}/diffinery/agent-policyGet an organization's agent policy
PUT/orgs/{org}/diffinery/agent-policyChange an organization's agent policy
GET/orgs/{org}/diffinery/model-keysList an organization's model keys
PUT/orgs/{org}/diffinery/model-keys/{provider}Save an organization's model key
DELETE/orgs/{org}/diffinery/model-keys/{provider}Delete an organization's model key
GET/orgs/{org}/diffinery/model-usageGet an organization's model usage
GET/orgs/{org}/installationList installation
GET/orgs/{org}/usageGet an organization's quotas and usage
GET/repos/{owner}/{repo}/diffinery/agent-reviewGet agent review settings
PUT/repos/{owner}/{repo}/diffinery/agent-reviewTurn agent review on, change or off
GET/repos/{owner}/{repo}/diffinery/agent-setupGet the agent setup check
POST/repos/{owner}/{repo}/diffinery/agent-setup/checksReport an agent setup check
PUT/repos/{owner}/{repo}/diffinery/comments/{id}/minimizedHide (minimize) a comment
DELETE/repos/{owner}/{repo}/diffinery/comments/{id}/minimizedShow a hidden comment again
POST/repos/{owner}/{repo}/diffinery/delete-closed-pullsDelete closed pull requests
GET/repos/{owner}/{repo}/diffinery/projectGet the project
GET/repos/{owner}/{repo}/diffinery/project/coordinatorGet your coordinator
PUT/repos/{owner}/{repo}/diffinery/project/coordinatorTurn on or change your coordinator
DELETE/repos/{owner}/{repo}/diffinery/project/coordinatorTurn off your coordinator
GET/repos/{owner}/{repo}/diffinery/project/coordinatorsList the coordinators in a project
GET/repos/{owner}/{repo}/diffinery/project/memoryGet the project memory
PUT/repos/{owner}/{repo}/diffinery/project/memorySave or restore the project memory
GET/repos/{owner}/{repo}/diffinery/project/postsList the project conversation
POST/repos/{owner}/{repo}/diffinery/project/postsPost to the project conversation
POST/repos/{owner}/{repo}/diffinery/project/posts/{n}/handleHand a post to your coordinator
PUT/repos/{owner}/{repo}/diffinery/project/settingsChange the project settings
POST/repos/{owner}/{repo}/diffinery/purge-unreachablePurge unreachable objects
GET/repos/{owner}/{repo}/diffinery/tasksList agent tasks
POST/repos/{owner}/{repo}/diffinery/tasksStart an agent task
GET/repos/{owner}/{repo}/diffinery/tasks/{number}Get an agent task
PATCH/repos/{owner}/{repo}/diffinery/tasks/{number}Change a task's options
GET/repos/{owner}/{repo}/diffinery/tasks/{number}/attemptsCompare a task's attempts
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/attempts/{attempt}/pickPick a task's attempt
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/messagesSend a task a follow-up
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/plan/approveApprove a task's plan
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/plan/splitSplit a task's plan into tasks
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/retryRetry a task
POST/repos/{owner}/{repo}/diffinery/tasks/{number}/stopStop a task
GET/repos/{owner}/{repo}/diffinery/tasks/{number}/transcriptRead a task's transcript
GET/repos/{owner}/{repo}/installationList installation
POST/repos/{owner}/{repo}/transferTransfer a repository
GET/user/blocksList the people you blocked
GET/user/blocks/{username}Check whether you blocked a person
PUT/user/blocks/{username}Block a person
DELETE/user/blocks/{username}Unblock a person
GET/user/installationsList installations
GET/user/installations/{id}/repositoriesList repositories
PUT/user/installations/{id}/repositories/{repoId}Set a repository
DELETE/user/installations/{id}/repositories/{repoId}Delete a repository
GET/user/memberships/orgsList your organization memberships
GET/user/memberships/orgs/{org}Get your organization membership
PATCH/user/memberships/orgs/{org}Accept an organization invitation
GET/user/repository_invitationsList your repository invitations
PATCH/user/repository_invitations/{id}Accept a repository invitation
DELETE/user/repository_invitations/{id}Decline a repository invitation
GET/user/usageGet your quotas and usage
GET/users/{username}/installationList installation
PUT/users/{username}/suspendedSuspend a person
DELETE/users/{username}/suspendedUnsuspend a person

Get an account's Actions suspension

GET /api/v3/admin/accounts/{login}/actions-suspension

Site administrators only. suspended, reason, suspended_by and suspended_at.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl "https://diffinery.com/api/v3/admin/accounts/diffy/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Suspend Actions for an account

PUT /api/v3/admin/accounts/{login}/actions-suspension

Site administrators only. As for a repository, for every repository the person or organization owns; their running runs and sandboxes stop now. Audited as actions.suspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.

Body (JSON):

NameTypeRequiredDescription
reasonstringyesWhy (up to 500 characters). Shown to the people affected and kept in the audit log.
curl -X PUT "https://diffinery.com/api/v3/admin/accounts/diffy/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"..."}'

Lift an account's Actions suspension

DELETE /api/v3/admin/accounts/{login}/actions-suspension

Site administrators only. New work can start again; nothing restarts. Audited as actions.unsuspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl -X DELETE "https://diffinery.com/api/v3/admin/accounts/diffy/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an account's quotas and usage

GET /api/v3/admin/accounts/{login}/quotas

Site administrators only.

Access: A site administrator. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.
curl "https://diffinery.com/api/v3/admin/accounts/diffy/quotas" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Change an account's quotas

PATCH /api/v3/admin/accounts/{login}/quotas

Site administrators only. Send only the quotas to change: a whole number, -1 for unlimited, or null for the default. Audited as account.quotas.set.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
loginstringyesAccount login.

Body (JSON):

NameTypeRequiredDescription
hosted_minutesintegernoHosted minutes per calendar month (UTC).
hosted_jobsintegernoHosted Actions jobs running at once.
sandboxesintegernoAgent sandboxes open at once.
repositoriesintegernoRepositories the account owns.
storage_bytesintegernoBytes stored: git objects, Git LFS objects, release assets and packages, not Actions artifacts or caches.
curl -X PATCH "https://diffinery.com/api/v3/admin/accounts/diffy/quotas" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get the hosted compute pause

GET /api/v3/admin/hosted-compute-pause

Site administrators only. paused, reason, paused_by and paused_at.

Access: A site administrator. Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/admin/hosted-compute-pause" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Pause hosted compute

PUT /api/v3/admin/hosted-compute-pause

Site administrators only. Hosted jobs fail without starting and sandboxes are refused everywhere; running ones stop now. Self-hosted runners still work. Audited as compute.pause.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Body (JSON):

NameTypeRequiredDescription
reasonstringyesWhy (up to 500 characters). Shown to the people affected and kept in the audit log.
curl -X PUT "https://diffinery.com/api/v3/admin/hosted-compute-pause" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"..."}'

Resume hosted compute

DELETE /api/v3/admin/hosted-compute-pause

Site administrators only. New hosted jobs and sandboxes can start again; nothing restarts. Audited as compute.unpause.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

curl -X DELETE "https://diffinery.com/api/v3/admin/hosted-compute-pause" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List reports

GET /api/v3/admin/reports

Site administrators only. Newest first, with the reporter, the account reported, the excerpt kept when it was reported and the resolution. The total is in x-total-count.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Query parameters:

NameTypeRequiredDescription
statestringnoopen (default), resolved or all.
per_pageintegernoResults per page (default 30, at most 100).
pageintegernoPage number, starting at 1.
curl "https://diffinery.com/api/v3/admin/reports" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a report

GET /api/v3/admin/reports/{id}

Site administrators only.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/admin/reports/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Resolve or reopen a report

PATCH /api/v3/admin/reports/{id}

Site administrators only. Audited as report.resolve or report.reopen.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
statestringyesresolved or open.
resolutionstringnoWhat you did, for resolved (up to 2,000 characters).
curl -X PATCH "https://diffinery.com/api/v3/admin/reports/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

Get a repository's Actions suspension

GET /api/v3/admin/repos/{owner}/{repo}/actions-suspension

Site administrators only. suspended, reason, suspended_by, suspended_at, and owner_suspended when its owner's Actions are suspended.

Access: A site administrator. Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/admin/repos/acme/website/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Suspend Actions for a repository

PUT /api/v3/admin/repos/{owner}/{repo}/actions-suspension

Site administrators only. No runs start, queued jobs fail and no sandboxes open; what runs now stops (stopped). Audited as actions.suspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
reasonstringyesWhy (up to 500 characters). Shown to the people affected and kept in the audit log.
curl -X PUT "https://diffinery.com/api/v3/admin/repos/acme/website/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"..."}'

Lift a repository's Actions suspension

DELETE /api/v3/admin/repos/{owner}/{repo}/actions-suspension

Site administrators only. New work can start again; nothing restarts. Audited as actions.unsuspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X DELETE "https://diffinery.com/api/v3/admin/repos/acme/website/actions-suspension" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List app

GET /api/v3/app

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

curl "https://diffinery.com/api/v3/app" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List installations

GET /api/v3/app/installations

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

curl "https://diffinery.com/api/v3/app/installations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a installation

GET /api/v3/app/installations/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/app/installations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a installation

DELETE /api/v3/app/installations/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/app/installations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a access token

POST /api/v3/app/installations/{id}/access_tokens

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/app/installations/1/access_tokens" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set suspended

PUT /api/v3/app/installations/{id}/suspended

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X PUT "https://diffinery.com/api/v3/app/installations/1/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete suspended

DELETE /api/v3/app/installations/{id}/suspended

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/app/installations/1/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a app

GET /api/v3/apps/{slug}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl "https://diffinery.com/api/v3/apps/slug" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List apps

GET /api/v3/diffinery/apps

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/apps" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a app

POST /api/v3/diffinery/apps

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

curl -X POST "https://diffinery.com/api/v3/diffinery/apps" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a app (GET /diffinery/apps/slug)

GET /api/v3/diffinery/apps/{slug}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl "https://diffinery.com/api/v3/diffinery/apps/slug" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a app

PATCH /api/v3/diffinery/apps/{slug}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl -X PATCH "https://diffinery.com/api/v3/diffinery/apps/slug" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a app

DELETE /api/v3/diffinery/apps/{slug}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl -X DELETE "https://diffinery.com/api/v3/diffinery/apps/slug" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a installation

POST /api/v3/diffinery/apps/{slug}/installations

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl -X POST "https://diffinery.com/api/v3/diffinery/apps/slug/installations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List keys

GET /api/v3/diffinery/apps/{slug}/keys

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl "https://diffinery.com/api/v3/diffinery/apps/slug/keys" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a key

POST /api/v3/diffinery/apps/{slug}/keys

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
curl -X POST "https://diffinery.com/api/v3/diffinery/apps/slug/keys" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a key

DELETE /api/v3/diffinery/apps/{slug}/keys/{keyId}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
slugstringyesslug
keyIdstringyeskeyId
curl -X DELETE "https://diffinery.com/api/v3/diffinery/apps/slug/keys/keyId" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Your auto-merge setting

GET /api/v3/diffinery/auto-merge

Whether Diffinery turns on auto-merge for the pull requests you open: { enabled, merge_method }, where merge_method is default (as the branch merges), merge, squash, rebase, or null when off. An agent's token reads the agent's own. See /docs/collaboration/merge-on-green.

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/diffinery/auto-merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Turn auto-merge on or off for pull requests you open

PUT /api/v3/diffinery/auto-merge

People only. When on, Diffinery turns on auto-merge for you as you open a pull request (or mark your draft ready), wherever its base branch has at least one required check; it merges once every rule of the branch is met, approvals included. The body may also be just true or false. Returns the setting. Audited as account.auto_merge. See /docs/collaboration/merge-on-green.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

Body (JSON):

NameTypeRequiredDescription
enabledbooleanyesOn or off.
merge_methodstringnodefault (as the branch merges, the default), merge, squash or rebase.
curl -X PUT "https://diffinery.com/api/v3/diffinery/auto-merge" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true}'

Your email address and whether it is suppressed

GET /api/v3/diffinery/email

suppressed is null, or why Diffinery sends nothing to your address: reason (hard-bounce, complaint or manual), detail, source, created_at and owner_can_lift.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/email" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Ask for the email that turns email back on

POST /api/v3/diffinery/email/verification

When your address is suppressed by a bounce or complaint, sends one email to it, past the suppression list; following its link while signed in lifts the suppression. 409 when it isn't suppressed, 403 for a suppression a site administrator added, at most 3 an hour.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

curl -X POST "https://diffinery.com/api/v3/diffinery/email/verification" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get a installation (GET /diffinery/installations/id)

GET /api/v3/diffinery/installations/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/diffinery/installations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Update a installation

PATCH /api/v3/diffinery/installations/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X PATCH "https://diffinery.com/api/v3/diffinery/installations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a installation (DELETE /diffinery/installations/id)

DELETE /api/v3/diffinery/installations/{id}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/installations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Create a accept permission

POST /api/v3/diffinery/installations/{id}/accept_permissions

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X POST "https://diffinery.com/api/v3/diffinery/installations/1/accept_permissions" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set suspended (PUT /diffinery/installations/id/suspended)

PUT /api/v3/diffinery/installations/{id}/suspended

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X PUT "https://diffinery.com/api/v3/diffinery/installations/1/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete suspended (DELETE /diffinery/installations/id/suspended)

DELETE /api/v3/diffinery/installations/{id}/suspended

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/diffinery/installations/1/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your model keys

GET /api/v3/diffinery/model-keys

Your saved model API keys for agent tasks: provider (anthropic, openai or openrouter), hint (the key's last four characters), opted_in_at, created_at and updated_at. The keys themselves are never returned. See /docs/agents/tasks#model-access.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/model-keys" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Save a model key

PUT /api/v3/diffinery/model-keys/{provider}

From a browser session only: no token, agent, job or sandbox can set a model key. provider is anthropic, openai or openrouter. accept_terms: true records that you use that provider through Diffinery under your own account and its terms (422 without it). The key is encrypted, never shown again and never sent to a sandbox. Sends you a security email. Audited as model_key.set.

Access: Any active account (a token, or a browser session). No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
providerstringyesprovider

Body (JSON):

NameTypeRequiredDescription
keystringnoThe API key (sk-ant-..., sk-... or sk-or-...).
accept_termsbooleannoMust be true.
curl -X PUT "https://diffinery.com/api/v3/diffinery/model-keys/provider" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a model key

DELETE /api/v3/diffinery/model-keys/{provider}

From a browser session only. Running tasks that use it lose model access. Audited as model_key.delete.

Access: Any active account (a token, or a browser session). No token can call it: it needs a browser session. Success: 204.

Path parameters:

NameTypeRequiredDescription
providerstringyesprovider
curl -X DELETE "https://diffinery.com/api/v3/diffinery/model-keys/provider" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your model usage

GET /api/v3/diffinery/model-usage

The model usage you paid for over the last days, as on Settings → Model access: days, since, and repositories, one line per repository (named as it was when its runs ended) and kind (task, review or coordinator) with runs, reported_by_cli_runs, requests, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens and cost_usd (null when no run reported a cost). A token limited to some repositories sees only their lines. See /docs/agents/tasks#usage-and-cost.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

Query parameters:

NameTypeRequiredDescription
daysintegerno1 to 90 (default 30).
curl "https://diffinery.com/api/v3/diffinery/model-usage" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Report content to the site administrators

POST /api/v3/diffinery/reports

Diffinery only. People only, at most 20 a day and one open report per thing. Returns the report (id, kind, target, html_url, reason, body, state, created_at). Audited as report.create.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 201.

Body (JSON):

NameTypeRequiredDescription
kindstringyesuser, repository, issue, pull_request or comment.
loginstringnoThe person, for user.
repositorystringnoowner/name, for everything but user.
numberintegernoThe issue or pull request, for issue and pull_request.
comment_idstringnoThe comment, for comment.
reasonstringyesspam, harassment, hate, violence, sexual, malware, impersonation or other.
bodystringnoA note for the administrators (up to 2,000 characters; required for other).
curl -X POST "https://diffinery.com/api/v3/diffinery/reports" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"...","reason":"..."}'

List your agent tasks

GET /api/v3/diffinery/tasks

Agent tasks you started across repositories where you still have write access, most recently changed first (for an agent's token: the tasks it runs). A token limited to repositories sees only those.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/tasks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Your morning view

GET /api/v3/diffinery/today

Pull requests that need you, your agents' open pull requests with their state, and what merged, was released or failed in the last 24 hours, across the repositories you can see that were active in the last 30 days (at most 100). A token limited to repositories sees only those. See /docs/agents/today.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/diffinery/today" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List repositories

GET /api/v3/installation/repositories

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

curl "https://diffinery.com/api/v3/installation/repositories" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete token

DELETE /api/v3/installation/token

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

curl -X DELETE "https://diffinery.com/api/v3/installation/token" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List the people an organization blocked

GET /api/v3/orgs/{org}/blocks

Organization owners and site administrators.

Access: An owner of the organization (or a site admin). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/blocks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Check whether an organization blocked a person

GET /api/v3/orgs/{org}/blocks/{username}

204 if it did, 404 if not.

Access: An owner of the organization (or a site admin). Tokens need the read scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
usernamestringyesusername
curl "https://diffinery.com/api/v3/orgs/acme/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Block a person from an organization

PUT /api/v3/orgs/{org}/blocks/{username}

As blocking for yourself, for every repository the organization owns. Members can't be blocked. Audited as org.block.

Access: An owner of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
usernamestringyesusername
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Unblock a person from an organization

DELETE /api/v3/orgs/{org}/blocks/{username}

Audited as org.unblock.

Access: An owner of the organization (or a site admin). Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
usernamestringyesusername
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an organization's agent policy

GET /api/v3/orgs/{org}/diffinery/agent-policy

Owners only (and site administrators); a token limited to repositories gets 403. keys (personal, either or organization: whose key pays), runtimes (claude-code, codex, custom), providers (anthropic, openai, openrouter), max_running (tasks at once per repository, 1 to 10), terminals, terminal_tasks, review, member_monthly_tokens (null for no allowance), updated_by and updated_at. See /docs/agents/organizations.

Access: An owner of the organization (or a site admin). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/diffinery/agent-policy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Change an organization's agent policy

PUT /api/v3/orgs/{org}/diffinery/agent-policy

From a browser session only, by an owner. Fields left out stay as they are; answers with the whole policy. 422 when a value is out of range, or no runtime or provider is left allowed. Each repository's tasks at once are held to max_running right away. Audited as org.agent_policy.update, with the new values.

Access: An owner of the organization (or a site admin). No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
keysstringnopersonal (each person's own keys), either (the organization's keys when it has them) or organization (only the organization's keys).
runtimesarraynoAllowed runtimes: claude-code, codex, custom. At least one.
providersarraynoAllowed providers: anthropic, openai, openrouter. At least one.
max_runningintegernoMost tasks at once per repository, 1 to 10.
terminalsbooleannoAllow web terminals.
terminal_tasksbooleannoLet terminals run agent tasks.
reviewbooleannoAllow agent review.
member_monthly_tokensintegernoTokens one person may spend of the organization's keys in a calendar month (UTC), 10,000 to 10,000,000,000, or null for no allowance.
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/diffinery/agent-policy" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List an organization's model keys

GET /api/v3/orgs/{org}/diffinery/model-keys

Owners only; a token limited to repositories gets 403. Each key as GET /diffinery/model-keys shows a personal one: provider, hint (last four characters), opted_in_at, created_at and updated_at. The keys themselves are never returned. See /docs/agents/organizations.

Access: An owner of the organization (or a site admin). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/diffinery/model-keys" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Save an organization's model key

PUT /api/v3/orgs/{org}/diffinery/model-keys/{provider}

From a browser session with a sign-in from the last 2 hours, by an owner. provider is anthropic, openai or openrouter; accept_terms: true is required. The key is encrypted, never shown again and never sent to a sandbox. Every owner gets a security email. Audited as org.model_key.set.

Access: An owner of the organization (or a site admin). No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
providerstringyesprovider

Body (JSON):

NameTypeRequiredDescription
keystringnoThe API key (sk-ant-..., sk-... or sk-or-...).
accept_termsbooleannoMust be true.
curl -X PUT "https://diffinery.com/api/v3/orgs/acme/diffinery/model-keys/provider" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete an organization's model key

DELETE /api/v3/orgs/{org}/diffinery/model-keys/{provider}

From a browser session with a sign-in from the last 2 hours, by an owner. 404 when the organization has no key for that provider. Audited as org.model_key.delete.

Access: An owner of the organization (or a site admin). No token can call it: it needs a browser session. Success: 204.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
providerstringyesprovider
curl -X DELETE "https://diffinery.com/api/v3/orgs/acme/diffinery/model-keys/provider" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an organization's model usage

GET /api/v3/orgs/{org}/diffinery/model-usage

Owners only; a token limited to repositories gets 403. The runs the organization's keys paid for over the last days, shaped like GET /diffinery/model-usage with a person on each line, and month: month, member_monthly_tokens and people (each person and their tokens on the organization's keys this month). See /docs/agents/organizations#usage.

Access: An owner of the organization (or a site admin). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Query parameters:

NameTypeRequiredDescription
daysintegerno1 to 90 (default 30).
curl "https://diffinery.com/api/v3/orgs/acme/diffinery/model-usage" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List installation

GET /api/v3/orgs/{org}/installation

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/installation" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an organization's quotas and usage

GET /api/v3/orgs/{org}/usage

The same as GET /user/usage, for the organization's owners and admins.

Access: An owner or admin of the organization (or a site admin). Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/orgs/acme/usage" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get agent review settings

GET /api/v3/repos/{owner}/{repo}/diffinery/agent-review

Whether agent review is on, which agent reviews with which runtime, whose model key every review uses (uses_key_of), when it reviews (trigger: push, open or request), which pull requests (authors: all, people or agents), drafts, autofix, daily_limit and tokens_per_review. {"enabled": false} when it was never turned on. Needs write access. See /docs/agents/review.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/agent-review" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Turn agent review on, change or off

PUT /api/v3/repos/{owner}/{repo}/diffinery/agent-review

From a browser session only, by a repository admin who can run tasks as the agent and has the runtime's model key: every review on the repository, including ones other people ask for, spends that admin's key, so accept_terms must be true. {"enabled": false} turns it off. Audited as review.settings.

Access: Admin access to the repository (or to the package). No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
agentstringnoThe reviewing agent's login (required).
runtimestringnoclaude-code (default), codex or custom.
providerstringnoWhere the runtime's model calls go: its own provider (anthropic for Claude Code, openai for Codex; the default) or openrouter.
modelstringnoWith provider: openrouter: the OpenRouter model id (default ~anthropic/claude-sonnet-latest for Claude Code, ~openai/gpt-sol-latest for Codex).
commandstringnoFor custom: the shell command; it must end its output with the findings block the prompt describes.
triggerstringnopush (default: on open and every push), open (once per pull request) or request (only when asked).
authorsstringnoall (default), people or agents.
draftsbooleannoReview drafts too (default false).
autofixbooleannoStart a fix task on the pull request's branch for blocking findings (default false; at most 3 times per pull request).
daily_limitintegernoMost reviews and autofix runs the repository starts in 24 hours, 1 to 1000 (default 50). Past it, pull requests get an action-required check, autofix waits, and you get an email.
tokens_per_reviewintegernoMost tokens one review may use, counted from the provider's responses (cache reads count as a tenth), 100000 to 50000000 (default 2000000).
accept_termsbooleannoMust be true: reviews use your model key.
enabledbooleannofalse turns agent review off.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/diffinery/agent-review" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get the agent setup check

GET /api/v3/repos/{owner}/{repo}/diffinery/agent-setup

The latest Check on Settings → Agent setup, or check: null before any: ok, checked_at, first_ok_at (when a check first passed), the account and token (name, prefix) that reported it, cli_version and the checks lines. See Cloud agent environments.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/agent-setup" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Report an agent setup check

POST /api/v3/repos/{owner}/{repo}/diffinery/agent-setup/checks

What the hosted setup script (/{owner}/{repo}/agent-setup.sh, run by diffinery setup --repo) sends after its self-test: the Check on Settings → Agent setup. Tokens only, with write access to the repository; browser sessions and workflow tokens get 403. The report is green only when every line passed. Returns ok and the page's html_url. See Cloud agent environments.

Access: Write access to the repository. Tokens need the write scope. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
checksobject[]yes1 to 30 lines of { name, ok, message }: what was checked, whether it passed, and what to change when it didn't.
cli_versionstringnoThe CLI's version.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/agent-setup/checks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"checks":"..."}'

Hide (minimize) a comment

PUT /api/v3/repos/{owner}/{repo}/diffinery/comments/{id}/minimized

Diffinery only (GitHub's GraphQL minimizeComment). Write access, people only. The comment is shown collapsed with its reason. Audited as comment.minimize.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.

Body (JSON):

NameTypeRequiredDescription
reasonstringyesspam, abuse, off_topic, outdated, duplicate or resolved (or GitHub's classifier, such as OFF_TOPIC).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/diffinery/comments/1/minimized" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"..."}'

Show a hidden comment again

DELETE /api/v3/repos/{owner}/{repo}/diffinery/comments/{id}/minimized

Diffinery only. Write access, people only. Audited as comment.unminimize.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/diffinery/comments/1/minimized" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete closed pull requests

POST /api/v3/repos/{owner}/{repo}/diffinery/delete-closed-pulls

For starting over with fresh history after rewriting the branches. Permanently deletes every closed and merged pull request (not ones still in the merge queue) with its comments, reviews, review comments, timeline events, reactions and refs/pull/{number}/* refs, then purges unreachable objects as POST .../diffinery/purge-unreachable does. Issues, open pull requests, branches, tags and workflow runs stay; pull request numbers are not reused. Returns { pull_requests, objects, bytes }. People only, not agents. Repositories of up to 300,000 objects (422 otherwise). From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL. Audited as repo.delete_closed_pulls. See /docs/repositories/overview#start-over-with-fresh-history.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/delete-closed-pulls" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get the project

GET /api/v3/repos/{owner}/{repo}/diffinery/project

The repository's project: settings (max_running, instructions, plan_first), memory (body, version, updated_by, updated_at) and board, the agent tasks by column (waiting, working, queued, review, landing, done, idle). Agent reviews aren't on the board. Needs write access. See /docs/agents/projects.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/project" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your coordinator

GET /api/v3/repos/{owner}/{repo}/diffinery/project/coordinator

Your coordinator's settings in this project: enabled, agent, runtime, command, provider, model, tokens_per_run, tokens_per_task, opted_in_at, updated_at. Needs write access.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/coordinator" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Turn on or change your coordinator

PUT /api/v3/repos/{owner}/{repo}/diffinery/project/coordinator

Your agent then reads your posts and turns them into tasks, on your model key. Each coordinator starts at most 5 tasks per post and 20 per 24 hours in the project. A person in a browser session only. Audited as project.coordinator. See /docs/agents/projects#coordinator.

Access: Write access to the repository. No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
agentstringyesThe login of an agent you manage with write access to the repository.
runtimestringnoclaude-code (default), codex or custom.
commandstringnoFor custom: the shell command.
providerstringnoopenrouter to run Claude Code or Codex via OpenRouter.
modelstringnoWith provider: openrouter: the OpenRouter model id.
tokens_per_runintegernoToken budget of each coordinator run, 100,000 to 50,000,000 (default 1,000,000).
tokens_per_taskintegernoToken budget of each run of a task it starts, 100,000 to 50,000,000 (default 2,000,000).
acceptbooleanyesMust be true: confirms your coordinator and its tasks use your model key.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/coordinator" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"agent":"...","accept":true}'

Turn off your coordinator

DELETE /api/v3/repos/{owner}/{repo}/diffinery/project/coordinator

A person in a browser session only. Audited as project.coordinator.

Access: Write access to the repository. No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X DELETE "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/coordinator" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List the coordinators in a project

GET /api/v3/repos/{owner}/{repo}/diffinery/project/coordinators

Every person's coordinator in this project, oldest first: person, agent, runtime, provider, model, opted_in_at. Never their token budgets or custom command. Needs write access. See /docs/agents/projects#coordinator.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/coordinators" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get the project memory

GET /api/v3/repos/{owner}/{repo}/diffinery/project/memory

The current memory and its last 50 versions (version, updated_by, updated_at, length). Every agent task reads it as background notes; agent reviews don't. Needs write access.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/memory" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Save or restore the project memory

PUT /api/v3/repos/{owner}/{repo}/diffinery/project/memory

Saves body (at most 40,000 characters) as a new version, or restores an earlier version as a new one with restore (404 no such memory version). A person in a browser session only. Audited as project.memory.

Access: Write access to the repository. No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
bodystringnoThe new memory (Markdown).
restoreintegernoA version number to restore instead.
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/memory" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List the project conversation

GET /api/v3/repos/{owner}/{repo}/diffinery/project/posts

Posts and task events, oldest first: those after after, or the latest 100. Needs write access.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
afterintegernoReturn posts after this id (default 0).
per_pageintegernoAt most 100 (default 100).
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/posts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Post to the project conversation

POST /api/v3/repos/{owner}/{repo}/diffinery/project/posts

Markdown, at most 20,000 characters (422 otherwise). If you have a coordinator in this project, it handles the post unless you send coordinator: false; the response's coordinator says whether it did. A person in a browser session only. 403 on an archived repository.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
bodystringyesThe post.
coordinatorbooleannofalse to post without handing it to your coordinator.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/posts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body":"..."}'

Hand a post to your coordinator

POST /api/v3/repos/{owner}/{repo}/diffinery/project/posts/{n}/handle

Your coordinator handles post n, anyone's, on your model key. Each post is handled once. A person in a browser session only. Audited as project.coordinate. See /docs/agents/projects#coordinator.

Access: Write access to the repository. No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
nstringyesn
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/posts/n/handle" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Change the project settings

PUT /api/v3/repos/{owner}/{repo}/diffinery/project/settings

Project instructions every agent task and agent review gets, how many tasks run at once, and whether tasks plan first. Tasks beyond max_running queue and start oldest first. A person in a browser session only. Audited as project.settings.

Access: Admin access to the repository (or to the package). No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
max_runningintegerno1 to 10 (default 3).
instructionsstringnoAt most 10,000 characters.
plan_firststringnooff (default: tasks build at once unless started with plan_first: true), default (tasks plan first unless started with plan_first: false) or required (every task plans first, including ones coordinators start).
curl -X PUT "https://diffinery.com/api/v3/repos/acme/website/diffinery/project/settings" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Purge unreachable objects

POST /api/v3/repos/{owner}/{repo}/diffinery/purge-unreachable

Permanently deletes every commit, tree and file that no branch, tag, pull request, merge queue entry or unfinished workflow run reaches, and empties the archive cache, so a secret force-pushed away can't be fetched by its SHA. Returns { objects, bytes }. People only, not agents. Repositories of up to 300,000 objects (422 otherwise). From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL. Audited as repo.purge_unreachable. See /docs/security/push-protection#removing-a-secret-that-was-pushed.

Access: Admin access to the repository (or to the package). Tokens need the admin scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/purge-unreachable" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List agent tasks

GET /api/v3/repos/{owner}/{repo}/diffinery/tasks

The repository's agent tasks, newest first. Needs write access: transcripts show an agent's reasoning and command output. state filters: queued, running, ready, failed or stopped, or active for running and queued together.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Query parameters:

NameTypeRequiredDescription
statestringnoqueued, running, ready, failed, stopped or active (running or queued).
per_pageintegernoAt most 100 (default 50).
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Start an agent task

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks

From a browser session only, by a person with write access, as one of their agents (they own it, or administer the organization that owns it) that has write access here: each run spends the person's own model key, so no token can start one. The agent works in a sandbox, then Diffinery pushes agent/<number>-<slug> and opens a pull request as the agent. 422 when the runtime needs a model key you haven't saved. Audited as task.start. See /docs/agents/tasks.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
goalstringnoWhat to do (required, at most 20,000 characters).
runtimestringnoclaude-code (default), codex or custom.
providerstringnoWhere the runtime's model calls go: its own provider (anthropic for Claude Code, openai for Codex; the default) or openrouter.
modelstringnoWith provider: openrouter: the OpenRouter model id (default ~anthropic/claude-sonnet-latest for Claude Code, ~openai/gpt-sol-latest for Codex).
agentstringnoThe agent's login (required).
basestringnoBranch to start from (default: the default branch).
plan_firstbooleannotrue to plan in a read-only sandbox before building, false to build at once. Left out, the project's default; a project that requires plans ignores false. See /docs/agents/tasks#plan-first.
attemptsintegerno1 (default) to 4: run the first build as that many attempts side by side, then pick one (422 above 1 for a task on a pull request's branch). See /docs/agents/tasks#best-of-n.
fix_checksbooleannoStart a fix run when the pull request's checks fail (default true, false for a task on a pull request's branch). See /docs/agents/tasks#verify-and-land.
landbooleannoTurn on auto-merge for its pull request as the task's agent, so it merges once approved and checks pass (default false).
commandstringnoFor custom: the shell command to run.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get an agent task

GET /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}

The task, its runs and its pull request. Needs write access. A plan-first task also has plan_state (planning, waiting, approved or split) and plan; a task split from a plan has parent_task. A task with more than one attempt has pick_state (running, waiting or picked) and picked_attempt, and each run its attempt. Every task has fix_checks, check_fixes (fix runs started so far) and land, paid_by (person, or organization when an organization's key pays), and usage (the model usage of all its runs; each run has its own usage, with source: proxy, or runtime for a run in a terminal). See /docs/agents/tasks#usage-and-cost.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Change a task's options

PATCH /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}

From a browser session only, by the person who started the task. fix_checks starts a fix run when its pull request's checks fail (one per commit, at most 3 per task); turning land on turns on auto-merge for an open pull request as the task's agent, under the usual rules for agents. 422 when a value isn't true or false; 409 only agent tasks have these options for an agent review. Audited as task.options. See /docs/agents/tasks#verify-and-land.

Access: Write access to the repository. No token can call it: it needs a browser session.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
fix_checksbooleannoFix failing checks.
landbooleannoLand when approved.
curl -X PATCH "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Compare a task's attempts

GET /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/attempts

Needs write access. One entry per attempt of a best-of-N task: attempt, run, state, error, branch, head_sha, changes (files, additions, deletions), checks and failing_checks on its branch, model_requests, tokens, summary (its last message) and compare_url. See /docs/agents/tasks#best-of-n.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/attempts" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Pick a task's attempt

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/attempts/{attempt}/pick

From a browser session only, by the person who started the task. The attempt's branch becomes the task's branch, with a pull request; the other attempts' branches are deleted. 409 the attempts are still running, attempt <n> is already picked or this task has no attempts to pick from; 404 no such attempt; 422 attempt <n> has no work to pick: ... when it changed nothing or didn't finish. Audited as task.pick.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
attemptstringyesattempt
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/attempts/attempt/pick" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Send a task a follow-up

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/messages

From a browser session only, by the person who started the task. Starts a new run on the task's branch with the message (while a run is active, it waits and starts when that run ends). Audited as task.message.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Body (JSON):

NameTypeRequiredDescription
bodystringnoThe message.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/messages" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Approve a task's plan

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/plan/approve

From a browser session only, by the person who started the task. The build run starts with the goal and the plan, and every later run gets the plan as the approved one. 409 the plan isn't ready yet while it plans, this task has no plan waiting for approval, or the task is running. Audited as task.plan_approve. See /docs/agents/tasks#plan-first.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/plan/approve" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Split a task's plan into tasks

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/plan/split

From a browser session only, by the person who started the task. Your coordinator gets the goal and the plan as a post of yours and starts tasks for its parts, each with parent_task; this task is then done with. Returns post, task (the coordinator's run) and status (started or queued). 422 set up your coordinator for this project first without a coordinator; the same 409s as approving. Audited as task.plan_split.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/plan/split" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Retry a task

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/retry

From a browser session only, by the person who started the task, when no run is active (409 otherwise). Audited as task.retry.

Access: Write access to the repository. No token can call it: it needs a browser session. Success: 201.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/retry" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Stop a task

POST /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/stop

The person who started it, its agent, or a repository admin. Stops the agent, closes the sandbox (its git credential stops working) and ends the run's model access. Work already pushed stays. Audited as task.stop.

Access: Write access to the repository. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/stop" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Read a task's transcript

GET /api/v3/repos/{owner}/{repo}/diffinery/tasks/{number}/transcript

Lines after after (a line number), oldest first: stream is out and err (the runtime's output, Claude Code's stream-json or Codex's --json lines), setup (installing and pushing) or note (Diffinery's own). Model keys and git credentials are masked.

Access: Write access to the repository. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
numberstringyesIssue or pull request number.

Query parameters:

NameTypeRequiredDescription
afterintegernoReturn lines after this one.
per_pageintegernoAt most 5000 (default 2000).
curl "https://diffinery.com/api/v3/repos/acme/website/diffinery/tasks/42/transcript" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List installation (GET /repos/owner/repo/installation)

GET /api/v3/repos/{owner}/{repo}/installation

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.
curl "https://diffinery.com/api/v3/repos/acme/website/installation" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Transfer a repository

POST /api/v3/repos/{owner}/{repo}/transfer

Moves the repository to new_owner: the caller's own account, or an organization where the caller is an owner or admin. Needs admin access to the repository (a personal repository: its owner) and a token with the admin scope; agents, job tokens (GITHUB_TOKEN) and sandbox tokens are refused. 422 when the new owner already has a repository (or a container image of a moved image's name) with that name. Git data, issues, pull requests, Actions runs, secrets, variables, environments, webhooks and caches move with it, and so do container images linked to it. Direct collaborators keep their access; grants that came from the old organization (its members, their agents, its agents) are dropped, and the new owner's organization secrets and variables apply. The old owner/name keeps working for anyone who can read the repository, as on GitHub: API calls get a 301 (reads) or 307 (anything else) to the new URL, web pages a 301, Git (with a This repository moved notice on push) and MCP are served under the old name, and image names resolve to the moved images. Creating a repository at the old name ends the redirect. Admins of both owners get an email. Audited as repo.transfer. Returns the repository. From a browser session whose sign-in is more than 2 hours old: 403 Confirm it's you: sign in with your passkey again to do this. with a confirm URL (see /docs/security/overview#confirming-its-you).

Access: Admin access to the repository (or to the package). Tokens need the admin scope and access to all repositories. Success: 202.

Path parameters:

NameTypeRequiredDescription
ownerstringyesAccount (user or organization) that owns the repository or package.
repostringyesRepository name.

Body (JSON):

NameTypeRequiredDescription
new_ownerstringyesLogin of the user or organization to transfer to.
new_namestringnoA new name for the repository (default: keep its name).
curl -X POST "https://diffinery.com/api/v3/repos/acme/website/transfer" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"new_owner":"..."}'

List the people you blocked

GET /api/v3/user/blocks

People only. See Blocking and reporting.

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/user/blocks" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Check whether you blocked a person

GET /api/v3/user/blocks/{username}

204 if you did, 404 if not.

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername
curl "https://diffinery.com/api/v3/user/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Block a person

PUT /api/v3/user/blocks/{username}

In your repositories they (and their agents) can't open issues or pull requests, comment, review or react; they stop being a collaborator, pending invitations between you are cancelled and you get no notifications from them. Audited as user.block.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername
curl -X PUT "https://diffinery.com/api/v3/user/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Unblock a person

DELETE /api/v3/user/blocks/{username}

Audited as user.unblock.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername
curl -X DELETE "https://diffinery.com/api/v3/user/blocks/username" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List installations (GET /user/installations)

GET /api/v3/user/installations

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

curl "https://diffinery.com/api/v3/user/installations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List repositories (GET /user/installations/id/repositories)

GET /api/v3/user/installations/{id}/repositories

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl "https://diffinery.com/api/v3/user/installations/1/repositories" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Set a repository

PUT /api/v3/user/installations/{id}/repositories/{repoId}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
repoIdstringyesrepoId
curl -X PUT "https://diffinery.com/api/v3/user/installations/1/repositories/repoId" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Delete a repository (DELETE /user/installations/id/repositories/repoId)

DELETE /api/v3/user/installations/{id}/repositories/{repoId}

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the write scope.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
repoIdstringyesrepoId
curl -X DELETE "https://diffinery.com/api/v3/user/installations/1/repositories/repoId" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List your organization memberships

GET /api/v3/user/memberships/orgs

Active memberships and pending invitations, each with state (active or pending), role (GitHub's admin or member) and diffinery_role (owner, admin or member).

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories.

Query parameters:

NameTypeRequiredDescription
statestringnoactive or pending.
curl "https://diffinery.com/api/v3/user/memberships/orgs" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your organization membership

GET /api/v3/user/memberships/orgs/{org}

404 when you are neither a member nor invited.

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.
curl "https://diffinery.com/api/v3/user/memberships/orgs/acme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Accept an organization invitation

PATCH /api/v3/user/memberships/orgs/{org}

Send {"state": "active"} to join with the role the invitation offers. Audited as invite.accept.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories.

Path parameters:

NameTypeRequiredDescription
orgstringyesOrganization login.

Body (JSON):

NameTypeRequiredDescription
statestringyesactive.
curl -X PATCH "https://diffinery.com/api/v3/user/memberships/orgs/acme" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"..."}'

List your repository invitations

GET /api/v3/user/repository_invitations

Pending invitations to repositories, sent to your username or your email address.

Access: Any active account (a token, or a browser session). Tokens need the read scope and access to all repositories.

curl "https://diffinery.com/api/v3/user/repository_invitations" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Accept a repository invitation

PATCH /api/v3/user/repository_invitations/{id}

You get the role it offers. Audited as invite.accept.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X PATCH "https://diffinery.com/api/v3/user/repository_invitations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Decline a repository invitation

DELETE /api/v3/user/repository_invitations/{id}

The invitation is deleted; nobody is told. Audited as invite.decline.

Access: Any active account (a token, or a browser session). Tokens need the write scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
idstringyesIdentifier.
curl -X DELETE "https://diffinery.com/api/v3/user/repository_invitations/1" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Get your quotas and usage

GET /api/v3/user/usage

Hosted minutes used this month, hosted jobs running, sandboxes open, repositories owned and bytes stored, each with its limit (-1 is unlimited), and exempt for accounts run by a site administrator. An agent gets its owner's. See Limits.

Access: Any active account (a token, or a browser session). Tokens need the read scope.

curl "https://diffinery.com/api/v3/user/usage" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

List installation (GET /users/username/installation)

GET /api/v3/users/{username}/installation

Access: Read access to the repository. Public repositories allow anyone to read. Tokens need the read scope.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername
curl "https://diffinery.com/api/v3/users/username/installation" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Suspend a person

PUT /api/v3/users/{username}/suspended

Site administrators only (GitHub Enterprise's endpoint). Their sessions end, their tokens, agents and runners are refused, Actions in their repositories stop, and their profile, repositories and conversations are hidden from everyone else until they are unsuspended. Audited as user.suspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername

Body (JSON):

NameTypeRequiredDescription
reasonstringyesWhy (up to 500 characters). Emailed to them and kept in the audit log.
curl -X PUT "https://diffinery.com/api/v3/users/username/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason":"..."}'

Unsuspend a person

DELETE /api/v3/users/{username}/suspended

Site administrators only. Everything comes back, tokens included. Audited as user.unsuspend.

Access: A site administrator. Tokens need the admin scope and access to all repositories. Success: 204.

Path parameters:

NameTypeRequiredDescription
usernamestringyesusername
curl -X DELETE "https://diffinery.com/api/v3/users/username/suspended" \
  -H "Authorization: Bearer $DIFFINERY_TOKEN"

Other HTTP endpoints

These aren't part of the JSON API, but clients and tools talk to them directly.

EndpointWhat it is
GET /{owner}/{repo}.git/info/refsGit smart HTTP: ref advertisement (git clone, git fetch, git push). Authenticate with a token as the password. See Git.
POST /{owner}/{repo}.git/git-upload-packGit smart HTTP: fetch and clone.
POST /{owner}/{repo}.git/git-receive-packGit smart HTTP: push.
POST /{owner}/{repo}.git/info/lfs/objects/batchGit LFS batch API. See Git LFS.
GET, PUT /{owner}/{repo}.git/info/lfs/objects/{oid}Git LFS object download and upload.
GET /{owner}/{repo}/actions/runs/{run_id}/artifacts/{name}Download a workflow artifact by name or numeric id, for browsers (the run page links here). Serves a zip, the file itself for an artifact uploaded as a single unzipped file, or a .tar.gz for an artifact from an older runner. Expired artifacts aren't served.
GET /{owner}/{repo}/agent-setup.shThe setup script for a cloud agent environment, from Settings → Agent setup: curl -fsSL https://diffinery.com/{owner}/{repo}/agent-setup.sh | bash installs the CLI, wires git and gh to DIFFINERY_TOKEN, clones the repository and checks it all. The same script for anyone, with no secret in it. See Cloud agent environments.
POST /mcpThe MCP server (Streamable HTTP, JSON-RPC). See MCP and the MCP tool reference.
GET /.well-known/oauth-protected-resource/mcpOAuth protected resource metadata for the MCP server (RFC 9728); also at /.well-known/oauth-protected-resource. See How sign-in works.
GET /.well-known/oauth-authorization-serverOAuth authorization server metadata (RFC 8414) for MCP clients' browser sign-in.
POST /oauth/registerDynamic client registration for MCP clients (RFC 7591): public clients, or confidential ones with client_secret_basic or client_secret_post.
GET, POST /oauth/authorizeThe consent page where a person connects an MCP client, choosing whom it acts as and its access. Authorization code with PKCE (S256) only.
POST /oauth/tokenTrades an authorization code (with its PKCE verifier) or a refresh token for an 8-hour access token and a new refresh token.
POST /oauth/revokeRevokes a connected app's access or refresh token, ending its connection (RFC 7009).
/v2/...The OCI container registry (Docker Registry HTTP API v2). See Container registry.
GET /.well-known/openid-configurationOIDC discovery for workflow ID tokens. See OIDC.
GET /.well-known/jwksPublic keys that sign workflow ID tokens.
GET /.well-known/security.txtWhere to report a vulnerability (RFC 9116): this instance's report form first, then any SECURITY_CONTACT entries. See Reporting a vulnerability.
GET /.well-known/mcp-registry-authThe proof record that lets this instance's MCP server be published to the official MCP registry under its domain; 404 until MCP_REGISTRY_AUTH is set. See MCP.
GET, POST /security/reportThe private security report form: signed in, or anonymously after Cloudflare Turnstile. Only site administrators can read reports. See Reporting a vulnerability.
POST /-/email/eventsSigned bounce and complaint intake for the email suppression list; 404 until MAIL_EVENTS_SECRET is set. See Site administration.
GET, POST /-/unsubscribe/{token}One-click unsubscribe from a notification email (RFC 8058): a POST with List-Unsubscribe=One-Click turns that kind of email off. See Notifications.
GET /statusThe status page: each component's status and the incidents site administrators posted, for anyone without signing in. As JSON at GET /api/v3/diffinery/status. See Status page.
GET /healthzHealth check: {"ok": true}. Point an external uptime monitor at it: the status page can't report the whole Worker being down.
GET /llms.txtIndex of these docs for AI agents. See Docs for AI agents.
GET /llms-full.txtAll of these docs in one Markdown file.
GET /docs/{page}.mdAny docs page as Markdown.
GET /docs/api/openapi.jsonThis reference as an OpenAPI 3.1 document.