OAuth 2.0 Authentication

Landing supports OAuth 2.0 authentication for secure third-party integrations. This guide will walk you through the process of setting up OAuth authentication for your application.

OAuth integration is only available for projects on a paid plan.

1. Create an OAuth Application

Contact support@landing.so to create a new OAuth application. You will receive:

  • Client ID
  • Client Secret
  • Authorized redirect URIs

You can also request PKCE (Proof Key for Code Exchange) configuration for enhanced security, which is recommended for public clients that cannot securely store a client secret.

2. Redirect Users to Landing’s Authorization Page

When a user wants to authorize your application, redirect them to Landing’s authorization URL with the correct parameters:

GET https://app.landing.so/oauth/authorize

Required Parameters:

ParameterDescription
client_idYour application’s client ID
redirect_uriOne of your authorized redirect URIs
response_typeMust be code
scopeComma-separated list of requested scopes
stateA random string to prevent CSRF attacks

Optional Parameters:

ParameterDescription
code_challengeBase64URL encoded SHA-256 hash of the code verifier (required if using PKCE)
code_challenge_methodMust be S256 when using PKCE

Available Scopes:

  • project.read - Read access to projects
  • pages.read - Read access to pages
  • leads.read - Read access to leads
  • user.read - Read access to user information (default)

Example Request (Standard Flow):

GET https://app.landing.so/oauth/authorize?
  response_type=code&
  client_id=YOUR_CLIENT_ID&
  redirect_uri=YOUR_REDIRECT_URI&
  scope=project.read,pages.read&
  state=random_string

Example Request (PKCE Flow):

GET https://app.landing.so/oauth/authorize?
  response_type=code&
  client_id=YOUR_CLIENT_ID&
  redirect_uri=YOUR_REDIRECT_URI&
  scope=project.read,pages.read&
  state=random_string&
  code_challenge=CODE_CHALLENGE&
  code_challenge_method=S256

3. Handle the Authorization Response

After the user approves your application, they will be redirected back to your specified redirect_uri with an authorization code:

GET https://your-redirect-uri?code=AUTHORIZATION_CODE&state=random_string

Verify that the state parameter matches the one you sent in step 2 to prevent CSRF attacks.

4. Exchange Code for Access Token

Exchange the authorization code for an access token by making a POST request:

POST https://app.landing.so/api/oauth/token

Required Parameters:

ParameterDescription
grant_typeMust be authorization_code
codeThe authorization code received in step 3
redirect_uriThe same redirect URI used in step 2
client_idYour application’s client ID

Authentication Methods (One Required):

MethodParameters
Client Secretclient_secret: Your application’s client secret
PKCEcode_verifier: The original code verifier string used to generate the code challenge

The parameters should be sent as application/x-www-form-urlencoded data.

Example Response:

{
  "access_token": "ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 315705599,
  "refresh_token": "REFRESH_TOKEN",
  "scope": "project.read pages.read"
}

5. Make API Requests

Use the access token to make authenticated requests to Landing’s API by including it in the Authorization header:

Authorization: Bearer ACCESS_TOKEN

6. Refresh Access Token

When an access token expires, use the refresh token to obtain a new one:

POST https://app.landing.so/api/oauth/token

Required Parameters:

ParameterDescription
grant_typeMust be refresh_token
refresh_tokenThe refresh token
client_idYour application’s client ID

Optional Parameters:

ParameterDescription
client_secretYour application’s client secret (required if not using PKCE)

Example Response:

{
  "access_token": "NEW_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 315705599,
  "refresh_token": "NEW_REFRESH_TOKEN"
}

User Information

Once authenticated, you can retrieve information about the authenticated user:

GET https://app.landing.so/api/oauth/userinfo
Authorization: Bearer ACCESS_TOKEN

Example Response:

{
  "user": {
    "id": "user_id",
    "email": "user@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "image": "https://..."
  },
  "project": {
    "id": "project_id",
    "name": "Project Name"
  }
}

This endpoint requires the user.read scope.