Skip to main content
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).
FieldTypeDescription
dateStartstringStart date range (YYYY-MM-DD)
dateEndstringEnd date range (YYYY-MM-DD)
client_idnumberFilter by client ID
team_idnumberFilter by team ID
user_idnumberFilter by user/PM ID
brand_idnumberFilter by brand ID
product_idnumberFilter by product ID
statusstring"finished", "in_process", "suspended"
healthnumber1 (on track), 2 (at risk), 3 (delayed), 4 (critical)
archivednumber1 (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:
CodeDescriptionSolution
400Bad RequestCheck required fields and JSON syntax
401UnauthorizedRefresh or re-obtain access token
403ForbiddenRequest necessary permissions from admin
404Not FoundVerify resource ID exists
429Too Many RequestsImplement backoff and retry
500Server ErrorRetry with exponential backoff
Common causes:
  • Access token has expired
  • Token not included in Authorization header
  • Token format is incorrect (missing “Bearer ” prefix)
Solutions:
  1. Verify header format: Authorization: Bearer YOUR_TOKEN
  2. Refresh the token using /oauth/refreshtoken
  3. Re-authenticate if refresh token is also expired
Common causes:
  • Missing required fields in request body
  • Invalid date format (use YYYY-MM-DD)
  • Malformed JSON
Solutions:
  1. Check the API Reference for required parameters
  2. Validate JSON syntax before sending
  3. Ensure dates use ISO 8601 format
Common causes:
  • Temporary service disruption
  • High API traffic
Solutions:
  1. Wait 5 minutes and retry
  2. Implement exponential backoff in your integration
  3. 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:
Need help? Contact our support team at help@projectcor.com or visit COR Support.