This guide walks you through authenticating with the COR API and making your first requests to manage projects, tasks, and time entries.
Prerequisites : Before you begin, make sure you have your API credentials ready. See the Development guide to learn how to obtain your API Key and Client Secret from the COR dashboard.
Step 1: Get an access token
COR uses OAuth 2.0 for authentication. The Client Credentials flow is recommended for server-to-server integrations.
Encode your credentials
First, create a Base64 encoded string of your API Key and Client Secret:
echo -n "YOUR_API_KEY:YOUR_CLIENT_SECRET" | base64
This produces a string like: WU9VUl9BUElfS0VZOllPVVJfQ0xJRU5UX1NFQ1JFVA==
Request the token
Use your encoded credentials to obtain an access token:
curl --location --request POST 'https://api.projectcor.com/v1/oauth/token?grant_type=client_credentials' \
--header 'Authorization: Basic YOUR_BASE64_CREDENTIALS'
Success response:
{
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" ,
"token_type" : "Bearer" ,
"expires_in" : 3600 ,
"refresh_token" : "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4uLi4"
}
Save the access_token and refresh_token. You’ll use the access token for all API calls.
Store your tokens securely using environment variables. Never hardcode them in your source code. See secure token management for best practices.
Alternative authentication methods
Best for applications that act on behalf of users with their consent. Step 1: Redirect users to the consent screen:https://YOUR_SUBDOMAIN.cor.works/oauth2/authorize?name=YourAppName&response_type=code&redirect_uri=YOUR_CALLBACK_URL
Step 2: Exchange the authorization code for a token:curl --location --request POST 'https://api.projectcor.com/v1/oauth2/token?grant_type=authorization_code&code=AUTH_CODE'
For testing and development purposes only. This method is not recommended for production applications.
curl --location 'https://api.projectcor.com/v1/auth/login' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'email=your@email.com' \
--data-urlencode 'password=your_password'
Step 2: Verify your authentication
Test your access token by retrieving your user profile:
curl --location 'https://api.projectcor.com/v1/me' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Success response:
{
"id" : 12345 ,
"first_name" : "John" ,
"last_name" : "Doe" ,
"email" : "john.doe@company.com" ,
"picture" : "https://cdn.projectcor.com/avatars/12345.jpg" ,
"role_id" : 3 ,
"user_position_id" : 5 ,
"daily_hours" : 8 ,
"remaining_hours" : 6.5 ,
"cuil" : null ,
"labels" : []
}
Role IDs: 1 (C-Level), 2 (Director), 3 (Project Manager), 4 (Collaborator), 5 (Freelancer), 6 (Client).
If you see your user data, your authentication is working correctly.
Step 3: Explore core endpoints
Now that you’re authenticated, here are the most common operations you’ll perform with the COR API.
List your projects
All list endpoints in COR return paginated responses by default. Use page and perPage parameters to navigate results, and filters to narrow down the data.
# Basic request (returns page 1 with 20 items)
curl --location 'https://api.projectcor.com/v1/projects' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
# With pagination
curl --location 'https://api.projectcor.com/v1/projects?page=1&perPage=10' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
# With filters (URL-encoded JSON)
curl --location 'https://api.projectcor.com/v1/projects?page=1&filters=%7B%22client_id%22%3A25855%2C%22status%22%3A%22in_process%22%2C%22archived%22%3A2%7D' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Paginated response structure:
{
"total" : "14" ,
"perPage" : 20 ,
"page" : 1 ,
"lastPage" : 1 ,
"meta_data" : {
"profitability_limit" : "30.00"
},
"data" : [
{
"id" : 155693 ,
"name" : "Website Redesign" ,
"brief" : "Complete website overhaul for Q1" ,
"client_id" : 25855 ,
"health" : 1 ,
"status" : "active" ,
"start" : "2025-01-15 00:00:00" ,
"end" : "2025-03-31 00:00:00" ,
"estimated_time" : 200 ,
"elapsed_time" : 45 ,
"profitability_now" : 85 ,
"estimated_profitability" : 100 ,
"archived" : false ,
"billable" : true ,
"income_type" : "fee" ,
"pm_id" : 8546 ,
"created_at" : "2025-01-10 14:30:00" ,
"client" : {
"id" : 25855 ,
"name" : "Acme Corp" ,
"client_status_id" : 1
},
"pm" : {
"id" : 8546 ,
"first_name" : "John" ,
"last_name" : "Doe" ,
"email" : "john@company.com" ,
"role_id" : 3
}
}
]
}
Pagination parameters:
page: Page number (default: 1). Set to false to disable pagination and get all results.
perPage: Items per page (default: 20).
Field Type Description dateStartstring Start date range (YYYY-MM-DD) dateEndstring End date range (YYYY-MM-DD) client_idnumber Filter by client ID team_idnumber Filter by team ID user_idnumber Filter by user/PM ID brand_idnumber Filter by brand ID product_idnumber Filter by product ID statusstring "finished", "in_process", "suspended"healthnumber 1 (on track), 2 (at risk), 3 (delayed), 4 (critical) archivednumber 1 (archived only), 2 (active only)
List tasks for a project
Tasks are also paginated by default. Use the filters parameter with a JSON object to filter tasks by project:
curl --location 'https://api.projectcor.com/v1/tasks?page=1&filters=%7B%22project_id%22%3A5001%7D' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
The filters parameter accepts a URL-encoded JSON object. You can filter by multiple fields like project_id, status, user_id, and more.
Paginated response structure:
{
"total" : "25" ,
"perPage" : 20 ,
"page" : 1 ,
"lastPage" : 2 ,
"data" : [
{
"id" : 10001 ,
"title" : "Design homepage mockup" ,
"project_id" : 5001 ,
"description" : "Create wireframes and high-fidelity mockups for the new homepage" ,
"status" : "finalizada" ,
"priority" : 2 ,
"deadline" : "2024-01-15T18:00:00Z" ,
"archived" : false
},
{
"id" : 10002 ,
"title" : "Implement responsive navigation" ,
"project_id" : 5001 ,
"description" : "Build mobile-first navigation component with hamburger menu" ,
"status" : "en_proceso" ,
"priority" : 1 ,
"deadline" : "2024-01-22T18:00:00Z" ,
"archived" : false
}
]
}
Task status values: nueva (new), en_proceso (in progress), estancada (stalled), finalizada (completed).
Priority values: 0 (low), 1 (medium), 2 (high), 3 (urgent).
Log time to a task
Time entries use start and stop timestamps to track worked hours:
curl --location 'https://api.projectcor.com/v1/hours' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"task_log_id": 10002,
"start": "2024-01-18T09:00:00Z",
"stop": "2024-01-18T11:30:00Z"
}'
Success response:
{
"id" : 50001 ,
"task_log_id" : 10002 ,
"start" : "2024-01-18T09:00:00Z" ,
"stop" : "2024-01-18T11:30:00Z" ,
"status" : "pending"
}
The stop field is optional. If omitted, a timer will start for the task that you can stop later.
Get your clients
Clients are also paginated by default:
curl --location 'https://api.projectcor.com/v1/clients?page=1' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Paginated response structure:
{
"total" : "45" ,
"perPage" : 20 ,
"page" : 1 ,
"lastPage" : 3 ,
"data" : [
{
"id" : 2001 ,
"name" : "Acme Corp" ,
"business_name" : "Acme Corporation LLC" ,
"name_contact" : "Jane" ,
"last_name_contact" : "Smith" ,
"email_contact" : "jane.smith@acme.com" ,
"phone" : "+1 555-0100" ,
"website" : "https://acme.com" ,
"description" : "Enterprise software solutions" ,
"condition" : "active"
},
{
"id" : 2002 ,
"name" : "TechStart Inc" ,
"business_name" : "TechStart Incorporated" ,
"name_contact" : "Mike" ,
"last_name_contact" : "Johnson" ,
"email_contact" : "mike@techstart.io" ,
"phone" : "+1 555-0200" ,
"website" : "https://techstart.io" ,
"description" : "Startup accelerator" ,
"condition" : "active"
}
]
}
Step 4: Refresh your token
Access tokens expire after the time specified in expires_in (typically 1 hour). Use the refresh token to obtain a new access token:
curl --location 'https://api.projectcor.com/v1/oauth/refreshtoken' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'refresh_token=YOUR_REFRESH_TOKEN'
Success response:
{
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.newtoken..." ,
"token_type" : "Bearer" ,
"expires_in" : 3600 ,
"refresh_token" : "bmV3IHJlZnJlc2ggdG9rZW4uLi4"
}
For production applications, implement automatic token refresh to ensure uninterrupted API access. See the Development guide for a complete implementation example.
Handle errors
When something goes wrong, the API returns standard HTTP status codes:
Code Description Solution 400Bad Request Check required fields and JSON syntax 401Unauthorized Refresh or re-obtain access token 403Forbidden Request necessary permissions from admin 404Not Found Verify resource ID exists 429Too Many Requests Implement backoff and retry 500Server Error Retry with exponential backoff
401 Unauthorized - Token issues
Common causes:
Access token has expired
Token not included in Authorization header
Token format is incorrect (missing “Bearer ” prefix)
Solutions:
Verify header format: Authorization: Bearer YOUR_TOKEN
Refresh the token using /oauth/refreshtoken
Re-authenticate if refresh token is also expired
400 Bad Request - Invalid data
Common causes:
Missing required fields in request body
Invalid date format (use YYYY-MM-DD)
Malformed JSON
Solutions:
Check the API Reference for required parameters
Validate JSON syntax before sending
Ensure dates use ISO 8601 format
Common causes:
Temporary service disruption
High API traffic
Solutions:
Wait 5 minutes and retry
Implement exponential backoff in your integration
Check COR Status for known issues
Next steps
Congratulations! You’ve successfully authenticated and made your first API calls. Here’s where to go next:
Development Guide Set up your development environment with best practices for token management, error handling, and pagination.
API Reference Explore all available endpoints with detailed parameters and response schemas.
Projects API Create, update, and manage projects with budgets, timelines, and team assignments.
Tasks API Manage tasks, track progress, and handle assignments across your projects.
Time Tracking API Log hours, manage time entries, and generate reports for billing.
Resource Allocation Plan team capacity, allocate users to projects, and manage workload distribution.
Integrations API Connect external systems like Salesforce, Jira, and SAP with bidirectional sync.