Build secure integrations that access PortTask on behalf of users. Our OAuth 2.0 implementation supports Authorization Code with PKCE, Client Credentials, and Refresh Token flows.
For web and mobile apps that act on behalf of a user. Users authorize your app through the browser with consent screen.
For server-to-server integrations without user interaction. Ideal for backend services, cron jobs, and automated systems.
Maintain long-lived sessions without re-authorization. Exchange expired access tokens for fresh ones silently.
Choose the flow that matches your application type.
GET https://app.porttask.com/oauth/authorize?
client_id=pt_client_aBcDeFgHiJkLmNoPqRsTu
&redirect_uri=https://yourapp.com/callback
&response_type=code
&scope=port-calls:read vessels:read
&state=random_csrf_token
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256POST https://app.porttask.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=pt_client_aBcDeFgHiJkLmNoPqRsTu
&client_secret=pt_secret_YourClientSecret
&code=pt_code_receivedFromCallback
&redirect_uri=https://yourapp.com/callback
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk{
"access_token": "pt_access_eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "pt_refresh_dGhpcyBpcyBhIHJl...",
"scope": "port-calls:read vessels:read"
}Access tokens expire after 1 hour. Use the refresh token to obtain a new access token without requiring user re-authorization. Refresh tokens are valid for 30 days.
POST https://app.porttask.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&client_id=pt_client_aBcDeFgHiJkLmNoPqRsTu
&client_secret=pt_secret_YourClientSecret
&refresh_token=pt_refresh_dGhpcyBpcyBhIHJl...Our SDKs handle the OAuth flow for you, including PKCE, token storage, and automatic refresh.
import { PortTaskOAuth } from '@porttask/sdk';
const oauth = new PortTaskOAuth({
clientId: process.env.PORTTASK_CLIENT_ID,
clientSecret: process.env.PORTTASK_CLIENT_SECRET,
redirectUri: 'https://yourapp.com/callback',
});
// Step 1: Generate authorization URL
const authUrl = oauth.getAuthorizationUrl({
scope: ['port-calls:read', 'vessels:read'],
state: generateCSRFToken(),
});
// Step 2: Handle callback and exchange code for token
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
verifyCSRFToken(state);
const tokens = await oauth.exchangeCode(code);
// tokens.accessToken, tokens.refreshToken
// Step 3: Use the access token
const client = oauth.getClient(tokens.accessToken);
const portCalls = await client.portCalls.list();
});from porttask import PortTaskOAuth
oauth = PortTaskOAuth(
client_id=os.environ["PORTTASK_CLIENT_ID"],
client_secret=os.environ["PORTTASK_CLIENT_SECRET"],
redirect_uri="https://yourapp.com/callback",
)
# Step 1: Generate authorization URL
auth_url = oauth.get_authorization_url(
scope=["port-calls:read", "vessels:read"],
state=generate_csrf_token(),
)
# Step 2: Exchange code for tokens (in your callback handler)
tokens = oauth.exchange_code(code=request.args["code"])
# Step 3: Make authenticated requests
client = oauth.get_client(tokens.access_token)
port_calls = client.port_calls.list()Scopes define what your OAuth application can access. Request only the scopes your application needs -- users will see these permissions on the consent screen.
| Scope | Description | Access Level |
|---|---|---|
read:port_calls | Read port calls and related data | port_calls |
write:port_calls | Create and update port calls | port_calls |
delete:port_calls | Delete port calls | port_calls |
read:service_orders | Read service orders | service_orders |
write:service_orders | Create and update service orders | service_orders |
read:vendors | Read vendor information | vendors |
write:vendors | Manage vendor relationships | vendors |
read:vessels | Read vessel information | vessels |
read:documents | Read documents | documents |
write:documents | Upload and manage documents | documents |
read:invoices | Read invoices and billing | invoices |
write:invoices | Create and manage invoices | invoices |
read:analytics | Access analytics and reports | analytics |
ai:predictions | Use AI prediction endpoints | predictions |
webhooks:manage | Manage webhook subscriptions | manage |
admin | Full administrative access | read |
Select the appropriate grant type based on your application architecture.
authorization_codeStandard OAuth 2.0 flow for web applications. Users authorize your app via the browser.
client_credentialsMachine-to-machine authentication without user interaction. For server-side integrations.
refresh_tokenExchange a refresh token for a new access token. Enables long-lived sessions.
Follow these steps to set up OAuth for your application.
Navigate to the PortTask Control Panel and create a new OAuth application. You will need to provide:
After registration, you will receive a Client ID and Client Secret. Store the client secret securely -- it is only shown once.
| Endpoint | Method | Description |
|---|---|---|
/oauth/authorize | GET | Starts the authorization flow. Redirect users here. |
/oauth/token | POST | Exchange authorization code for tokens, or refresh an access token. |
/oauth/revoke | POST | Revoke an access token or refresh token. |
/oauth/userinfo | GET | Get information about the authenticated user. |
/.well-known/openid-configuration | GET | OpenID Connect discovery document. |
OAuth errors follow the standard error response format defined in RFC 6749.
| Error Code | Description | Resolution |
|---|---|---|
invalid_request | Missing or malformed parameter | Check required parameters are present and correctly formatted |
unauthorized_client | Client not authorized for this grant type | Verify grant type is enabled for your OAuth app |
access_denied | User denied the authorization request | Show a message explaining why access is needed |
invalid_scope | Requested scope exceeds allowed scopes | Only request scopes that are configured for your app |
invalid_grant | Authorization code expired or already used | Codes expire after 10 minutes; restart the authorization flow |
invalid_client | Client authentication failed | Verify client_id and client_secret are correct |
{
"error": "invalid_grant",
"error_description": "The authorization code has expired. Please restart the authorization flow."
}Register an OAuth application and start building secure integrations with PortTask today.