# Platform setup

Source: https://ceyo.ai/docs/signal/platform-setup-guides

### Platform setup

Set up the resource structure and packages that customer data will use before adding prompts, competitors, or customer access.

### Understand the resource hierarchy

The API key selects one workspace. Packages, projects, and locations created with that key stay inside that workspace.

```
Workspace
├── Package (project)
│   └── Standard project
└── Locations-only project
    ├── Location → Package (location)
    └── Location → Package (location)
```

**Workspace**

The tenant boundary. It comes from the API key and never appears in public API paths.

**Package**

Defines visibility limits, models, cadence, enabled features, and customer access for one resource type.

**Project**

Represents a tracked brand or acts as the container for a location portfolio.

**Location**

Represents one local entity under a project and uses its own location package.

> **Stable partner identifiers**
>
> Set `external_id` from your own system when creating projects and locations. You can use it in supported lookup and path parameters instead of storing only Signal UUIDs.

### Choose project or location scope

Choose the scope from the data you need to track. This decision also determines where packages, prompts, competitors, and visibility data live.

**Standard project**

Use for one brand or website with project-level visibility. The project requires a project package and website.

**Locations-only project**

Use as a portfolio container when each location is tracked and packaged independently. The container has no project package.

**Location scope**

Use for one store, office, service area, or other local entity. Location API paths are always nested under their project.

> **Immutable choice**
>
> `project_mode` and package assignment cannot be changed after creation. Create a new resource if the hierarchy needs to change.

### Configure packages

Create packages before provisioning resources. A project package can be assigned only to standard projects. A location package can be assigned only to locations.

**Visibility**

Select a cadence, prompt limit, and at least one supported model.

**Features**

Enable diagnosis, agents, analytics, prompt volume, or fan-out only where the customer needs them.

**Customer access**

Set `pricing.frontend_delivery_enabled` for hosted Signal access and redirect login links.

**Listings**

Location packages include listings automatically. Do not send the derived `listings.enabled` field.

```json
{
  "package_type": "project",
  "configuration": {
    "visibility": {
      "cadence": "weekly",
      "prompt_limit": 100,
      "model_keys": ["chatgpt", "claude"]
    },
    "diagnosis": {
      "enabled": true
    },
    "pricing": {
      "frontend_delivery_enabled": true
    }
  }
}
```

> **Validate before creating**
>
> Send the package type and configuration to `POST /packages/preview`. After validation, create the package with `POST /packages`. To change a package configuration later, clone it and assign the new package to newly created resources.

### Provision a project

Use a workspace-scoped key with `projects:write`. Send a stable external ID so future synchronization does not depend on the project name.

#### Standard project

Supply `package_id` and `website`. Set `start: true` to begin automatic onboarding immediately after the project is created.

```curl
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/projects' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Acme Europe",
    "external_id": "customer-acme-eu",
    "project_mode": "standard",
    "package_id": "92404fd7-f096-49e9-9ab0-5ed73517d9db",
    "website": "https://acme.example",
    "country_code": "NL",
    "language": "en",
    "start": true
  }'
```

#### Locations-only project

Omit `package_id`. The locations created under this project select their own location packages.

```curl
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/projects' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Acme Locations",
    "external_id": "customer-acme-locations",
    "project_mode": "locations_only",
    "start": false
  }'
```

> **Start behavior**
>
> With `start: false`, automatic onboarding is skipped. The resource remains available for manual configuration through the supported settings, prompt, and competitor APIs.

### Provision a location portfolio

Create the locations-only project first, then create each location beneath its returned project ID or external ID.

**1\. Select a package**

Use an active `location` package from the same workspace.

**2\. Preserve your identity**

Set a unique location `external_id`, such as a store or account identifier.

**3\. Send local data**

Send a `google_place_id` when you have one. Otherwise, send your own local data; `city` and `country_code` are enough to use `start: true`.

**4\. Choose onboarding**

Set `start` independently for each location and poll the returned `onboarding_operation.status_url`.

```curl
curl --request POST \
  --url 'https://api.signal.ceyo.ai/v1/projects/{project_id}/locations' \
  --header "Authorization: Bearer ${SIGNAL_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Acme Amsterdam",
    "external_id": "store-nl-ams-01",
    "package_id": "66aeb6f8-a353-4acf-a914-e288ca0e4341",
    "website": "https://acme.example/amsterdam",
    "city": "Amsterdam",
    "country_code": "NL",
    "language": "nl",
    "start": true
  }'
```

Without a place ID, onboarding looks for a clear Google match. It keeps your supplied fields, and continues without listing analysis if no match is found. Repeat the request for each location, then use `GET /projects/{project_id}/locations` or the locations overview endpoint to reconcile the completed portfolio.
