Articles on: Getting Started

Client Portal API

Client Portal API


Overview


The Client Portal API allows you to programmatically manage portal invitations, retrieve portal configuration, and generate portal access tokens.


Base URL


All endpoints are under /api/v1/client-portal/


Authentication


All endpoints require authentication using a Bearer token:


Authorization: Bearer your-api-token-here


Endpoints


Get Portal Configuration


Get the current portal configuration for the authenticated tenant.


Endpoint: GET /api/v1/client-portal/config


Response:

{
"data": {
"portal_name": "Client Portal",
"portal_logo": "portal-logos/logo.png",
"primary_color": "#3B82F6",
"secondary_color": "#1E40AF",
"welcome_message": "Welcome to your client portal!",
"enabled_modules": ["invoices", "proposals", "tasks"],
"is_active": true,
"allow_file_sharing": true,
"show_activity_feed": true,
"token_expiration_days": 30
}
}


Example:

curl -H "Authorization: Bearer your-token" \
https://your-domain.com/api/v1/client-portal/config



Send Portal Invitation to Contact


Send a portal access invitation email to a contact.


Endpoint: POST /api/v1/client-portal/contacts/{contactId}/invite


URL Parameters:

  • contactId (required) - The ID of the contact


Request Body:

{
"custom_message": "Welcome to your client portal! Click the link below to access your invoices, proposals, and more."
}


Response:

{
"message": "Portal invitation sent successfully",
"token": "portal-access-token-here"
}


Example:

curl -X POST \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"custom_message": "Welcome!"}' \
https://your-domain.com/api/v1/client-portal/contacts/1/invite


Error Responses:

  • 400 Bad Request - Contact doesn't have an email address
  • 404 Not Found - Contact not found
  • 500 Internal Server Error - Failed to send invitation



Send Portal Invitation to Company


Send a portal access invitation email to a company.


Endpoint: POST /api/v1/client-portal/companies/{companyId}/invite


URL Parameters:

  • companyId (required) - The ID of the company


Request Body:

{
"custom_message": "Welcome to your company portal!"
}


Response:

{
"message": "Portal invitation sent successfully",
"token": "portal-access-token-here"
}


Example:

curl -X POST \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"custom_message": "Welcome!"}' \
https://your-domain.com/api/v1/client-portal/companies/1/invite



Get Portal Token


Get or create a portal access token for a contact or company.


Endpoint: POST /api/v1/client-portal/token


Request Body:

{
"type": "contact",
"id": 1
}


Parameters:

  • type (required) - Either "contact" or "company"
  • id (required) - The ID of the contact or company


Response:

{
"token": "portal-access-token-here",
"url": "https://your-domain.com/client-portal/token-here",
"expires_at": "2026-02-19T00:00:00Z"
}


Example:

curl -X POST \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"type": "contact", "id": 1}' \
https://your-domain.com/api/v1/client-portal/token


Use Case:

Use this endpoint to generate portal access tokens programmatically. You can then:

  • Embed the portal URL in your own application
  • Create custom invitation flows
  • Build integrations that require portal access



Error Responses


All endpoints return standard error responses:


400 Bad Request:

{
"message": "Contact does not have an email address"
}


404 Not Found:

{
"message": "Contact not found"
}


500 Internal Server Error:

{
"message": "Failed to send portal invitation: Error details"
}



Rate Limiting


API requests are rate limited to 60 requests per minute per token. If you exceed this limit, you'll receive a 429 Too Many Requests response.



Webhooks


Portal-related webhook events:


  • client_portal.invitation_sent - Fired when a portal invitation is sent
  • client_portal.token_created - Fired when a new portal token is created
  • client_portal.token_accessed - Fired when a portal token is accessed


See Webhooks Documentation for more information.



Examples


Send Invitation and Get Token


// Send invitation
const response = await fetch('/api/v1/client-portal/contacts/1/invite', {
method: 'POST',
headers: {
'Authorization': 'Bearer your-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({
custom_message: 'Welcome to your portal!'
})
});

const data = await response.json();
console.log('Portal token:', data.token);
console.log('Portal URL:', `https://your-domain.com/client-portal/${data.token}`);


Get Portal Configuration


const response = await fetch('/api/v1/client-portal/config', {
headers: {
'Authorization': 'Bearer your-token'
}
});

const { data } = await response.json();
console.log('Portal name:', data.portal_name);
console.log('Enabled modules:', data.enabled_modules);



Best Practices


  1. Store Tokens Securely: If you store portal tokens, encrypt them
  2. Monitor Token Expiration: Check expires_at and send new invitations before expiration
  3. Handle Errors Gracefully: Always check response status and handle errors appropriately
  4. Respect Rate Limits: Implement retry logic with exponential backoff
  5. Use Custom Messages: Personalize invitation messages when possible



Next Steps



Updated on: 13/03/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!