Skip to main content
POST
/
api
/
signals
/
types
Create a keyword signal type
curl --request POST \
  --url https://app.puffle.ai/api/signals/types \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "label": "<string>",
  "description": "<string>",
  "prompt": "<string>",
  "keywords": [
    "<string>"
  ],
  "disqualifiers": "<string>"
}
'
{
  "type": {
    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "label": "<string>",
    "description": "<string>",
    "kind": "structured",
    "structured_type": "hiring",
    "structured_config": {},
    "keywords": [
      "<string>"
    ],
    "disqualifiers": "<string>",
    "scoring_prompt": "<string>",
    "search_prompt": "<string>",
    "color": "<string>",
    "enabled": true,
    "position": 4503599627370495,
    "built_in": true,
    "created_at": "2023-11-07T05:31:56Z",
    "updated_at": "2023-11-07T05:31:56Z"
  }
}

Overview

Creates a keyword-kind signal type for the caller. The handler:
  • auto-assigns a color from the unused palette
  • places the type at the next position
  • seeds one signal_type_sources row per registered datasource adapter (all disabled by default)
Max 20 signal types per user. The four structured types (Hiring, Funding, Leadership Change, Competitor Mentions) are only created via the auto-seed on first read of GET /api/signals/types; this endpoint always produces kind: "keyword".

AI agent notes

This is the internal UI-facing endpoint. Third-party integrations should prefer the v1 public API under /api/v1/signals/types.Enable sources after creation. New types ship with every signal_type_sources row disabled. Loop PUT /api/signals/types/{id}/sources/{sourceId} to turn on the adapters the type should query.Populate prompts. scoring_prompt / search_prompt are left empty on creation. Either call updateSignalType directly or POST /api/signals/types/{id}/generate to let AI fill them in from onboarding context.Label collisions return 409. Retry with a suffix ("Pain Point (2)") if a label is already taken.Quota is 20 types per user. The handler returns 400 Maximum of 20 signal types per user once the cap is hit — delete an unused type first.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json

Only keyword-kind types can be created through this endpoint. Structured types are the 4 built-ins seeded on first read of GET /api/signals/types.

label
string
required

Display name. Required. Unique per user — a collision returns 409.

Minimum string length: 1
description
string
prompt
string

Accepted but ignored by the current handler — scoring_prompt / search_prompt are set via updateSignalType after creation.

keywords
string[]

Initial keyword list. Defaults to [].

disqualifiers
string

Response

Signal type created.

type
object
required

A user-defined signal type. Max 20 per user.