Skip to main content
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
    }
)
```