Create a catalog entry
POST/v1/catalog/entities
Creates a catalog entry, as New in the Catalog: a destino (a country, city or zone), a place (punto), accommodation (alojamiento, which needs a Google placeId), an activity (actividad) or a service (servicio). Put it in the tree with content.partOf (the parent's id). An entry of the same kind for the same Google place, or with the same externalId, is a 409 naming the existing one (existingId) — update that one instead. Images are added after, with the entry's image upload. Undo with POST /changes/{changeId}/revert (a soft delete, while nobody has edited it).
content fields by kind — use exactly these names; an unknown field is refused. text fields accept plain text (one paragraph per line). partOf is the parent entry's id: a punto hangs from a destino; nothing hangs from a punto.
Every kind also takes: category: string, features: string[], altNames: string[], estado: borrador|migrado|revisado|publicado|obsoleto, verifiedAt: string (pattern)|null, source: string, reviewNotes: string.
- destino: partOf: uuid|null, intro: text, gettingAround: text, food: text, whenToGo: text, zoneNote: string
- punto: partOf: uuid|null, description: text, tips: text, warnings: text, durationMin: number, hours: {state: unknown|always|scheduled, rules: string, display: string, note: string}, closedWeekdays: mon|tue|wed|thu|fri|sat|sun[], momentsOfDay: amanecer|manana|mediodia|tarde|atardecer|noche[], bestSeasons: primavera|sakura|verano|otono|koyo|invierno|iluminaciones|todo_el_ano[], intensity: baja|media|alta, indoor: boolean, accessibility: unknown|accessible|limited|not, profiles: primera_vez|repetidor|familia_ninos|pareja|grupo|senior|movilidad_reducida|cultural|gastronomico|naturaleza|fotografia|otaku|compras|presupuesto_ajustado|premium[], priority: 1|2|3, paidEntry: boolean, priceNote: string, bookingUrl: string, arrival: text, mapUrl: string, googleFeatureId: string
- alojamiento: partOf: uuid|null, description: text, tips: text, warnings: text, includes: text, accessibility: unknown|accessible|limited|not, checkInWindow: {from: string (pattern), to: string (pattern)}, checkOutTime: string (pattern), mealTimes: {breakfast: string (pattern), dinner: string (pattern), note: string}
- actividad: partOf: uuid|null, description: text, tips: text, warnings: text, durationMin: number|null, hours: {state: unknown|always|scheduled, rules: string, display: string, note: string}, closedWeekdays: mon|tue|wed|thu|fri|sat|sun[], momentsOfDay: amanecer|manana|mediodia|tarde|atardecer|noche[], bestSeasons: primavera|sakura|verano|otono|koyo|invierno|iluminaciones|todo_el_ano[], intensity: baja|media|alta, indoor: boolean, accessibility: unknown|accessible|limited|not, profiles: primera_vez|repetidor|familia_ninos|pareja|grupo|senior|movilidad_reducida|cultural|gastronomico|naturaleza|fotografia|otaku|compras|presupuesto_ajustado|premium[], includes: text, meetingPoint: string, requiresReservation: boolean, fixedTime: boolean, providers: {key: string, name: string, place: object, partOf: uuid|null, notes: string}[], beforeYouGo: text
- servicio: partOf: uuid|null, description: text, tips: text, warnings: text, includes: text, provider: string
Permissions: catalog:write · Kind: write · Cost: 1 unit · MCP tool create_catalog_entity
Undoable: the response carries Bymundi-Change-Id; revert it with POST /v1/changes/{changeId}/revert.
Path parameters
None.
Body
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"destino" | "punto" | "alojamiento" | "actividad" | "servicio" | yes | |
name |
string | yes | max 200 chars |
placeId |
string | The Google place id. Required for alojamiento. max 300 chars |
|
cityKey |
string | A normalized city key; derived from the name when absent. max 200 chars | |
place |
object | Where it is. The Google place id goes in placeId, not here. |
|
place.lat |
number | null | ||
place.lng |
number | null | ||
place.formattedAddress |
string | max 500 chars | |
content |
object | The kind's own fields — see the list in the description. | |
tags |
string[] | Lowercased and de-duplicated; at most 12. max 12 items | |
externalId |
string | Your system's id for this entry (e.g. a supplier's product code). Unique among the agency's live entries; "" clears it. max 200 chars |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
object |
"catalog_entity" | yes | |
id |
uuid | yes | |
kind |
"destino" | "punto" | "alojamiento" | "actividad" | "servicio" | yes | |
name |
string | yes | |
placeId |
string | yes | |
cityKey |
string | yes | |
externalId |
string | yes | |
place |
object | yes | |
images |
object[] | yes | |
tags |
string[] | yes | |
origin |
"human" | "ai" | "api" | "import" | yes | |
content |
object | yes | |
updatedAt |
string | yes | |
deletedAt |
string | null | yes |
Errors
Errors are problem details. Besides the refusals described above, any call like this one can return:
invalid_request— Invalid requestunauthorized— Missing or invalid API keyinsufficient_scope— Missing permissionrate_limited— Rate limit reachedidempotency_key_reused— Idempotency-Key reusedrequest_in_progress— Request in progress