# Your first request from a browser or phone

The same flow for apps without a client secret, which use PKCE instead.

Apps that run in a browser, on a phone or on someone's computer can't keep a client secret safe. Instead, they prove who they are with [PKCE](/authentication/oauth-flow/#pkce): a random secret that's made fresh for every login. If your app runs on a server, follow [Your first request](/getting-started/first-request/) instead.

This walks you through the whole flow by hand, so you can see every step. In a real app, an OAuth library will do most of this for you.

## 1. Make a code verifier

Make a random _code verifier_ and its _code challenge_. You need a new pair every time someone logs in:

```bash
CODE_VERIFIER=$(openssl rand -base64 48 | tr -d '=+/\n' | cut -c1-64)
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=\n')
```

## 2. Ask for access

Open this link in your browser, with your own client ID and one of your redirect links:

```text
https://streetartcities.com/api/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://example.com/callback
  &scope=collections:read
  &state=anything-random
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
```

Log in if needed and click **Allow**. You end up on your redirect link, with a `code` added to it:

```text
https://example.com/callback?code=3kW9...&state=anything-random
```

## 3. Swap the code for a token

The code only works once, and only for 10 minutes:

```bash
curl -X POST https://streetartcities.com/api/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "THE_CODE",
    "redirect_uri": "https://example.com/callback",
    "client_id": "YOUR_CLIENT_ID",
    "code_verifier": "'"$CODE_VERIFIER"'"
  }'
```

You get back:

```json
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "Yh1c...",
  "scope": "collections:read"
}
```

## 4. Call the API

Send the access token in the `Authorization` header:

```bash
curl https://streetartcities.com/api/collections \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

That's it: you've got the person's collections. From here, read up on [tokens](/authentication/tokens/) to keep people logged in, or explore the [Edits API](/edits-api/overview/).
