# Confirm an email address

> Confirm an email address with the six-digit code from the confirmation email g1t sent it.

<div class="g1t-endpoint"><span class="g1t-method" data-method="post">POST</span><code>/user/emails/confirm</code></div>

The same email has a link that does the same; either one works, once, for 60 minutes, and asking for a new email ends both. A new account must confirm its address before it can do anything else: until then this, `GET /user` and `GET /user/emails` are the only calls its token can make, and everything else, MCP included, is refused with `403`. Confirming a new account's address also invites it to the workspace its invite named, when the invite still applies: the answer's `invited_to` names it, and the invitation waits for you to accept or decline it ([`accept_invitation`](/reference/api/invites/accept-invitation/)), or `invite_lapsed` says why not. Ten wrong codes in an hour pause checking for the account. People only.

The code confirms the address it was sent to, and ends the link sent with it. A wrong, used or expired code answers `422` with one message for all three; after ten wrong codes in an hour the account answers `409` for a while, and the link in the email still works. `verified` says whether the account is confirmed: whether its primary address is. `invited_to` is set when the invite the account signed up with brings it into a workspace: confirming the address sends the account an invitation to that workspace, which it accepts with `POST /user/invitations/{id}/accept` or declines; nobody joins a workspace without saying yes. `joined` is kept for older clients and is null. When the invite was revoked or expired, or the workspace deleted, while the account waited, the address is confirmed all the same and `invite_lapsed` says so. See [Confirming your email address](/guides/authentication/#confirming-your-email-address).

- **Authentication:** Required. Send an [access token](/reference/api/#authentication) as `Authorization: Bearer`.
- **MCP tool:** [`account`](/reference/mcp/#account) with `action` `confirm_email`, and the same inputs
- **Scope:** An access token needs [`account:write`](/guides/authentication/#scopes).

## Body parameters

Send a JSON object. Names are `snake_case`, as in responses; the `camelCase` spelling is accepted too.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | string | Yes | The six-digit code from the confirmation email. Spaces and hyphens are ignored. |

## Example request

```sh
curl -X POST https://api.g1t.sh/user/emails/confirm \
  -H "Authorization: Bearer $G1T_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "482913"
  }'
```

## Example response

A successful request answers `200` with:

```json
{
  "username": "ada",
  "display_username": "Ada",
  "email": "ada@example.com",
  "verified": true,
  "joined": null,
  "invited_to": "acme",
  "invite_lapsed": null
}
```

## Errors

A failed request answers with one of these statuses and a body like `{"error": {"code": "not_found", "message": "Repository not found."}}`. See [errors](/reference/api/#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. |
