# Turn a sign-in request down

**POST** `/api/embed/v1/oauth-requests/{requestId}/deny`

Turns an AI app’s sign-in request down.

Needs a partner key: `Authorization: Bearer gre_…`, from [Platform › Partner keys](https://docs.gorunner.io/embed/platform-screens#partner-keys). Call it from your server only.

Embed · Self-hosted with an Embed license

## Parameters

### Path

- `requestId` · Required · string: The request’s ID: the `gr_request` parameter on the address the person arrived at.

### Body

Optional.

- `reason` · Optional · string: `cancelled` (the default), `not_member`, `not_allowed` or `role`, such as to keep viewers out.

## When to turn it down

When the person pressed Cancel, doesn’t belong to the account, or you refuse them. Viewers and operators may connect otherwise, read only and read and run. Once per request; audited `embed.oauth.denied`.

## Responses

- 200 OK

  Send the browser to `continueUrl` with a 303: the app is told it wasn’t allowed.

- 400 `VALIDATION_ERROR`

  `reason` isn’t one of the four.

- 404 `OAUTH_REQUEST_NOT_FOUND`

  No such request, or it expired.

- 409 `OAUTH_REQUEST_DONE`

  It was already answered. It carries `details.continueUrl`: send the browser there so the AI app is told.

- 500 `INTERNAL_ERROR`

  Something failed on the installation’s side. Try again.

Any call can also answer: [`401 UNAUTHORIZED`](https://docs.gorunner.io/errors#UNAUTHORIZED) · [`403 EMBED_NOT_LICENSED`](https://docs.gorunner.io/errors#EMBED_NOT_LICENSED) · [`403 IP_NOT_ALLOWED`](https://docs.gorunner.io/errors#IP_NOT_ALLOWED) · [`413 PAYLOAD_TOO_LARGE`](https://docs.gorunner.io/errors#PAYLOAD_TOO_LARGE) · [`415 INVALID_CONTENT_TYPE`](https://docs.gorunner.io/errors#INVALID_CONTENT_TYPE) · [`429 RATE_LIMITED`](https://docs.gorunner.io/errors#RATE_LIMITED) · [`503 BUSY`](https://docs.gorunner.io/errors#BUSY). See [Errors](https://docs.gorunner.io/embed/api#errors).

Request

**curl**

```bash
GORUNNER="https://automations.example.com"
GORUNNER_EMBED_KEY="YOUR_PARTNER_KEY"  # gre_…
REQUEST_ID="q7Kd2mXr9TfL0aZc3vBn8wYe"  # gr_request from the address

URL="$GORUNNER/api/embed/v1/oauth-requests/"
URL="${URL}$REQUEST_ID/deny"
curl -X POST "$URL" \
  -H "Authorization: Bearer $GORUNNER_EMBED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "not_member"
  }'
```

**JavaScript**

```js
const GORUNNER = "https://automations.example.com";
const KEY = process.env.GORUNNER_EMBED_KEY; // gre_…
const REQUEST_ID = encodeURIComponent("q7Kd2mXr9TfL0aZc3vBn8wYe");

const res = await fetch(
  `${GORUNNER}/api/embed/v1/oauth-requests/` +
    `${REQUEST_ID}/deny`,
  {
    method: "POST",
    headers: {
        Authorization: `Bearer ${KEY}`,
        "Content-Type": "application/json",
      },
    body: JSON.stringify({ reason: "not_member" }),
  },
);
const { data } = await res.json();
```

**Python**

```python
import os, requests
from urllib.parse import quote

GORUNNER = "https://automations.example.com"
KEY = os.environ["GORUNNER_EMBED_KEY"]  # gre_…
REQUEST_ID = quote("q7Kd2mXr9TfL0aZc3vBn8wYe", safe="")

res = requests.post(
    f"{GORUNNER}/api/embed/v1/oauth-requests/"
    f"{REQUEST_ID}/deny",
    headers={"Authorization": f"Bearer {KEY}"},
    json={"reason": "not_member"},
)
data = res.json()["data"]
```

Response · 200 OK

```json
{
  "data": {
    "continueUrl": "https://automations.example.com/api/embed/oauth/return?request=q7Kd2mXr9TfL0aZc3vBn8wYe&ticket=…"
  }
}
```

**Every field**

### Body

- `reason` · Optional · string: One of `not_member`, `not_allowed`, `role`, `cancelled`. Default `cancelled`.

### Response · 200 OK

- `data` · object
  - `continueUrl` · URL

Related: [Sign a person in for an AI app](https://docs.gorunner.io/embed/api/ai-apps/complete-oauth-request)

Source: https://docs.gorunner.io/embed/api/ai-apps/deny-oauth-request
