Create a deploy key
Add a deploy key to a repository: key, one line in OpenSSH public key format (ssh-ed25519, ecdsa-sha2-nistp256/384/521 or ssh-rsa), and a title.
/repos/{owner}/{name}/keysIt is read-only unless read_only is false, which lets it push, workflow files included. A key registered anywhere already, as a person’s SSH key or another deploy key, is refused with 409: give each machine its own. At most 100 keys a repository. Needs the Admin role on the repository and a confirmed email address; agents’ tokens and workspace tokens without Admin are refused. Recorded in the workspace’s audit log.
read_only is true unless you send false. The key’s comment is not kept; it becomes the title when you send none. Refused with 400 for a line that is not an OpenSSH public key, 409 with Key is already in use. when the key is registered already (as anyone’s SSH key or as a deploy key anywhere), 409 past 100 keys, and 403 without the Admin role, from an agent’s token, from a workspace token without Admin, or before your email address is confirmed. Recorded in the workspace’s audit log as repo.deploy_key_added.
- Authentication: Required. Send an access token as
Authorization: Bearer. - MCP tool:
accesswithactionadd_deploy_key, and the same inputs - Scope: An access token needs
access:admin.
Path parameters
Section titled “Path parameters”| Name | Type | Required | Description |
|---|---|---|---|
owner |
string | Yes | The workspace that owns the repository. |
name |
string | Yes | The repository’s name. |
Body parameters
Section titled “Body parameters”Send a JSON object. Names are snake_case, as in responses; the camelCase spelling is accepted too.
| Name | Type | Required | Description |
|---|---|---|---|
title |
string | No | A name for it, such as the machine that uses it. Left out, the key’s comment, else “Deploy key”. |
key |
string | Yes | The public key, one line in OpenSSH format: the contents of a .pub file. |
read_only |
boolean | No | False lets it push, workflow files included. True (read-only) unless you say. |
Example request
Section titled “Example request”curl -X POST https://api.g1t.sh/repos/flagon-io/hello/keys \ -H "Authorization: Bearer $G1T_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "Release bot", "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8Vq2nLr5Xw0sT3yK7mP1cH4dF6gB9aE2uZ5oN8iR0j release@ci", "read_only": false }'Example response
Section titled “Example response”A successful request answers 200 with:
{ "id": "dk_01kp3g4h5j6k7m8n9p0q1r2s3t", "title": "Release bot", "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8Vq2nLr5Xw0sT3yK7mP1cH4dF6gB9aE2uZ5oN8iR0j", "fingerprint": "SHA256:2h7VyLkcqBHwKVtfFUchGsE5pDwpgBPV/VvJgYiS27M", "read_only": false, "created_at": "2026-10-07T15:30:00.000Z", "created_by": "syntaqx", "last_used_at": null}Errors
Section titled “Errors”A failed request answers with one of these statuses and a body like {"error": {"code": "not_found", "message": "Repository not found."}}. See errors.
| Status | Code | When |
|---|---|---|
| 401 | unauthenticated |
A token is required, or the one sent is not valid. |
| 403 | forbidden |
The token is valid but not allowed to do this, such as a member-only change or an agent token outside its repository. |
| 404 | not_found |
It does not exist, or you cannot see it. |
| 409 | conflict |
The request conflicts with the current state. |
| 422 | invalid |
The input is not valid. message says which field and why. |