---
id: pat-create
title: Create a personal access token
description: >-
  Creates a personal access token that acts as you. It either follows your
  access (`access: same_as_user`) or holds the grants you send (`access:
  grants`), and every check combines it with your access at that moment, so it
  can never do more than you.
sidebar_label: Create a personal access token
hide_title: true
hide_table_of_contents: true
api: >-
  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
sidebar_class_name: post api-method
info_path: docs/api/authorization
custom_edit_url: null
canonical: 'https://docs.nullplatform.com/docs/api/pat-create'
---
<Heading
  as={"h1"}
  className={"openapi__heading"}
  children={"Create a personal access token"}
>
</Heading>

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

</MethodEndpoint>

Creates a personal access token that acts as you. It either follows your access (`access: same_as_user`) or holds the grants you send (`access: grants`), and every check combines it with your access at that moment, so it can never do more than you.

> ℹ️ **Note:** Personal access tokens are managed with your own login session. A request authenticated with an API key, a personal access token included, is rejected with a `403`.

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

<ParamsDetails
  parameters={undefined}
>

</ParamsDetails>

<RequestSchema
  title={"Body"}
  body={{"content":{"application/json":{"schema":{"type":"object","description":"An expiration is required: send `expires_in` or `expires_at`, not both. Sending both returns a `400` with id `API_KEY_SERVICE.AMBIGUOUS_EXPIRATION`.\n","required":["name"],"properties":{"name":{"type":"string","description":"A descriptive name for the token, for example where it runs.","example":"local-scripts"},"expires_in":{"type":"integer","minimum":60,"maximum":2147483647,"description":"How long the token lives, 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 expiration it resolves to must be at most a year away. Prefer `expires_in` over `expires_at`: because it counts from the server's clock, a lifetime at the limit isn't rejected when your own clock runs ahead. Only `expires_at` is stored and returned.\n","example":2592000},"expires_at":{"type":"string","format":"date-time","description":"The ISO-8601 UTC timestamp of when the token stops working. It must be in the future and at most a year away. Send this or `expires_in`, not both.","example":"2027-01-06T00:00:00Z"},"access":{"type":"string","enum":["grants","same_as_user"],"default":"grants","description":"What the token can do.\n\n- `same_as_user`: the token follows your access in the organization, including roles you get or lose later. Send no `grants`.\n- `grants`: the token holds only the `grants` you send.\n\nEither way, every check combines the token's access with yours at that moment.\n","example":"same_as_user"},"grants":{"type":"array","description":"Required when `access` is `grants`, and not allowed with `same_as_user`. Every item carries an `nrn` plus one of the shapes an API key grant takes: `role_id` or `role_slug`, `actions`, or `inherits` with `actions.add` and `actions.remove`.\n\n> ℹ️ **Note:** You can only grant roles you hold on that resource or one above it, and actions you hold there.\n","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":"Tags to find the token by. Each key can appear only once.","items":{"type":"object","properties":{"key":{"type":"string","description":"Tag key.","example":"team"},"value":{"type":"string","description":"Tag value.","example":"platform"}}}}},"title":"patNew"},"examples":{"Same access as you":{"value":{"name":"local-scripts","expires_in":2592000,"access":"same_as_user","tags":[{"key":"team","value":"platform"}]}},"Read-only grant on one account":{"value":{"name":"read-only-reports","expires_at":"2027-01-06T00:00:00Z","access":"grants","grants":[{"nrn":"organization=1:account=2","role_slug":"member"}]}}}}}}}
>

</RequestSchema>

<StatusCodes
  id={undefined}
  label={undefined}
  responses={{"201":{"description":"The operation was successful.","content":{"application/json":{"schema":{"allOf":[{"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"},{"type":"object","required":["api_key"],"properties":{"api_key":{"type":"string","description":"Your new personal access token.\n\n>\n> ⚠️ **Save your token securely.**\n>\n> The token is displayed only once. Make sure to store it in a secure location as it cannot be retrieved later.","example":"AAAA.1234567890abcdef1234567890abcdefPTs="}}}],"title":"patPostResponse"}}}},"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>

