---
id: pat-update
title: Update a personal access token
description: Updates one of your personal access tokens. Send only what you want to change.
sidebar_label: Update a personal access token
hide_title: true
hide_table_of_contents: true
api: >-
  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
sidebar_class_name: patch api-method
info_path: docs/api/authorization
custom_edit_url: null
canonical: 'https://docs.nullplatform.com/docs/api/pat-update'
---
<Heading
  as={"h1"}
  className={"openapi__heading"}
  children={"Update a personal access token"}
>
</Heading>

<MethodEndpoint
  method={"patch"}
  path={"/pat/{id}"}
  context={"endpoint"}
>

</MethodEndpoint>

Updates one of your personal access tokens. Send only what you want to change.

- The expiration can only move later, up to a year from now. An expired token can't be extended. Send it as `expires_in` or `expires_at`, not both.
- `grants` replaces all of the token's grants.
- Switching to `same_as_user` drops the token's grants. Switching back to `grants` requires the grants it should have.

<Heading
  id={"request"}
  as={"h2"}
  className={"openapi-tabs__heading"}
  children={"Request"}
>
</Heading>

<ParamsDetails
  parameters={[{"name":"id","in":"path","description":"The unique identifier for the personal access token.\n","required":true,"schema":{"type":"integer"},"example":1234}]}
>

</ParamsDetails>

<RequestSchema
  title={"Body"}
  body={{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"A descriptive name for the token.","example":"local-scripts"},"expires_in":{"type":"integer","minimum":60,"maximum":2147483647,"description":"A later expiration, in seconds (at least 60), counted from the server's clock when it receives the request. Send this or `expires_at`, not both.\n\nThe same rules as `expires_at` apply to the date it resolves to. Only `expires_at` is stored and returned.\n","example":7776000},"expires_at":{"type":"string","format":"date-time","description":"A later expiration, at most a year from now. The expiration can't move earlier, and an expired token can't be extended. Send this or `expires_in`, not both.","example":"2027-04-06T00:00:00Z"},"access":{"type":"string","enum":["grants","same_as_user"],"description":"Leave it out to keep the token's current access. `same_as_user` drops the token's grants; switching back to `grants` requires `grants`.\n","example":"same_as_user"},"grants":{"type":"array","description":"The token's new grants. They replace all of its current ones.","items":{"type":"object","oneOf":[{"type":"object","required":["nrn","role_slug"],"properties":{"nrn":{"type":"string","description":"The NRN of the resource where the API key's role is assigned.","example":"organization=1:account=1:namespace=1:application=4"},"role_slug":{"type":"string","description":"The slug of the role assigned to the API key for this NRN.\n\n> Note: See [Roles](/docs/authorization/roles) for more info.\n>\n","example":"machine:ci"}},"title":"grantsRoleSlug"},{"type":"object","required":["nrn","role_id"],"properties":{"nrn":{"type":"string","description":"The NRN of the resource where the API key's role is assigned.","example":"organization=1:account=1:namespace=1:application=4"},"role_id":{"type":"integer","description":"The ID of the role assigned to the API key for this NRN.\n\n> Note: See [Roles](/docs/authorization/roles) for more info.\n>\n","example":700317756}},"title":"grantsRoleId"},{"type":"object","required":["nrn","actions"],"properties":{"nrn":{"type":"string","description":"The NRN of the resource the grant applies to.","example":"organization=1:account=1:namespace=1"},"actions":{"type":"array","description":"The actions the API key may call at this NRN, without naming an existing role.\nnullplatform creates a role private to the key carrying exactly these actions.\n\n> Note: You can only grant actions you could hand out at that NRN yourself: the ones\n> you hold there, plus the ones carried by roles you may assign to an API key there.\n>\n","items":{"type":"string"},"example":["application:read","deployment:create"]}},"title":"grantsActions"},{"type":"object","required":["nrn","inherits"],"properties":{"nrn":{"type":"string","description":"The NRN of the resource the grant applies to.","example":"organization=1:account=1"},"inherits":{"type":"array","description":"Existing roles, by slug or ID, merged into a single role private to this key.\nInheriting two roles in one grant is not the same as granting them separately:\nit produces one role, which `actions.add` and `actions.remove` can then adjust.\nYou must be allowed to assign each inherited role to an API key at this NRN, the\nsame check a grant by `role_id` passes. The key follows the roles it inherits: an\naction later added to one of them reaches the key too.\n\n> Note: A role private to another API key cannot be inherited.\n>\n","items":{"oneOf":[{"type":"string"},{"type":"integer"}]},"example":["ops","developer"]},"actions":{"type":"object","description":"How the union of the inherited roles is adjusted.","properties":{"add":{"type":"array","description":"Actions granted on top of what the inherited roles provide. Measured against what you can hand out at this NRN.","items":{"type":"string"},"example":["application:delete"]},"remove":{"type":"array","description":"Inherited actions excluded from this grant. Each must be carried by one of the inherited roles, and none may also be in `add`.","items":{"type":"string"},"example":["deployment:create"]}}}},"title":"grantsInherits"}]}},"tags":{"type":"array","description":"The token's new tags. They replace all of its current ones.","items":{"type":"object","properties":{"key":{"type":"string","description":"Tag key.","example":"team"},"value":{"type":"string","description":"Tag value.","example":"platform"}}}}},"title":"patWrite"},"examples":{"Extend the expiration":{"value":{"expires_in":7776000}},"Extend the expiration to a date":{"value":{"expires_at":"2027-04-06T00:00:00Z"}},"Follow your access":{"value":{"access":"same_as_user"}}}}}}}
>

</RequestSchema>

<StatusCodes
  id={undefined}
  label={undefined}
  responses={{"200":{"description":"The operation was successful.","content":{"application/json":{"schema":{"type":"object","required":["id","name","access","tags","grants","expires_at","created_at","updated_at"],"properties":{"id":{"type":"integer","description":"Unique ID for the token.","example":1234},"name":{"type":"string","description":"The descriptive name given to the token.","example":"local-scripts"},"masked_api_key":{"type":"string","description":"The token, masked.","example":"AAAAxxxxxPTs="},"access":{"type":"string","enum":["grants","same_as_user"],"description":"Whether the token follows your access (`same_as_user`) or holds its own grants (`grants`).","example":"same_as_user"},"tags":{"type":"array","description":"Tags associated with the token. Empty when it has none.","items":{"type":"object","required":["key","value"],"properties":{"key":{"type":"string","description":"Tag key.","example":"team"},"value":{"type":"string","description":"Tag value.","example":"platform"}}}},"grants":{"type":"array","description":"What the token can do. For a `same_as_user` token, these are your own grants in the organization at the moment of the request. A token that no longer works, because it expired or your user is inactive, reports none.\n","items":{"type":"object","properties":{"id":{"type":"integer","description":"The ID of the grant.","example":5678},"nrn":{"type":"string","description":"The NRN of the resource the grant applies to.","example":"organization=1:account=2"},"role_id":{"type":"integer","description":"The ID of the role granted.","example":700317756},"role_slug":{"type":"string","description":"The slug of the role granted.","example":"developer"},"actions":{"type":"array","description":"The action names the grant resolves to, present when it was created from `actions` or `inherits`.","items":{"type":"string"},"example":["application:read","deployment:create"]}}}},"personal":{"type":"boolean","description":"Always `true` for a personal access token.","example":true},"owner_id":{"type":"integer","description":"The ID of the user who created the token.","example":42},"acting_user_id":{"type":"integer","description":"The ID of the user the token acts as: you.","example":42},"last_used_at":{"type":"string","format":"date-time","nullable":true,"description":"The ISO-8601 UTC timestamp of when the token was last exchanged for an access token.","example":"2026-10-08T12:00:00.000Z"},"expires_at":{"type":"string","format":"date-time","description":"The ISO-8601 UTC timestamp of when the token stops working.","example":"2027-01-06T00:00:00.000Z"},"expired":{"type":"boolean","description":"Whether the token has expired.","example":false},"created_at":{"type":"string","format":"date-time","description":"The ISO-8601 UTC timestamp of when the token was created.","example":"2026-10-08T00:00:00.000Z"},"updated_at":{"type":"string","format":"date-time","description":"The ISO-8601 UTC timestamp of when the token was last updated.","example":"2026-10-08T00:00:00.000Z"}},"title":"patResponse"}}}},"4XX":{"description":"The request couldn't be processed. For example, a parameter is invalid, the resource doesn't exist, or you don't have permission. The body is a problem details object (RFC 9457).","content":{"application/problem+json":{"schema":{"type":"object","description":"Describes what went wrong, following the RFC 9457 problem details format.","required":["type","title","status"],"properties":{"type":{"type":"string","description":"A URI that identifies the kind of problem. It's an identifier, not a link, and it's the same every time this problem occurs.","example":"urn:nullplatform:error:routes-helper:invalid-params"},"title":{"type":"string","description":"A short, human-readable summary of the problem.","example":"There are invalid parameters on the request"},"status":{"type":"integer","description":"The HTTP status code of the response.","example":400},"code":{"type":"string","description":"A stable, machine-readable error code. Use it to handle specific errors in your integrations.","example":"ROUTES_HELPER.INVALID_PARAMS"},"detail":{"type":"string","nullable":true,"description":"More information about what went wrong in this request, when available.","example":null},"errors":{"type":"array","description":"One entry per invalid field or parameter. Only present on validation errors.","items":{"type":"object","properties":{"field":{"type":"string","description":"The name of the invalid field or parameter.","example":"application_id"},"in":{"type":"string","description":"Where the field was sent: `body`, `query`, or `params` (path parameters).","example":"query"},"issue":{"type":"string","description":"What's wrong with the field, such as `required` or `invalid`.","example":"invalid"},"value":{"description":"The value that was sent, when relevant.","example":"not-a-number"},"message":{"type":"string","description":"A human-readable explanation of the issue."}}}},"message":{"type":"string","deprecated":true,"description":"Same value as `title`, kept for backward compatibility. Use `title` or `code` instead.","example":"There are invalid parameters on the request"},"traceId":{"type":"string","description":"An identifier for this request, when available. Include it when you contact nullplatform support."}}}}}},"5XX":{"description":"Something went wrong on nullplatform's side. The body is a problem details object (RFC 9457).","content":{"application/problem+json":{"schema":{"type":"object","description":"Describes what went wrong, following the RFC 9457 problem details format.","required":["type","title","status"],"properties":{"type":{"type":"string","description":"A URI that identifies the kind of problem. It's an identifier, not a link, and it's the same every time this problem occurs.","example":"about:blank"},"title":{"type":"string","description":"A short, human-readable summary of the problem.","example":"Oops.. there was an internal error"},"status":{"type":"integer","description":"The HTTP status code of the response.","example":500},"code":{"type":"string","description":"A stable, machine-readable error code. Use it to handle specific errors in your integrations."},"detail":{"type":"string","nullable":true,"description":"More information about what went wrong in this request, when available.","example":null},"message":{"type":"string","deprecated":true,"description":"Same value as `title`, kept for backward compatibility. Use `title` or `code` instead.","example":"Oops.. there was an internal error"},"traceId":{"type":"string","description":"An identifier for this request, when available. Include it when you contact nullplatform support."}}}}}}}}
>

</StatusCodes>

