goals
Goals API Documentation
Overview
The Goals API allows you to create, manage, and track sales and purchase goals for campaigns. Goals can be assigned to users and groups, and progress is tracked automatically based on opportunities.
Base URL
/api/sales/goals
Authentication
All endpoints require JWT authentication via the Authorization header.
Endpoints
1. List Goals
Endpoint: POST /api/sales/goals
Gets all goals with optional filters and pagination.
Request Body:
{
"action": "get_all_goals",
"campaigns": ["uuid-campaign-1", "uuid-campaign-2"],
"owner": ["uuid-owner"],
"user_assigned": [12, 15],
"group_assigned": [3],
"progress_min": 0,
"progress_max": 100,
"page": "MTIz",
"page_size": 10
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "get_all_goals" |
campaigns | array | No | Filter by campaign UUIDs |
owner | array | No | Filter by owner UUIDs |
user_assigned | array | No | Filter by assigned user IDs (integers) |
group_assigned | array | No | Filter by assigned group IDs (integers) |
progress_min | integer | No | Minimum progress (0-100) |
progress_max | integer | No | Maximum progress (0-100) |
page | string | No | Pagination cursor |
page_size | integer | No | Results per page (default: 10) |
Notes:
user_assignedandgroup_assignedcannot be used simultaneouslyprogress_minandprogress_maxmust be between 0 and 100
Response:
{
"code": 0,
"data": [
{
"uuid": "goal-uuid",
"description": "Objetivo Zona Sur",
"campaign": {
"uuid": "uuid-campaign-1",
"name": "Campaña 2025"
},
"created_by": {
"first_name": "Juan",
"last_name": "Perez"
},
"assigned_to": [
{
"type": "user",
"uuid": "uuid-user-1",
"name": "Carlos Gomez"
}
],
"goal_type": "sale",
"goal_subtype": "volume",
"amount": 10000,
"unit": "kg",
"progress": 65
}
],
"next_page": "NfSA"
}
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 3 | Validation error (invalid filters) |
| 10 | Invalid filters |
2. Create Goal
Endpoint: POST /api/sales/goals/goal
Creates a new goal with optional user and group assignments.
Request Body:
{
"action": "create",
"description": "Objetivo Venta Fertilizante",
"campaign_uuid": "uuid-campaign",
"goal_type": "sale",
"goal_subtype": "volume",
"input_uuid": "uuid-input",
"amount": 5000,
"id_unit": 1,
"users": [12, 15],
"groups": [3]
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "create" |
description | string | Yes | Goal description |
campaign_uuid | string (UUID) | Yes | Campaign UUID |
goal_type | string | Yes | "sale" or "purchase" |
goal_subtype | string | Yes | "volume" or "billing" |
amount | number | Yes | Target amount (must be > 0) |
input_uuid | string (UUID) | Conditional | Required for sale goals |
crop_id | integer | Conditional | Required for purchase goals |
variety_id | integer | No | Crop variety ID |
id_unit | integer | Yes | Unit ID from unidades table (volume) or monedas table (billing) |
users | array | No | User IDs (integers) to assign |
groups | array | No | Group IDs (integers) to assign |
Validation Rules:
amountmust be greater than 0id_unitis required for both volume and billing subtypesgoal_type = sale→input_uuidrequiredgoal_type = purchase→crop_idrequired- For volume goals:
id_unitreferences unidades table - For billing goals:
id_unitreferences monedas table
Response:
{
"code": 0,
"message": "goal created successfully",
"data": {
"uuid": "goal-uuid",
"description": "Objetivo Venta Fertilizante",
"campaign": {
"name": "Campaña 2025"
},
"goal_type": "sale",
"goal_subtype": "volume",
"amount": 5000,
"id_unit": 1,
"unit": "kg",
"assigned_to": [
{"type": "user", "id": 12},
{"type": "group", "id": 3}
],
"created_at": "2025-01-20T15:30:00Z"
}
}
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 2 | Invalid action |
| 30 | Validation error |
| 31 | Campaign not found |
| 32 | Invalid goal type |
3. Update Goal
Endpoint: POST /api/sales/goals/goal
Updates an existing goal. Only the owner can update.
Request Body:
{
"action": "update",
"uuid": "goal-uuid",
"description": "Objetivo actualizado",
"amount": 6000,
"users": [12],
"groups": []
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "update" |
uuid | string (UUID) | Yes | Goal UUID |
description | string | No | New description |
amount | number | No | New target amount (must be > 0) |
users | array | No | New user IDs (integers) - replaces existing |
groups | array | No | New group IDs (integers) - replaces existing |
Notes:
- Only the goal owner can update
- Providing
usersorgroupsreplaces all existing assignments
Response:
{
"code": 0,
"message": "goal updated successfully",
"data": {
"uuid": "goal-uuid",
"description": "Objetivo actualizado",
"amount": 6000,
"assigned_to": [
{"type": "user", "id": 12}
],
"modified_at": "2025-01-20T16:45:00Z"
}
}
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 2 | Invalid action |
| 20 | Goal not found |
| 21 | Insufficient permissions (not owner) |
| 30 | Validation error |
4. Delete Goal
Endpoint: POST /api/sales/goals/goal
Soft deletes a goal. Only the owner can delete.
Request Body:
{
"action": "delete",
"uuid": "goal-uuid"
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "delete" |
uuid | string (UUID) | Yes | Goal UUID |
Response:
{
"code": 0,
"message": "goal deleted successfully"
}
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 2 | Invalid action |
| 20 | Goal not found |
| 21 | Insufficient permissions (not owner) |
5. Assign Goal
Endpoint: POST /api/sales/goals/assign
Assigns users and/or groups to a goal. Only the owner can assign.
Request Body:
{
"goal_uuid": "goal-uuid",
"users": [12, 15],
"groups": [3]
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
goal_uuid | string (UUID) | Yes | Goal UUID |
users | array | No | User IDs (integers) to assign |
groups | array | No | Group IDs (integers) to assign |
Notes:
- At least one of
usersorgroupsmust be provided - Both can be provided simultaneously
- Only the goal owner can assign
Response:
{
"code": 0,
"message": "goal assigned successfully"
}
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 3 | Validation error (no users or groups provided) |
| 20 | Goal not found |
| 21 | Insufficient permissions (not owner) |
6. Unassign Users
Endpoint: POST /api/sales/goals/unassign
Unassigns users from a goal. Only the owner can unassign.
Request Body:
{
"action": "unassign_users",
"goal_uuid": "goal-uuid",
"users": [12]
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "unassign_users" |
goal_uuid | string (UUID) | Yes | Goal UUID |
users | array | Yes | User IDs (integers) to unassign |
Response:
{
"code": 0,
"message": "goal unassigned successfully"
}
7. Unassign Groups
Endpoint: POST /api/sales/goals/unassign
Unassigns groups from a goal. Only the owner can unassign.
Request Body:
{
"action": "unassign_groups",
"goal_uuid": "goal-uuid",
"groups": [3]
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "unassign_groups" |
goal_uuid | string (UUID) | Yes | Goal UUID |
groups | array | Yes | Group IDs (integers) to unassign |
Response:
{
"code": 0,
"message": "goal unassigned successfully"
}
Error Codes (Unassign):
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 3 | Validation error |
| 20 | Goal not found |
| 21 | Insufficient permissions (not owner) |
8. Get Goal Progress
Endpoint: POST /api/sales/goals/progress
Gets detailed progress information for a goal.
Request Body:
{
"goal_uuid": "goal-uuid",
"user_id": 12,
"group_id": 3
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
goal_uuid | string (UUID) | Yes | Goal UUID |
user_id | integer | No | Filter progress by user |
group_id | integer | No | Filter progress by group |
Notes:
user_idandgroup_idcannot be sent together- If neither is provided, returns consolidated progress
Response:
{
"code": 0,
"data": {
"uuid": "goal-uuid",
"description": "Objetivo Zona Sur",
"campaign": {
"uuid": "uuid-campaign-1",
"name": "Campaña 2025"
},
"goal_type": "sale",
"goal_subtype": "volume",
"target": 10000,
"unit": "kg",
"assigned_to": [
{
"type": "user",
"uuid": "uuid-user-1",
"name": "Carlos Gomez"
}
],
"progress_detail": {
"current": 6500,
"progress": 65.00,
"operations": [
{"uuid": "opp-uuid-1", "name": "Opportunity 1", "quantity": 5000},
{"uuid": "opp-uuid-2", "name": "Opportunity 2", "quantity": 1500}
],
"other_units_opportunities": [
{"uuid": "opp-uuid-3", "name": "Opportunity 3", "quantity": 100, "unit_id": 5}
]
}
}
}
Progress Calculation:
- For volume goals: Opportunities with matching units are summed directly. Different units are converted using the units API. If conversion fails (different unit types), they're added to
other_units_opportunities - For billing goals: Only opportunities with matching currency (unit_id) are counted. Different currencies are added to
other_units_opportunities operations: Array of opportunities that contributed to the progressother_units_opportunities: Array of opportunities with incompatible units/currencies that couldn't be included in progress
Error Codes:
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 3 | Validation error (user_id and group_id sent together) |
| 20 | Goal not found |
| 21 | Insufficient permissions |
Data Models
Goal Object
{
"uuid": "string (UUID)",
"description": "string",
"campaign": {
"uuid": "string (UUID)",
"name": "string"
},
"created_by": {
"first_name": "string",
"last_name": "string"
},
"assigned_to": [
{
"type": "user|group",
"id": "integer",
"name": "string"
}
],
"goal_type": "sale|purchase",
"goal_subtype": "volume|billing",
"amount": "number",
"id_unit": "integer (ID from unidades or monedas table)",
"unit": "string (unit name from unidades.unit or monedas.moneda)",
"progress": "integer (0-100)",
"created_at": "timestamp",
"modified_at": "timestamp"
}
Common Error Codes
| Code | Description |
|---|---|
| 1 | Missing JSON body |
| 2 | Invalid action |
| 3 | Validation error |
| 10 | Invalid filters |
| 20 | Goal not found |
| 21 | Insufficient permissions |
| 30 | Validation error (business logic) |
| 31 | Campaign not found |
| 32 | Invalid goal type |
| 33 | Invalid assignment |
Examples
Example 1: Create a Sale Volume Goal
curl -X POST https://api.example.com/api/sales/goals/goal \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "create",
"description": "Venta de Fertilizante Q1",
"campaign_uuid": "550e8400-e29b-41d4-a716-446655440000",
"goal_type": "sale",
"goal_subtype": "volume",
"input_uuid": "550e8400-e29b-41d4-a716-446655440042",
"amount": 10000,
"id_unit": 1,
"users": [12, 15]
}'
Example 2: List Goals for a Campaign
curl -X POST https://api.example.com/api/sales/goals \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "get_all_goals",
"campaigns": ["550e8400-e29b-41d4-a716-446655440000"],
"page_size": 20
}'
Example 3: Update Goal Amount
curl -X POST https://api.example.com/api/sales/goals/goal \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "update",
"uuid": "goal-uuid-here",
"amount": 15000
}'