Skip to Content

REST API Authentication

Learn how to authenticate your requests to the Layer One REST API. Obtain an access token by authenticating with the authorization server, enabling secure and authorized access to all API endpoints.

Authentication Endpoints

Production

https://api.integrated-projects.com/v1/authentication/token

Staging

https://staging-api.integrated-projects.com/v1/authentication/token

Authentication Flow

The Layer One API uses OAuth 2.0 client credentials flow for authentication:

  1. Request credentials from IPX team to retrieve client ID and client secret
  2. App makes an HTTP call to an OAuth REST endpoint and provides its credentials
  3. An access token is returned to your app
  4. In making subsequent calls to various APIs, your app includes the access token in a request header

Creating an Access Token

Request Method

POST /v1/authentication/token

Headers

Authorization: Basic <BASE64_ENCODED_CLIENT_ID_AND_SECRET> Content-Type: application/json

Request Body

{ "client_id": "<client_id>", "client_secret": "<client_secret>", "grant_type": "client_credentials" }

Parameters

ParameterTypeDescription
client_idstringClient ID of the app
client_secretstringClient secret of the app
grant_typestringReturns a access token if type is client_credentials

Response

{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIngrOVd4R1dUR1ZeBeKNhS8aq2URXM2qUzxBEUVAM...", "token_type": "Bearer", "expires_in": 3599 }

Response Parameters

ParameterTypeDescription
access_tokenstringAccess token
token_typestringWill always be Bearer
expires_innumberAccess token expiration time (in seconds)

Using the Access Token

Include the access token in the Authorization header of all subsequent API requests:

curl -X GET \ https://api.integrated-projects.com/v1/projects \ -H "Authorization: Bearer your-access-token-here" \ -H "Content-Type: application/json"

Revoking an Access Token

You can revoke an access token when it’s no longer needed, such as during logout or security incidents.

Request Method

POST /v1/authentication/revoke

Endpoints

  • Production: https://api.integrated-projects.com/v1/authentication/revoke
  • Staging: https://staging-api.integrated-projects.com/v1/authentication/revoke

Request Body

{ "client_id": "<client_id>", "access_token": "<access_token>" }

Parameters

ParameterTypeDescription
client_idstringClient ID of the app
access_tokenstringAccess token to revoke

Response

Success Response:

{ "success": true, "error": null }

Error Response:

{ "success": false, "error": "Error message if applicable" }

Example Request

curl -X POST \ https://api.integrated-projects.com/v1/authentication/revoke \ -H "Content-Type: application/json" \ -d '{ "client_id": "4cf37e68-22a1-43be-ab7c-88ff51c4d903", "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs..." }'

Introspecting an Access Token

View access token details by supplying the token and client_id. This is useful for validating tokens and checking their expiration status.

Request Method

POST /v1/authentication/introspect

Endpoints

  • Production: https://api.integrated-projects.com/v1/authentication/introspect
  • Staging: https://staging-api.integrated-projects.com/v1/authentication/introspect

Request Body

{ "client_id": "<client_id>", "access_token": "<access_token>" }

Parameters

ParameterTypeDescription
client_idstringClient ID
access_tokenstringAccess token

Response

Success Response:

{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...", "token_type": "Bearer", "expires_at": "2025-06-03T11:42:44.840Z", "revoked": false }

Error Response:

{ "error": "invalid_credentials" }

Response Parameters

ParameterTypeDescription
access_tokenstringAccess token
token_typestringBearer
expires_atstringTimestamp of token expiration
revokedbooleantrue/false

Example Request

curl -X POST \ https://api.integrated-projects.com/v1/authentication/introspect \ -H "Content-Type: application/json" \ -d '{ "client_id": "4cf37e68-22a1-43be-ab7c-88ff51c4d903", "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs..." }'

Complete Authentication Example

Step 1: Encode Credentials

First, encode your client ID and secret in Base64 format:

# Format: client_id:client_secret echo -n "your_client_id:your_client_secret" | base64

Step 2: Request Access Token

curl -X POST \ https://api.integrated-projects.com/v1/authentication/token \ -H "Authorization: Basic <BASE64_ENCODED_CLIENT_ID_AND_SECRET>" \ -H "Content-Type: application/json" \ -d '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "grant_type": "client_credentials" }'

Step 3: Use Access Token

curl -X GET \ https://api.integrated-projects.com/v1/projects \ -H "Authorization: Bearer your-access-token-here" \ -H "Content-Type: application/json"

Code Examples

JavaScript/Node.js

const axios = require('axios'); // Step 1: Get access token const getAccessToken = async (clientId: string, clientSecret: string): Promise<string> => { const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64'); const response = await axios.post( 'https://api.integrated-projects.com/v1/authentication/token', { client_id: clientId, client_secret: clientSecret, grant_type: 'client_credentials' }, { headers: { 'Authorization': `Basic ${credentials}`, 'Content-Type': 'application/json' } } ); return response.data.access_token; }; // Step 2: Use access token for API calls const makeAPICall = async (accessToken: string) => { const response = await axios.get( 'https://api.integrated-projects.com/v1/projects', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' } } ); return response.data; }; // Step 3: Revoke access token when done const revokeAccessToken = async (clientId: string, accessToken: string): Promise<boolean> => { const response = await axios.post( 'https://api.integrated-projects.com/v1/authentication/revoke', { client_id: clientId, access_token: accessToken }, { headers: { 'Content-Type': 'application/json' } } ); return response.data.success; }; // Step 4: Introspect access token const introspectAccessToken = async (clientId: string, accessToken: string) => { const response = await axios.post( 'https://api.integrated-projects.com/v1/authentication/introspect', { client_id: clientId, access_token: accessToken }, { headers: { 'Content-Type': 'application/json' } } ); return response.data; }; // Usage const clientId = process.env.IPX_CLIENT_ID; const clientSecret = process.env.IPX_CLIENT_SECRET; const accessToken = await getAccessToken(clientId, clientSecret); const projects = await makeAPICall(accessToken); // Check token status const tokenInfo = await introspectAccessToken(clientId, accessToken); console.log('Token expires at:', tokenInfo.expires_at); console.log('Token revoked:', tokenInfo.revoked); // Revoke token when done await revokeAccessToken(clientId, accessToken);

Python

import requests import base64 import os def get_access_token(client_id: str, client_secret: str) -> str: # Encode credentials credentials = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode() headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/json' } data = { 'client_id': client_id, 'client_secret': client_secret, 'grant_type': 'client_credentials' } response = requests.post( 'https://api.integrated-projects.com/v1/authentication/token', headers=headers, json=data ) return response.json()['access_token'] def make_api_call(access_token: str): headers = { 'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json' } response = requests.get( 'https://api.integrated-projects.com/v1/projects', headers=headers ) return response.json() def revoke_access_token(client_id: str, access_token: str) -> bool: data = { 'client_id': client_id, 'access_token': access_token } response = requests.post( 'https://api.integrated-projects.com/v1/authentication/revoke', headers={'Content-Type': 'application/json'}, json=data ) return response.json()['success'] def introspect_access_token(client_id: str, access_token: str): data = { 'client_id': client_id, 'access_token': access_token } response = requests.post( 'https://api.integrated-projects.com/v1/authentication/introspect', headers={'Content-Type': 'application/json'}, json=data ) return response.json() # Usage client_id = os.getenv('IPX_CLIENT_ID') client_secret = os.getenv('IPX_CLIENT_SECRET') access_token = get_access_token(client_id, client_secret) projects = make_api_call(access_token) # Check token status token_info = introspect_access_token(client_id, access_token) print(f"Token expires at: {token_info['expires_at']}") print(f"Token revoked: {token_info['revoked']}") # Revoke token when done revoke_success = revoke_access_token(client_id, access_token)

Security Best Practices

Credential Security

  • Never expose client credentials in client-side code
  • Use environment variables to store client ID and secret
  • Rotate credentials regularly for enhanced security
  • Use different credentials for different environments (dev, staging, production)

Environment Configuration

# .env file IPX_CLIENT_ID=your_client_id_here IPX_CLIENT_SECRET=your_client_secret_here IPX_BASE_URL=https://api.integrated-projects.com/v1

Token Management

  • Store tokens securely in memory or secure storage
  • Handle token expiration by implementing automatic refresh
  • Monitor token usage and implement proper error handling
  • Revoke tokens when they’re no longer needed (logout, security incidents)
  • Use introspection to validate token status and expiration

Testing Authentication

You can test your authentication setup by making a request to get an access token:

curl -X POST \ https://api.integrated-projects.com/v1/authentication/token \ -H "Authorization: Basic <BASE64_ENCODED_CLIENT_ID_AND_SECRET>" \ -H "Content-Type: application/json" \ -d '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "grant_type": "client_credentials" }'

Success Response:

{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...", "token_type": "Bearer", "expires_in": 3599 }

Error Response:

{ "error": "invalid_client", "error_description": "Invalid client credentials" }

Token Expiration and Refresh

Access tokens have a limited lifespan (typically 1 hour). When a token expires, you’ll need to request a new one:

const handleTokenExpiration = async (clientId: string, clientSecret: string) => { try { // Check if token is still valid const tokenInfo = await introspectAccessToken(clientId, currentToken); if (tokenInfo.revoked || new Date(tokenInfo.expires_at) < new Date()) { // Token is expired or revoked, get a new one const newToken = await getAccessToken(clientId, clientSecret); return await makeAPICall(newToken); } // Token is still valid, use it const response = await makeAPICall(currentToken); return response; } catch (error) { if (error.status === 401) { // Token expired, get a new one const newToken = await getAccessToken(clientId, clientSecret); // Retry the API call with new token return await makeAPICall(newToken); } throw error; } };

Troubleshooting

Common Authentication Errors

ErrorDescriptionSolution
invalid_clientInvalid client credentialsVerify your client ID and secret
unauthorizedMissing or invalid authorization headerCheck Base64 encoding of credentials
invalid_grantInvalid grant typeEnsure grant_type is “client_credentials”
401 UnauthorizedExpired or invalid access tokenRequest a new access token

Getting Help

If you’re experiencing authentication issues:

  1. Verify your client ID and secret are correct
  2. Check that you’re using the correct endpoint (production vs staging)
  3. Ensure your Base64 encoding is correct
  4. Verify the request body format matches the specification
  5. Contact support if issues persist
Last updated on