Skip to main content

Overview

Macondo Link Manager uses a two-tier organizational hierarchy to help you manage links effectively. Clients represent your customers or major projects, while campaigns provide sub-organization for specific marketing initiatives.

Clients

Top-level organization for customers

Campaigns

Marketing initiatives under clients

Global Access

Shared across all agency users

Cascade Delete

Clean removal of nested data

Organizational Hierarchy

The system follows this structure:
Agency
  ├── Client A
  │   ├── Campaign 1
  │   │   ├── Link 1
  │   │   └── Link 2
  │   └── Campaign 2
  │       └── Link 3
  └── Client B
      ├── Campaign 3
      └── Links (without campaign)
Clients are global entities shared across all users in the agency. They do not have individual ownership - any authenticated user can view and manage all clients.

Client Management

Creating Clients

Create a new client to represent a customer or project.

API Endpoint

POST /clients
Content-Type: application/json

{
  "name": "Acme Corporation"
}

Request

name
string
required
The client name. Must be unique across all clients and at least 3 characters long.

Response

Returns 201 Created with the client object:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corporation",
  "createdAt": "2024-03-09T10:30:00Z",
  "updatedAt": "2024-03-09T10:30:00Z"
}
Client names must be globally unique. If you attempt to create a client with a name that already exists, you’ll receive a 409 Conflict error.

Listing Clients

Retrieve all clients in the agency with aggregate statistics.

API Endpoint

GET /clients

Response

Returns 200 OK with an array of clients including counts:
[
  {
    "id": "client-uuid-1",
    "name": "Acme Corporation",
    "campaignsCount": 5,
    "linksCount": 142,
    "createdAt": "2024-01-15T08:00:00Z"
  },
  {
    "id": "client-uuid-2",
    "name": "Tech Startup Inc",
    "campaignsCount": 2,
    "linksCount": 37,
    "createdAt": "2024-02-20T14:30:00Z"
  }
]

Included Metrics

campaignsCount
number
Total number of campaigns under this client
Total number of links associated with this client (including links in campaigns)

Viewing Client Details

Get information about a specific client.

API Endpoint

GET /clients/:id

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corporation",
  "createdAt": "2024-03-09T10:30:00Z",
  "updatedAt": "2024-03-09T10:30:00Z"
}

Updating Clients

Modify an existing client’s information.

API Endpoint

PUT /clients/:id
Content-Type: application/json

{
  "name": "Acme Corporation (Updated)"
}

Request

name
string
required
The new client name. Must still be unique and at least 3 characters.

Response

Returns 200 OK with the updated client object.
The new name must not conflict with existing client names, or you’ll receive a 409 Conflict error.

Deleting Clients

Permanently remove a client and all associated data.

API Endpoint

DELETE /clients/:id

Response

Returns 204 No Content on successful deletion.
Deleting a client is irreversible and will cascade delete:
  • All campaigns under the client
  • All links associated with the client (including those in campaigns)
  • All click analytics data for those links
This operation cannot be undone.

Cascade Deletion Example

Client "Acme Corporation"
  ├── Campaign "Spring Sale" (DELETED)
  │   ├── Link "acme-spring-1" (DELETED)
  │   │   └── 234 clicks (DELETED)
  │   └── Link "acme-spring-2" (DELETED)
  │       └── 156 clicks (DELETED)
  └── Link "acme-general" (DELETED)
      └── 89 clicks (DELETED)

Campaign Management

Creating Campaigns

Create a campaign under a specific client.

API Endpoint

POST /campaigns
Content-Type: application/json

{
  "name": "Spring Sale 2024",
  "clientId": "client-uuid"
}

Request

name
string
required
The campaign name. Must be at least 3 characters and unique within the client.
clientId
string (uuid)
required
The UUID of the client this campaign belongs to. Client must exist.

Response

Returns 201 Created with the campaign object:
{
  "id": "campaign-uuid",
  "name": "Spring Sale 2024",
  "clientId": "client-uuid",
  "createdAt": "2024-03-09T10:30:00Z",
  "updatedAt": "2024-03-09T10:30:00Z"
}
Campaign names only need to be unique within each client. Different clients can have campaigns with the same name.

Campaign Name Uniqueness

Client A
  ├── Campaign "Summer 2024" ✓
  └── Campaign "Summer 2024" ✗ Conflict

Client B
  └── Campaign "Summer 2024" ✓ OK - different client

Listing Campaigns

Retrieve campaigns with optional client filtering.

API Endpoint

GET /campaigns?clientId={uuid}

Query Parameters

clientId
uuid
Filter campaigns by specific client. If omitted, returns all campaigns.

Response

[
  {
    "id": "campaign-uuid-1",
    "name": "Spring Sale 2024",
    "clientId": "client-uuid",
    "clientName": "Acme Corporation",
    "linksCount": 23,
    "createdAt": "2024-03-01T08:00:00Z",
    "updatedAt": "2024-03-09T14:30:00Z"
  },
  {
    "id": "campaign-uuid-2",
    "name": "Product Launch",
    "clientId": "client-uuid",
    "clientName": "Acme Corporation",
    "linksCount": 15,
    "createdAt": "2024-02-15T10:00:00Z",
    "updatedAt": "2024-03-05T16:45:00Z"
  }
]

Included Metrics

clientName
string
Name of the client this campaign belongs to
Total number of links associated with this campaign

Viewing Campaign Details

Get information about a specific campaign.

API Endpoint

GET /campaigns/:id

Response

{
  "id": "campaign-uuid",
  "name": "Spring Sale 2024",
  "clientId": "client-uuid",
  "createdAt": "2024-03-09T10:30:00Z",
  "updatedAt": "2024-03-09T10:30:00Z"
}

Updating Campaigns

Modify an existing campaign’s name.

API Endpoint

PUT /campaigns/:id
Content-Type: application/json

{
  "name": "Spring Sale 2024 - Extended"
}

Request

name
string
required
The new campaign name. Must be at least 3 characters and unique within the client.
You cannot change which client a campaign belongs to. If you need to move a campaign, you must create a new one under the desired client.

Response

Returns 200 OK with the updated campaign object.

Deleting Campaigns

Permanently remove a campaign.

API Endpoint

DELETE /campaigns/:id

Response

Returns 204 No Content on successful deletion.

Campaign Deletion Behavior

When a campaign is deleted:
  • The campaign itself is removed
  • Links associated with the campaign are NOT deleted
  • Instead, their campaignId is set to null
  • Links remain associated with the client
  • Click analytics data is preserved

Example

Before deletion:
{
  "id": "link-uuid",
  "shortCode": "abc123",
  "clientId": "client-uuid",
  "campaignId": "campaign-uuid"
}
After campaign deletion:
{
  "id": "link-uuid",
  "shortCode": "abc123",
  "clientId": "client-uuid",
  "campaignId": null  // Campaign reference removed
}

Hierarchical Organization Benefits

Structured Analytics

The client-campaign hierarchy enables analytics at multiple levels:

Agency Level

View metrics across all clients

Client Level

See performance for specific clients

Campaign Level

Analyze individual campaign results

Flexible Filtering

Filter links by:
  • All links across the agency
  • Links for a specific client
  • Links for a specific campaign
  • Links with no campaign (client-level only)

Team Collaboration

Since clients and campaigns are global:
  • All team members see the same structure
  • No permission complexities
  • Consistent naming and organization
  • Easy handoffs between team members

Use Cases

Agency Structure

Macondo Agency
  ├── Client: Fashion Brand Co
  │   ├── Campaign: Summer Collection 2024
  │   ├── Campaign: Instagram Ads - March
  │   └── Campaign: Email Newsletter
  ├── Client: Tech Startup Inc
  │   ├── Campaign: Product Launch
  │   └── Campaign: Investor Outreach
  └── Client: Restaurant Chain
      ├── Campaign: New Menu Promotion
      └── Campaign: Loyalty Program

Campaign Types

Common campaign organization patterns:
  • Social Media
  • Email Marketing
  • Paid Ads
  • Influencer Partnerships

Error Handling

Common Errors

Status CodeErrorDescription
404Client not foundThe specified client doesn’t exist
404Campaign not foundThe specified campaign doesn’t exist
409Client already existsA client with this name already exists
409Campaign already existsA campaign with this name exists for this client
400Invalid nameName is too short (< 3 characters)
401UnauthorizedAuthentication required

Example Error Responses

Client name conflict:
{
  "message": "Já existe um cliente com esse nome."
}
Campaign name conflict:
{
  "message": "Já existe uma campanha com esse nome para este cliente."
}
Client not found:
{
  "message": "Cliente não encontrado."
}

Best Practices

Consistent Naming

Use clear, descriptive names for clients and campaigns

Logical Grouping

Group campaigns by channel, time, or product based on your needs

Archive Strategy

Consider a naming convention for archived campaigns (e.g., “[ARCHIVED] Campaign Name”)

Regular Cleanup

Periodically review and delete old campaigns to keep the list manageable
Before deleting a client, consider exporting analytics data if you need to preserve historical records.

Build docs developers (and LLMs) love