The Outlign API uses OAuth2 for secure authentication. This allows users to grant your application access to their data without sharing their credentials.
Outlign implements the standard OAuth2 authorization code flow. The process involves redirecting users to authenticate with Outlign, then exchanging the authorization code for access tokens.
Redirect to Authorization URL
Send users to Outlign's authorization endpoint
User Grants Permission
User logs in and authorizes your application
Exchange Code for Tokens
Your app receives an authorization code and exchanges it for access tokens
Make Authenticated Requests
Include the access token in API requests
Direct users to the authorization URL with the required parameters:
GET https://go.outlign.co/oauth/authorize
| Parameter | Type | Description |
|---|---|---|
| client_id | string | Your application's client ID |
| redirect_uri | string | URL to redirect to after authorization |
| response_type | string | Must be "code" |
| scope | string | Requested permissions: "outlign:all" |
| state | string | Optional security parameter to prevent CSRF attacks |
After the user authorizes your application, they'll be redirected to your redirect_uri with an authorization code. Exchange this code for an access token:
POST https://go.outlign.co/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&code=AUTHORIZATION_CODE
&redirect_uri=YOUR_REDIRECT_URI
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
"refresh_token": "def50200c7dd...",
"token_type": "Bearer",
"expires_in": 3600
}
Include the access token in the Authorization header of your API requests:
GET https://go.outlign.co/api/v1/companies
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
Access tokens expire after 1 hour. Use the refresh token to obtain a new access token without requiring user re-authentication:
POST https://go.outlign.co/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&refresh_token=YOUR_REFRESH_TOKEN
Important: Store refresh tokens securely and implement automatic token refresh in your application to maintain uninterrupted API access.
First-party integrations request the outlign:all scope, which grants full access to the
API. Agent-style integrations (for example, AI assistants connecting over OAuth) can instead request a
narrower set of granular scopes, so a user can grant read-only access without exposing
writes. When a token carries any granular scope, the REST API enforces it on every request: safe
methods (GET) require a read scope and writes (POST, PUT,
PATCH, DELETE) require a write scope.
| Scope | Grants |
|---|---|
| outlign:all | Full read & write access to the entire API (default for first-party apps) |
| projects:read | Read companies, clients, projects, phases, and milestones |
| projects:write | Create and update projects, phases, and milestones |
| steps:read | Read tasks (steps), assignees, and messages |
| steps:write | Create, update, and assign tasks (steps) |
| comments:write | Post, edit, and delete comments and messages |
| search | Use the Search endpoint |
| mcp:use | Connect to the Outlign MCP (agent) server |
Request multiple scopes by space-separating them in the scope parameter of the
authorization URL, for example scope=projects:read steps:read search.
How enforcement works: A token holding projects:write,
steps:write, or comments:write also satisfies the read requirement for
that area. Tokens with the legacy outlign:all scope (and other first-party tokens) are
never scope-restricted and keep full access.
{
"message": "Your access token does not include the required scope for this action."
}
Verify your authentication is working by making a request to the user info endpoint:
GET https://go.outlign.co/api/v1/me
{
"id": 123,
"email": "user@example.com",
"name": "John Doe"
}
Authentication errors return appropriate HTTP status codes and error messages:
{
"message": "Unauthenticated."
}
{
"message": "This action is unauthorized."
}