---
updatedAt: 2026-08-19T09:51:08.000Z
agentTools:
  projectIndex: https://developer.penneo.com/llms.txt
---

# Authenticate a user with Penneo

The browser will redirect the user to the Penneo Login page and, after a successful login, back to the
specified `redirect_uri`.<br>
A `code` parameter will be attached to the request so it can be later exchanged for an `access_token`.


# OpenAPI definition

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Penneo Authentication",
    "version": "v1",
    "description": "This page allows you to see the requests, parameters, and responses available from our API.<br><br>You will need an account to use these endpoints, you can get a trial account by visiting [penneo.com](https://penneo.com).<br><br>Please also read [the documentation](https://penneo.readme.io/docs/) before you begin.",
    "contact": {
      "name": "Penneo Support",
      "url": "https://www.support.penneo.com"
    }
  },
  "externalDocs": {
    "url": "https://penneo.readme.io/docs/",
    "description": "Penneo API documentation"
  },
  "servers": [
    {
      "url": "https://login-sandbox.penneo.com/",
      "description": "Sandbox server (uses your test data)"
    },
    {
      "url": "https://login.penneo.com/",
      "description": "Production server (uses your live data)"
    }
  ],
  "paths": {
    "/oauth/authorize": {
      "get": {
        "summary": "Authenticate a user with Penneo",
        "description": "The browser will redirect the user to the Penneo Login page and, after a successful login, back to the\nspecified `redirect_uri`.<br>\nA `code` parameter will be attached to the request so it can be later exchanged for an `access_token`.\n",
        "tags": [
          "OAuth"
        ],
        "operationId": "authorizeUser",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri",
              "example": "https://your.domain/callback"
            },
            "description": "The URL to which Penneo will redirect the browser after authorization has been granted by the user.<br>\nIt must be first registered in the client configuration.\n"
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The alphanumeric `client_id` obtained after registering your client application."
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Value derived from code verifier created in compliance with PKCE specification.<br>\nSee [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636) for more info.<br>\n**Required if the client is configured to require PKCE**, otherwise optional but strongly recommended\nfor enhanced security. If provided, you must also include `code_verifier` when exchanging the\nauthorization code for tokens.\n"
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "plain",
                "S256"
              ],
              "default": "plain"
            },
            "description": "Name of the algorithm used to calculate `code_challenge`. <br>\nRequired only if `code_challenge` is provided.<br>\nClients are **strongly recommended** to use `S256`, as it will not only preventing\n[CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) but also mitigate\n[eavesdropping](https://en.wikipedia.org/wiki/Network_eavesdropping) and\n[man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks.\n"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "An opaque value of your choice that will be included when redirecting back to your client application.<br>\nThis value is not required but **strongly recommended** to improve security and to prevent\n[CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attacks.<br> See [RFC-6749, Section\n10.12](https://www.rfc-editor.org/rfc/rfc6749#section-10.12) for more info.\n"
          }
        ],
        "responses": {
          "302": {
            "description": "Found",
            "headers": {
              "Location": {
                "schema": {
                  "format": "uri",
                  "type": "string",
                  "description": "Redirect to the specified redirect_uri with a `code` and `scope` parameters attached to the query\n",
                  "example": "'https://your.domain/callback?state=<your state value>&code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'\n"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "Missing required parameter"
              }
            }
          },
          "403": {
            "description": "Unauthorized",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "Unauthorized client"
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "Redirect URI does not match any of those defined for the client"
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "Unsupported response type"
              }
            }
          }
        }
      }
    }
  }
}
```