Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.projectcor.com/llms.txt

Use this file to discover all available pages before exploring further.

Use Cursor to help build integrations with the COR API. This guide shows how to configure Cursor with project rules optimized for COR API development.

Prerequisites

  • Cursor editor installed
  • COR API credentials (API Key and Client Secret)

Project rules

Create project rules that provide Cursor with context about COR APIs. In your project root:
mkdir -p .cursor
Create .cursor/rules.md:
# COR API Development Rules

You are an AI assistant specialized in building integrations with the COR platform APIs.

## Platform Overview

COR is a project management platform for agencies and professional services. The platform provides three APIs:

| API | Base URL | Purpose |
|-----|----------|---------|
| Main API | `https://api.projectcor.com/v1` | Core platform operations |
| Resource Allocation | `https://planner.svc.v2.projectcor.com` | User capacity management |
| Integrations API | `https://integrations.projectcor.com` | External system synchronization |

## Authentication

All APIs use OAuth 2.0 with Bearer tokens. The same token works across all three APIs.

### Getting a Token (Client Credentials)

```bash
# 1. Encode credentials
echo -n "API_KEY:CLIENT_SECRET" | base64

# 2. Request token
curl -X POST 'https://api.projectcor.com/v1/oauth/token?grant_type=client_credentials' \
  -H 'Authorization: Basic BASE64_CREDENTIALS'
```

### Using the Token

```
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
```

### Token Refresh

Tokens expire (check `expires_in`). Refresh before expiration:

```bash
curl -X POST 'https://api.projectcor.com/v1/oauth/refreshtoken' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'refresh_token=REFRESH_TOKEN'
```

## Main API Entities

### Core Entities

| Entity | Endpoints | Description |
|--------|-----------|-------------|
| Clients | `/clients` | Customer accounts |
| Projects | `/projects` | Project management |
| Tasks | `/tasks` | Task tracking |
| Hours | `/hours` | Time entries |
| Users | `/users` | Team members |
| Brands | `/brands` | Client brands |
| Products | `/products` | Brand products |

### Entity Relationships

```
Company
  └── Clients
        └── Brands
              └── Products
        └── Projects
              └── Tasks
                    └── Hours (time entries)
              └── Project Costs
              └── Project Estimates
  └── Users (with roles and positions)
```

### User Roles

| role_id | Role |
|---------|------|
| 1 | C-Level |
| 2 | Director |
| 3 | Project Manager |
| 4 | Collaborator |
| 5 | Freelancer |
| 6 | Client |

### Task Status Values

| Status | Description |
|--------|-------------|
| `nueva` | New |
| `en_proceso` | In progress |
| `estancada` | Stalled |
| `finalizada` | Completed |

### Project Status Values

| Status | Description |
|--------|-------------|
| `in_process` | Active |
| `finished` | Completed |
| `suspended` | On hold |

## Data Conventions

### Pagination

List endpoints return paginated responses by default:

```json
{
  "total": "45",
  "perPage": 20,
  "page": 1,
  "lastPage": 3,
  "data": [...]
}
```

Parameters:
- `page`: Page number (default: 1). Set to `false` to get all results
- `perPage`: Items per page (default: 20)

### Filters

Use URL-encoded JSON for filtering:

```bash
# Filter projects by client and status
filters={"client_id":25855,"status":"in_process","archived":2}

# URL encode it
curl '.../projects?filters=%7B%22client_id%22%3A25855%7D'
```

### Date Formats

- Request dates: `YYYY-MM-DD` (e.g., `2025-01-15`)
- Response dates: `YYYY-MM-DD HH:mm:ss` or ISO 8601

## Resource Allocation API

Manages user capacity on projects.

### Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/allocation/saveAllocation` | Create allocation |
| PUT | `/allocation/updateAllocation` | Update allocation |
| DELETE | `/allocation/removeAllocation` | Delete allocation |
| GET | `/allocation/getAllocations/{projectId}` | Get project allocations |

### Allocation Object

```json
{
  "userId": 1111,
  "companyId": 1111,
  "email": "user@example.com",
  "resource": {
    "typeId": "Project",
    "entityId": 1111
  },
  "from": "2024-06-01",
  "to": "2024-10-31",
  "assignedByUserId": 11111,
  "allocatedHours": 20
}
```

### Validation Rules

- `allocatedHours` cannot be empty
- `from` date must be before `to` date
- Date range cannot exceed 12 months
- No overlapping allocations for same user/project

### Allocation Errors

| Error | Description |
|-------|-------------|
| `InvalidAllocationError` | Invalid data (empty hours, bad dates, >12 months) |
| `AllocationAlreadyExistInDatesRangeError` | Overlapping allocation exists |
| `UserNotFoundError` | User doesn't exist |
| `UserNotHaveWorkDaysError` | User has no work days configured |
| `ProjectNotFoundError` | Project doesn't exist |
| `AllocationNotFoundError` | Allocation to update/delete not found |

## Integrations API

Synchronizes external systems with COR using external ID mapping.

### Required Field

All requests MUST include `metadata.source`:

```json
{
  "metadata": {
    "source": "SALESFORCE"
  },
  "id": "external-id-123",
  "name": "Entity Name"
}
```

### Supported Sources

`JIRA`, `SALESFORCE`, `ADVERTMIND`, `QUICKBOOKS`, `ZAPIER`, `OKTA`, `MICROSOFT_DYNAMICS`, `GITHUB`, `MICROSOFT_TEAMS`, `VBS`, `SAP`, `GLOBANT`

### Integration Entities

| Entity | Operations |
|--------|------------|
| Projects | CREATE, UPDATE, DELETE |
| Clients | CREATE, UPDATE, DELETE |
| Users | CREATE, UPDATE, DELETE, Assign Position |
| Working Time | CREATE, DELETE |
| Contracts | CREATE, UPDATE, DELETE, Attach/Detach Users |
| Workspaces | CREATE, UPDATE |
| Brands | CREATE, UPDATE, DELETE |

### External ID Flow

1. You provide external ID (from your system)
2. COR creates entity and stores mapping
3. Future operations reference external ID

```bash
# Create with external ID
POST /v2/integrations/projects
{"metadata":{"source":"SALESFORCE"},"id":"SF-OPP-123","name":"Project"}

# Update using external ID
PUT /v2/integrations/projects/SF-OPP-123
{"metadata":{"source":"SALESFORCE"},"name":"Updated Project"}
```

### Integration Error Codes

| Code | Description |
|------|-------------|
| `ZC001` | Generic Error |
| `ZC002` | Validation Error |
| `ZC003` | API Request Exception |
| `ZC004` | Query Exception |
| `ZC005` | External Request Exception |

## HTTP Status Codes

| Code | Description |
|------|-------------|
| `200` | Success |
| `201` | Created |
| `204` | Success (No Content) |
| `400` | Bad Request - check required fields |
| `401` | Unauthorized - refresh token |
| `403` | Forbidden - insufficient permissions |
| `404` | Not Found - verify resource exists |
| `422` | Unprocessable Entity - validation error |
| `429` | Too Many Requests - implement backoff |
| `500` | Server Error - retry with backoff |

## Best Practices

### Token Management

- Store tokens securely (environment variables)
- Implement automatic token refresh before expiration
- Never hardcode credentials in source code

### Error Handling

- Always check response status codes
- Parse error responses for specific error types
- Implement exponential backoff for retries

### Rate Limiting

- Implement delays between bulk operations
- Use pagination instead of fetching all at once
- Cache responses when appropriate

### Data Integrity

- Validate required fields before sending requests
- Use transactions for related operations when possible
- Log all API interactions for debugging

## Code Examples

### List Projects with Filters

```python
import requests
import json

headers = {'Authorization': f'Bearer {token}'}
filters = json.dumps({'status': 'in_process', 'archived': 2})

response = requests.get(
    'https://api.projectcor.com/v1/projects',
    params={'page': 1, 'perPage': 50, 'filters': filters},
    headers=headers
)

data = response.json()
for project in data['data']:
    print(f"{project['id']}: {project['name']}")
```

### Create Integration Project

```python
response = requests.post(
    'https://integrations.projectcor.com/v2/integrations/projects',
    headers={**headers, 'Content-Type': 'application/json'},
    json={
        'metadata': {'source': 'SALESFORCE'},
        'id': 'SF-OPP-12345',
        'name': 'New Project',
        'client_id': 'SF-ACC-67890',
        'start': '2025-01-15',
        'end': '2025-03-31'
    }
)
```

### Create Resource Allocation

```python
response = requests.post(
    'https://planner.svc.v2.projectcor.com/allocation/saveAllocation',
    headers={**headers, 'Content-Type': 'application/json'},
    json={
        'userId': 1111,
        'companyId': 1111,
        'resource': {'typeId': 'Project', 'entityId': 5001},
        'from': '2025-01-01',
        'to': '2025-03-31',
        'assignedByUserId': 1111,
        'allocatedHours': 40
    }
)
```