> ## Documentation Index
> Fetch the complete documentation index at: https://www.1password.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an access request

> Describe the task and the logins it needs. 1Password shows the request to the person, and they choose which of their logins to grant.

export const StatusBadge = ({children}) => <span className="op-status-badge not-prose">{children}</span>;

<StatusBadge>Partner preview</StatusBadge>

An access request describes the task and the websites where your agent needs to sign in. 1Password shows the request to the person, who chooses which of their logins, if any, to grant for each website. You never specify a 1Password item.

## Batch what the task needs

Create one request per task, with every login the task needs, before your agent starts. One request can include up to five login entries. Waiting until the agent reaches each sign-in page means more prompts and more waiting for the person.

If you already hold a reference for a login from an earlier approval and your product doesn't promise per-session approval, use it to fill the login instead of asking again. Create a new request only for a website you don't yet have a reference for, or when a fill fails because access ended.

## The request

```javascript theme={null}
{
  version: 2,
  goal: "Book a table for Friday and add it to my calendar",
  entries: [
    {
      type: "login",
      parameters: { website: "https://www.opentable.com" },
      reason: "Sign in to book the table",
      keywords: ["opentable"],
    },
    {
      type: "login",
      parameters: { website: "https://calendar.google.com" },
      reason: "Add the reservation to your calendar",
      keywords: ["personal", "google"],
    },
  ],
}
```

<ParamField body="goal" type="string">
  A description of the task, shown to the person above the logins. Up to 140 characters. Plain text only: 1Password removes invisible and control characters before it validates the request, so don't rely on them being kept.
</ParamField>

<ParamField body="entries" type="object[]" required>
  The logins you need, shown in the order you send them. Between 1 and 5.

  <Expandable title="entry properties">
    <ParamField body="type" type="string" required>
      The credential type, case-sensitive. `login` is the only supported value.
    </ParamField>

    <ParamField body="parameters.website" type="string" required>
      The website where the login will be used, up to 2,083 characters. Send a complete HTTPS URL, such as `https://github.com`. 1Password uses it to suggest matching logins. A login entry without a website is rejected.

      Before it validates the website, 1Password trims leading and trailing whitespace, removes invisible and control characters, and treats a value without a scheme as HTTPS. The result must be a valid absolute URL under the [WHATWG URL Standard](https://url.spec.whatwg.org/). Other schemes can pass validation, but web login matching and browser use need a complete HTTP or HTTPS URL.
    </ParamField>

    <ParamField body="reason" type="string">
      Why this specific login is needed, shown next to it. Up to 100 characters. 1Password removes invisible and control characters before it validates the request. An empty reason is accepted but displays no explanation, so provide one.
    </ParamField>

    <ParamField body="keywords" type="string[]">
      Terms from the person's request that help 1Password rank the right login, such as a company name, a product name, or a nickname they gave the account. Between 1 and 5 keywords, each 1 to 50 characters. An empty array is the same as leaving the field out. Keywords rank suggestions. They don't filter them, and the person can always pick a different login. Keywords aren't shown to the person.
    </ParamField>
  </Expandable>
</ParamField>

You don't supply a request ID or entry IDs: 1Password assigns them and returns them. Fields not listed here are ignored.

## Write text the person can act on

The person sees your goal and reasons exactly as you send them. 1Password doesn't translate or rewrite them.

* Write in the person's language, in words they'd use.
* Keep personal names, message content, account identifiers, and secrets out of every field.
* No markup or control characters.
* Say what the agent will do with the login, not how it works.

| Field | Clear | Unclear |
| - | - | - |
| `goal` | Cancel my GitHub Pro subscription | Execute subscription management workflow |
| `reason` | Sign in to cancel the subscription | Required for task step 3 |
| `reason` | Download last month's invoice | Access account for Jane Doe ([jane@example.com](mailto:jane@example.com)) |
| `keywords` | `["work", "github"]` | `["password", "login", "credentials"]` |

## Design good requests

A good request is:

* **Recognizable:** the person understands the task.
* **Specific:** each entry describes one concrete login the task needs.
* **Minimal:** it asks only for the logins the task needs.
* **Non-sensitive:** it leaves out secrets and personal context that doesn't matter.
* **Person-centered:** the goal and reasons describe actions the person recognizes.
* **Flexible:** it doesn't assume which item the person will pick.

<CodeGroup>
  ```json Good theme={null}
  {
    "goal": "Cancel unused software subscriptions",
    "entries": [
      {
        "type": "login",
        "parameters": { "website": "https://github.com" },
        "reason": "Sign in to cancel GitHub Pro",
        "keywords": ["personal"]
      }
    ]
  }
  ```

  ```json Avoid theme={null}
  {
    "goal": "Execute workflow node 17",
    "entries": [
      {
        "type": "login",
        "parameters": { "website": "https://github.com" },
        "reason": "The browser tool requires authentication",
        "keywords": ["item 8F3D2A"]
      }
    ]
  }
  ```
</CodeGroup>

The first explains the task to the person. The second describes your implementation and tries to decide which item the person picks.

## Where the request text goes

Your goal, reasons, keywords, and websites travel to the person's 1Password app inside the approval link, which is why you [treat the link as sensitive](/agentic-autofill/partners/approval#deliver-the-approval-link).

## Create the request

Call `api.agenticAutofill.v1.createAccessRequest` on the extension's service worker. See [Fill with the browser extension](/agentic-autofill/partners/fill#call-the-extension-over-cdp) for how to reach it.

```javascript theme={null}
const result = await api.agenticAutofill.v1.createAccessRequest({
  accessToken,
  integrationKey,
  requests: {
    version: 2,
    goal: "Manage SaaS subscriptions",
    entries: [
      {
        type: "login",
        parameters: { website: "https://github.com" },
        keywords: ["personal"],
        reason: "Cancel GitHub Pro subscription",
      },
    ],
  },
});

if (!result.success) throw new Error(result.error.code);
const { accessRequest, appLink } = result.result;
```

## The response

```javascript theme={null}
{
  success: true,
  result: {
    accessRequest: {
      path: "accounts/<account>/credential-broker-access-requests/<access-request-id>",
      id: "<access-request-id>",
      identity: "<target-identity-path>",
      state: "pending",
      createdAt: "<RFC 3339 timestamp>",
      goal: "Manage SaaS subscriptions",
      entries: [
        {
          id: "<entry-id>",
          type: "login",
          parameters: { website: "https://github.com" },
          keywords: ["personal"],
          reason: "Cancel GitHub Pro subscription",
        },
      ],
    },
    appLink: "onepassword://grant-brokered-access?access_request_reference=<opaque-reference>",
  },
}
```

Store the access request. You need:

* `accessRequest.id` to check its status. Use the `id`, not the `path`.
* Each `accessRequest.entries[].id` to match what the person grants to what you asked for.
* `appLink` to open the approval prompt on the person's device.

The request, its ID, and its entry IDs belong to this connection. You can create a request in one browser session and continue in another, as long as both use the same person's token and integration key.

## Errors

| Code | Cause | What to do |
| - | - | - |
| `invalidRequest` | The method or its parameters are malformed. | Fix the request before you retry. |
| `authenticationFailed` | The access token is invalid or expired. | Refresh the token on your backend, then retry. |
| `internal` | Anything else, including a request that breaks a limit, such as a goal over 140 characters or more than five entries. | Check the limits above. If the request is valid, retry once, then contact 1Password with the extension logs. |


## Related topics

- [Request an access token](/api-reference/authentication/request-an-access-token.md)
- [Authorize your integrations using OAuth 2.0](/users-api/authorization.md)
- [Get started with the 1Password Users API for Partners (Public Preview)](/users-api/get-started.md)
