Skip to content

Artist Endpoint Map

Related documentation: Artist Source of Truth Registry (canonical per-endpoint SoT + callers) · Artist Module Backend · Artist Product Vision · Frontend Artist · Artist Module Backend API

This page explains:

  • what each endpoint family is for
  • where frontend should use it
  • what user flow it belongs to
  • which part of the system owns that flow

Use this page as the product/use-flow reference.

Use Artist Module Backend API for the exact runtime route inventory.

Use Artist Source of Truth Registry when you need which database owns each route, who calls it, and Promoters vs Artists vs Mongo boundaries.

Each section below is organized as:

  • Endpoint
  • What It Is For
  • Frontend Use
  • Typical Flow

This is the document frontend teams should use when deciding:

  • where a route belongs in the UI
  • what screen should call it
  • what the expected user flow is

Authenticated (/api/v1, Bearer + x-org) read-only proxy so the Artists app can browse venues. Backed by the canonical Venues service admin feed — Backend-Kisum-Artists never owns or writes venue master data.

What It Is For:

  • venue directory list. Upstream: Venues GET /internal/admin/venues.
  • query params: search, iso2 (country), city, page, limit.
  • returns all non-deleted venues (active, inactive, claimed, unclaimed/sleeping): the proxy always sends sleeping=all upstream (the admin feed otherwise defaults to non-sleeping only); active is left unfiltered.

Frontend Use:

  • /venues directory page (src/services/venues/api.ts listVenues).

What It Is For:

  • one venue (full admin profile: location, capacity, genres, media, opening hours, rent, contacts, team). Upstream: Venues GET /internal/admin/venues/:id.
  • :id accepts the Venues Postgres UUID or numeric venue_id.

Frontend Use:

  • /venues/[id] detail page (getVenue).

Auth to Venues: X-Service-Token (audience venues) when S2S is enabled, else X-Internal-API-Key (VENUE_INTERNAL_API_KEY); base VENUE_INTERNAL_BASE_URL. No marketplace/booking/spaces/availability here.

Promoters (read-only directory proxy) — 2026-07-15

Section titled “Promoters (read-only directory proxy) — 2026-07-15”

Authenticated (/api/v1, Bearer + x-org) read-only proxy so the Artists app can browse Kisum promoter tenants (not the Artists industry directory) — who they are, who works there, and what they have actually delivered. Backed by Backend-Kisum-Promoters’ aggregated internal feed — Backend-Kisum-Artists never owns or writes promoter, company, or user data. This is the platform’s first cross-tenant data disclosure; see Data ownership.

What It Is For:

  • promoter tenant directory list. Upstream: Promoters GET /internal/directory/promoters.
  • query params: q, country (iso2), page, limit, sort, order.

Frontend Use:

  • /promoters directory page (src/services/promoters/api.ts listPromoters).

What It Is For:

  • one promoter tenant: identity (name/logo/country), staff (name, company role, department, work email — never phone), decision maker, department heads, shows-delivered + cancelled counts. Upstream: Promoters GET /internal/directory/promoters/:coreCompanyId. No show list inline.
  • :id is the Core company UUID.

Frontend Use:

  • /promoters/[id] detail page (getPromoter).

What It Is For:

  • paginated past shows for that promoter (date, artist, venue, country). Upstream: Promoters GET /internal/directory/promoters/:coreCompanyId/shows.
  • query params: page, limit, country, artistId, from, to.

Frontend Use:

  • /promoters/[id] Past shows table (listPromoterShows).

Auth to Promoters: X-Service-Token (audience promoters) when S2S is enabled, else X-Internal-API-Key (PROMOTER_INTERNAL_API_KEY, singular — matches Artists’ own VENUE_INTERNAL_* naming); base PROMOTER_INTERNAL_BASE_URL. Ops gotcha: the value must equal Promoters’ own INTERNAL_API_KEY — one secret, three names across callers (Artists: PROMOTER_INTERNAL_API_KEY; Admin: PROMOTERS_INTERNAL_API_KEY, plural; Venues: PROMOTER_INTERNAL_API_KEY, singular). No write routes here — read-only, matching the Venues directory pattern above.

Routes that let a fresh Auth/Core company bridge to an artists-company (the “agency”). Two flows: takeover (claim an existing unclaimed company) or creation (propose a brand-new one for admin approval). Backed by a new artists_provisioning_requests table (migration 20260525_market_provisioning_requests.sql) with strict business rules enforced via unique partial indexes:

  • one pending request per Auth org globally
  • one pending takeover per (target company, requester) pair
  • existing artists_company_claims_approved_uniq keeps enforcing “one approved org per company”

On approve (single tx): the service writes a real artists_company_claims row (status=‘approved’) + flips companies.claimed=TRUE + closes the request. Creation also inserts the new companies row from the stored spec first. The existing claim-based ownership checks (IsCompanyOwnedByOrg, etc.) continue to work unchanged — no claim-consuming code needs to change.

No file upload anywhere (different from Backend-Kisum-Venues’ equivalent). Tenant submits only optional notes. Reviewer identity is stamped from JWT locals server-side; the FE never sends decisionBy* fields.

What It Is For:

  • search the central directory of unclaimed artists-companies that a tenant could claim
  • search-required: returns [] when q.length < 2 (privacy + abuse vector — same comment as the Venues equivalent)
  • joins hasPendingRequest + pendingRequestId per caller (scoped to the requesting Auth org only — no cross-org leak)

Query params: q, country, page, limit (default 25, max 200).

Frontend Use:

  • SleepingCompanyBrowser on /settings/agency empty state

POST /api/v1/artists-companies/takeover-requests

Section titled “POST /api/v1/artists-companies/takeover-requests”

What It Is For:

  • submit a claim on an existing unclaimed agency
  • body: { companyId, notes? }companyId accepts either the bigint id or the uuid

Pre-checks before insert (friendly 409 messages):

  • caller has no other pending provisioning request (any kind)
  • caller has no other pending takeover on this specific target

Frontend Use:

  • TakeoverRequestDialog after a user picks a row from the sleeping browser

POST /api/v1/artists-companies/creation-requests

Section titled “POST /api/v1/artists-companies/creation-requests”

What It Is For:

  • propose a brand-new agency for admin approval
  • body: { spec: { name, country, slug?, city?, roleType?, websiteUrl?, description?, contactEmail?, contactPhone? }, notes? }
  • name + country required; spec is stored verbatim in JSONB until approve

Pre-checks: same single-pending-per-org guard as takeover.

Frontend Use:

  • CreationRequestDialog on /settings/agency empty state

What It Is For:

  • the caller’s own provisioning history (unified list with kind discriminator, newest first)
  • shows admin decisionNotes when present so the tenant sees rejection reasons

Query params: status (optional filter).

Frontend Use:

  • MyAgencyRequestsList on /settings/agency empty state

What It Is For:

  • “what artists-company is my Auth org bridged to?” — returns the single approved claim’s company
  • 404 = not bridged (canonical FE soft-gate signal; the tenant FE keys its banner + page two-mode render off this)

Frontend Use:

  • useActiveAgency() hook in Frontend-Kisum-Artists — drives both the layout’s amber no-agency banner and the /settings/agency page’s two-mode render
  • GET /internal/companies/:companyId/delete-preview — counts rows across Artists core-UUID columns + bridged directory companies; blockers for shared booking graph rows
  • POST /internal/companies/:companyId/purge — body { mode, force, tombstoneCompanyId }; repoints shared booking side to tombstone when force=true, then deletes company-scoped rows. Auth: internal key only.

Platform: Spotify id resolve (machine, 2026-08-03)

Section titled “Platform: Spotify id resolve (machine, 2026-08-03)”
  • POST /internal/artists/resolve-spotify-ids — body { "spotify_ids": ["…"] }{ "matches": { "<spotifyId>": "<kisumArtistId>" } } (numeric artists.id) from artist_platform_accounts + platforms.code='spotify'. Auth: X-Internal-API-Key (ARTISTS_INTERNAL_API_KEY). Does not change public GET /api/v1/artists?q=.
  • Consumer: Backend-Kisum-Admin Spotify search enrichment (kisumArtistId on GET /admin/artists/spotify). Admin does not query Artists Postgres directly.

Admin: GET|POST /internal/admin/artist-company-requests/*

Section titled “Admin: GET|POST /internal/admin/artist-company-requests/*”

Admin-only review queue (X-Internal-API-Key). 4 routes:

  • GET /internal/admin/artist-company-requests?status=&kind=&requestedCompanyId=&page=&limit= — paginated queue
  • GET /internal/admin/artist-company-requests/:requestId — single request detail
  • POST /internal/admin/artist-company-requests/:requestId/approve — body { decisionByUserId, decisionByEmail, decisionByName, decisionNotes? }. Runs the takeover or creation side-effect (single tx). Idempotent on already-approved.
  • POST /internal/admin/artist-company-requests/:requestId/reject — same body shape. Only valid from pending.

Frontend Use:

  • proxied through Backend-Kisum-Admin → /api/v1/admin/artist-company-requests/* and consumed by Frontend-Kisum-Admin → System → Artist Company Requests

What It Is For:

  • list artists for search, tables, and selector UIs

Query:

  • q — text search (when set, uses ranked WITH search / matches SQL: trigram % + LIKE, then exact → prefix → whole word → contains → similarity; client sort is ignored while q is present)
  • sort / order — only apply when q is empty (default sort: rank asc)

Frontend Use:

  • artist directory page
  • artist picker modals
  • shortlist add flow

Typical Flow:

  1. user opens artist list
  2. frontend loads artists
  3. user filters/searches
  4. user opens one artist detail

What It Is For:

  • create a new artist record

Frontend Use:

  • artist creation form
  • admin/operator data entry flow

Typical Flow:

  1. user clicks create artist
  2. frontend submits form
  3. user lands on artist detail

What It Is For:

  • load artist summary/detail record

Frontend Use:

  • artist detail header
  • summary card
  • page bootstrap

Typical Flow:

  1. user opens artist detail
  2. frontend loads main artist record
  3. page tabs then load subresources

What It Is For:

  • update core artist fields

Frontend Use:

  • edit artist form

Typical Flow:

  1. user edits artist
  2. frontend submits patch
  3. refresh summary/header

What It Is For:

  • remove artist record where allowed

Frontend Use:

  • destructive admin action only

Typical Flow:

  1. user confirms delete
  2. frontend calls delete
  3. list view refreshes

What It Is For:

  • read or update extended artist profile fields

Frontend Use:

  • profile tab
  • edit profile screen

Typical Flow:

  1. open profile tab
  2. load profile
  3. edit and save profile

What It Is For:

  • read or update artist genres

Frontend Use:

  • taxonomy editor
  • search tagging UI

What It Is For:

  • read or update artist subgenres

Frontend Use:

  • taxonomy editor
  • recommendation/search refinement

GET|PUT /api/v1/artists/{id}/platform-accounts

Section titled “GET|PUT /api/v1/artists/{id}/platform-accounts”

What It Is For:

  • manage artist platform handles and account links

Frontend Use:

  • profile integrations tab

GET|PUT /api/v1/artists/{id}/provider-refs

Section titled “GET|PUT /api/v1/artists/{id}/provider-refs”

What It Is For:

  • manage provider/source references

Frontend Use:

  • internal source-linking tools

What It Is For:

  • read or update artist-side team assignments

Response notes (GET):

  • Each row includes person fields plus company fields: companyId, companyName, companyLogoUrl, companyRoleType, companySlug.
  • When artist_team_assignments.person_id is set, Artists resolves company from the person’s active company_people employment (prefers companies.role_type matching assignment_type, then is_primary). company_id on assignments was removed (migration 000031); staff is the only representation link.

Frontend Use:

  • contacts/team tab

What It Is For:

  • read derived company relationships for an artist (staff assignments + needs-agent holding rows)

PUT returns 400 — update via artists/{id}/team, assignments, or company needs-agent promote endpoints.

Frontend Use:

  • roster tab
  • agency artist assignment flow

Staff-linked roster (2026-07-09, migration 000031)

Section titled “Staff-linked roster (2026-07-09, migration 000031)”

Breaking: company_rosters table removed. Representation truth is artist_team_assignments (person_id required). Company roster is derived from agents currently employed at the company (company_people). Imported artists without an agent live in company_needs_agent_artists until promoted.

New routes:

  • POST|GET|PATCH|DELETE /api/v1/assignments — granular assignment CRUD
  • GET|POST /api/v1/companies/{id}/needs-agent — list / add needs-agent rows
  • DELETE /api/v1/companies/{id}/needs-agent/{needsAgentId} — remove holding row
  • POST /api/v1/companies/{id}/needs-agent/{needsAgentId}/promote — assign staff + territories, remove holding row
  • PUT /api/v1/people/{id}/roster — bulk replace person assignments
  • POST|GET /api/v1/people/{id}/roster-claims — staff roster claim submit + list (pending + history). PATCH|DELETE /api/v1/people/{id}/roster-claims/{claimId} — tenant may update or cancel a pending claim (org-scoped; person must be employed by requester org). Do not use POST /assignments from the browser for this flow — claims require Admin approval. territories is structured JSONB (migration 000036); legacy free-text lives in territories_legacy (TEXT[]).
  • GET|POST /internal/admin/staff-roster-claims/* — Admin review queue (machine key). Approve creates artist_team_assignments from claim fields (personId, artistId, role, assignmentType, territories JSONB). Reject updates status only. Tables: artist_staff_roster_claims, artist_team_assignments (migration 000035 + 000036). Proxied via Backend-Kisum-Admin → /api/v1/admin/staff-roster-claims/*.

Structured territories JSONB (2026-07-11): artist_staff_roster_claims.territories and artist_team_assignments.territories store:

{
"region": [{ "id": 3, "excluded": null }, { "id": 4, "excluded": [18, 162] }],
"subregion": [{ "id": 6, "excluded": [153] }],
"countries": [156, 155]
}
  • Worldwide = region id: 0 (pinned first in roster-claim picker). With Worldwide, add exclusion rows for regions, subregions, or countries — stored on the Worldwide pick as excludedRegions, excludedSubregions, and excluded (country ids).
  • Pre-migration free-text (WW, Worldwide, etc.) remains in territories_legacy only; best-effort migration maps WW/Worldwide{"region":[{"id":0,"excluded":null}],…}.
  • Middle-agent marketplace listings keep separate territories_json string-array format — unchanged.

PUT /api/v1/companies/{id}/roster returns 400 (read-only derived view).

Roster read fields (2026-07-10): GET /api/v1/people/{id}/roster and GET /api/v1/companies/{id}/roster include artist_id plus artist_slug (from artists.slug) for promoter UI links. Assignment row id is not an artist directory id — frontends must prefer artist_slug (then artist_id) for /artists/:segment URLs.

Admin BFF forwards the same under /api/v1/admin/market-directory/*.

What It Is For:

  • list market companies / agencies / counterparties

Frontend Use:

  • company directory
  • agency picker
  • claim flow lookup

What It Is For:

  • create company/agency directory records

Frontend Use:

  • create agency/company flow

What It Is For:

  • load company detail

Frontend Use:

  • agency/company detail page

What It Is For:

  • update company detail fields

Frontend Use:

  • edit agency/company form

What It Is For:

  • delete company record where allowed

Frontend Use:

  • admin destructive action

What It Is For:

  • read or maintain company contacts

Frontend Use:

  • contacts tab

What It Is For:

  • read or maintain company locations

Frontend Use:

  • office/territory section

What It Is For:

  • read or maintain company genre alignment

Frontend Use:

  • company profile taxonomy

What It Is For:

  • read derived staff-linked roster for a company (PUT is rejected — read-only)

Frontend Use:

  • agency roster screen

Response notes:

  • one row per artist (deduped): if several staff at the company represent the same artist, the API keeps the primary assignment (then newest)
  • each row includes artist_id, artist_slug, artist_name, artist_image_url, assignment fields (id = assignment PK) plus optional person_* for the chosen agent
  • pagination total uses COUNT(DISTINCT artist_id)

What It Is For:

  • list artists linked to a staff person via artist_team_assignments

Frontend Use:

  • Promoters staff detail roster (/booking/agencies/:agencyId/staff/:staffId)

Response notes:

  • each row includes artist_id, artist_slug, artist_name, artist_image_url; UI links must use artist_slug (fallback artist_id), never assignment id

GET|PUT /api/v1/companies/{id}/social-metrics

Section titled “GET|PUT /api/v1/companies/{id}/social-metrics”

What It Is For:

  • read or maintain company social/market metrics

Frontend Use:

  • company profile analytics block

What It Is For:

  • list people / contacts

Frontend Use:

  • contacts list
  • person picker

What It Is For:

  • create a person/contact

Frontend Use:

  • add contact flow

What It Is For:

  • load one person/contact

Frontend Use:

  • contact detail drawer/page

What It Is For:

  • update contact record

Writable fields include: fullName, primaryRole, title, email, phone, phonePrefix (+XX from countries.phone_prefix), countryId, cityId, locationText (display cache; FE usually sets from city+country names), linkedinUrl, avatarUrl, notes.

Title sync (2026-07-10): when title is patched, Artists also updates the matching company_people.title row so affiliations and Promoters agency staff cards stay aligned. Scope: caller’s managed agency company (x-orgartists_company_claims); else primary affiliation; else all active affiliations.

Reads also embed country / city objects when FKs are set (migration 000034_people_location_phone).

Frontend Use:

  • edit contact flow (/people/[id]/edit) — country + city selects from /api/v1/countries and /api/v1/countries/{id}/cities; dial code select from countries phonePrefix.

What It Is For:

  • delete contact record where allowed

Frontend Use:

  • admin destructive action

What It Is For:

  • load the companies linked to a person (company_people — includes per-company title + role)

Frontend Use:

  • contact affiliations section (subtitle = title · role). Person Title edits via PATCH /api/v1/people/{id} sync into the scoped affiliation row (see PATCH above).

GET|PUT /api/v1/people/{id}/platform-accounts

Section titled “GET|PUT /api/v1/people/{id}/platform-accounts”

What It Is For:

  • read or maintain platform accounts linked to a person

Frontend Use:

  • contact external accounts/integrations

GET|POST|PATCH|DELETE /api/v1/genres, /subgenres, /regions, /countries, /states, /cities, /platforms, /provider-sources

Section titled “GET|POST|PATCH|DELETE /api/v1/genres, /subgenres, /regions, /countries, /states, /cities, /platforms, /provider-sources”

What It Is For:

  • maintain shared lookup/reference data

Frontend Use:

  • dropdowns
  • search/filtering
  • data management screens

Typical Flow:

  1. load page
  2. fetch lookup data
  3. populate selectors

What It Is For:

  • submit a claim that an org owns or operates a company record

Frontend Use:

  • “claim this company” action on company detail

Typical Flow:

  1. user opens company
  2. clicks claim
  3. submits claim
  4. UI shows pending review

What It Is For:

  • list claim records on a company

Frontend Use:

  • claim-history panel
  • admin review list

POST /api/v1/market-companies/{id}/claims/{claimId}/approve

Section titled “POST /api/v1/market-companies/{id}/claims/{claimId}/approve”

What It Is For:

  • approve a company claim

Frontend Use:

  • reviewer/admin approval action

POST /api/v1/market-companies/{id}/claims/{claimId}/reject

Section titled “POST /api/v1/market-companies/{id}/claims/{claimId}/reject”

What It Is For:

  • reject a company claim

Frontend Use:

  • reviewer/admin rejection action

GET /api/v1/market-companies/{id}/ownership

Section titled “GET /api/v1/market-companies/{id}/ownership”

What It Is For:

  • load the current ownership/claim state

Frontend Use:

  • company header badge
  • claim status panel

POST /api/v1/artists/{id}/representation-claims

Section titled “POST /api/v1/artists/{id}/representation-claims”

What It Is For:

  • submit a claim that a company represents the artist

Frontend Use:

  • add representation flow

Typical Flow:

  1. open artist representation tab
  2. submit claim
  3. pending review / approval state

POST /api/v1/artists/{id}/representation-claims/{claimId}/approve

Section titled “POST /api/v1/artists/{id}/representation-claims/{claimId}/approve”

What It Is For:

  • approve a representation claim

Frontend Use:

  • reviewer action

POST /api/v1/artists/{id}/representation-claims/{claimId}/reject

Section titled “POST /api/v1/artists/{id}/representation-claims/{claimId}/reject”

What It Is For:

  • reject a representation claim

Frontend Use:

  • reviewer action

What It Is For:

  • load the artist’s current representation state

Frontend Use:

  • artist representation summary tab

POST /api/v1/artists/{id}/representation/disputes

Section titled “POST /api/v1/artists/{id}/representation/disputes”

What It Is For:

  • open a dispute against a representation record

Frontend Use:

  • dispute flow on representation tab

What It Is For:

  • list artist availability entries

Frontend Use:

  • availabilities tab
  • artist calendar

What It Is For:

  • create an availability entry

Request body (camelCase JSON):

  • startsAt, endsAt — RFC3339 timestamps
  • availabilityTypeopen | blackout | soft_hold | routing_hold (default open)
  • statusactive | cancelled (default active)
  • territoryText, notes — optional strings
  • representationClaimId — optional; when omitted the insert still binds a nullable $2 placeholder (do not skip the arg index)

Frontend Use:

  • create availability flow (Frontend-Kisum-Artists maps UI available/hold/blocked → backend types and sends startsAt/endsAt)

PATCH /api/v1/artists/{id}/availabilities/{availabilityId}

Section titled “PATCH /api/v1/artists/{id}/availabilities/{availabilityId}”

What It Is For:

  • update an availability entry

Frontend Use:

  • edit availability flow

DELETE /api/v1/artists/{id}/availabilities/{availabilityId}

Section titled “DELETE /api/v1/artists/{id}/availabilities/{availabilityId}”

What It Is For:

  • remove an availability entry

Frontend Use:

  • delete availability action

GET /api/v1/marketplace/artist-availabilities

Section titled “GET /api/v1/marketplace/artist-availabilities”

What It Is For:

  • Unified marketplace browse — merges agency-published availabilities (artist_availabilities, official: true) and published middle-agent listings (middle_agent_availability_listings, official: false) in one paginated response.

Query params (non-exhaustive):

  • artistId — numeric Postgres artists.id (filters both sources)
  • from / to — date overlap window
  • officialtrue | false to return only one source (omit for both)
  • sort / order — middle-agent rows honor listing sort; merged list sorts by start/available date (default desc)
  • sellerCompanyId — middle-agent seller filter (company uuid or numeric id)
  • agencyId — selling agency (company uuid or numeric id). Official rows only; the agency is resolved with the same ownership rule the listing card shows
  • country — ISO-3166-1 alpha-2 or alpha-3 code, a country name, or a numeric country id. countryId (numeric only) still works for older callers; both may be sent together
  • city — numeric city id or a partial, case-insensitive city name
  • genre — numeric genre id, genre slug, or a partial, case-insensitive genre name
  • feeMin / feeMax — asking-fee range. Middle-agent listings only: matches fee_terms_json (artistFee, or a min/max band) with range-overlap semantics, and listings with no numeric fee are excluded while a bound is active. artist_availabilities has no fee column, so official rows are not fee-filtered

All filters are optional and an absent or blank value is always a no-op — it never narrows the result set. Unparsable feeMin/feeMax values are ignored rather than matching nothing.

Each row includes official: boolean.

Official rows (official: true) are flat agency availability records with at least artistName, artistUuid, artistImageUrl, startsAt, endsAt, and territoryText (camelCase in JSON). Promoters exclusive cards consume these fields directly — not a nested artist.name legacy shape.

Frontend Use:

  • marketplace search (one call for All tab)
  • promoter discovery flow
  • event booking tab marketplace panel (Promoters BFF splits client-side by official)

Typical Flow:

  1. promoter opens marketplace
  2. filters by date/location
  3. sees matching artists (exclusive + secondary when official omitted)
  4. opens profile or starts booking flow

Deprecated browse alias: GET /api/v1/marketplace/middle-agent-availability-listings remains for detail/enquiry routes; list browse should prefer the unified endpoint (Promoters legacy BFF GET .../middle-agent/availability-listings proxies unified with official=false).

GET /api/v1/agency/availability/summary (2026-07-14)

Section titled “GET /api/v1/agency/availability/summary (2026-07-14)”

What It Is For:

  • agency-wide, volume-independent day-by-day availability rollup for the caller’s own agency (scoped to x-org; fails closed without it)
  • query params: from/to (YYYY-MM-DD, default today..+41d, span clamped to ≤62 days), q, kind (available|hold|blocked), artistId, countryId, cityId
  • only status='active' windows; type→kind buckets: openavailable, soft_hold/routing_holdhold, blackoutblocked
  • response: { range:{from,to}, totals:{windows,artists,available,hold,blocked}, days:[{date,total,available,hold,blocked,artists}], capped }; a multi-day window is counted on each UTC day it overlaps, to is treated as an inclusive day (SQL upper bound is exclusive next-midnight)
  • capped (final-review fix, 2026-07-14) — true when the window fetch behind the summary hit AgencyAvailabilityWindowCap (20,000 windows); totals/days may undercount for very wide or dense ranges when this is set, so narrow from/to or add filters for an exact count
  • artistId (final-review fix, 2026-07-14) — was parsed but silently ignored by both agency endpoints (picking an artist did nothing); now applied to the SQL WHERE on both

Frontend Use:

  • Frontend-Kisum-Artists /availability Month heatmap (density-first per-day counts); shows a muted “narrow with filters” note when capped is true

GET /api/v1/agency/availability (2026-07-14)

Section titled “GET /api/v1/agency/availability (2026-07-14)”

What It Is For:

  • same agency scope and filters as the summary endpoint, plus page/limit/sort/order
  • standard paginated envelope of the agency’s active availability windows; each row carries artistName
  • artistId (final-review fix, 2026-07-14) — now actually filters the SQL, same fix as the summary endpoint
  • timestamps (final-review fix, 2026-07-14) — startsAt/endsAt always serialize with an explicit UTC Z suffix, so frontend day-bucketing (startAt.slice(0,10)) is correct regardless of the backend process’s local timezone

Frontend Use:

  • day drill-down panel (called with from=to=<day>, inclusive)
  • Agenda list view

What It Is For:

  • list booking requests

Frontend Use:

  • requests inbox/list

What It Is For:

  • create a booking request

Frontend Use:

  • new inquiry / request form (artist profile Request booking, shortlist row, marketplace)

Auth:

  • Bearer + x-org. Body promoterCompanyId may be the canonical Core org UUID (same as x-org) — no artists_company_claims row required. created_by_core_company_id is the buyer scope; optional promoter_company_id FK is filled from an approved claim when present.

Typical Flow:

  1. user chooses artist
  2. fills request (dates, territory, optional budget)
  3. submits request
  4. request appears in pipeline

Optional body fields (2026-06-26):

  • budgetAmount — numeric gross fee / all-in budget the promoter is willing to pay
  • budgetCurrency — ISO currency code (default USD)
  • On middle_agent_broadcast routing, budget is copied to each fan-out offer as buyerPriceAmount / buyerPriceCurrency

Optional body fields (2026-06-30):

  • promoterEventId — canonical Promoter publicEventId UUID when linking a request to an event; not required for standalone requests (offers still require event linkage via offersheet)

What It Is For:

  • load request detail

Frontend Use:

  • request detail screen

PATCH /api/v1/booking-requests/{requestId}

Section titled “PATCH /api/v1/booking-requests/{requestId}”

What It Is For:

  • update request detail

Frontend Use:

  • edit draft/pending request

POST /api/v1/booking-requests/{requestId}/withdraw

Section titled “POST /api/v1/booking-requests/{requestId}/withdraw”

What It Is For:

  • cancel a pending request (sets status cancelled; closes linked middle-agent broadcast offers)

Frontend Use:

  • request cancel/withdraw action in Promoters booking detail

DELETE /api/v1/booking-requests/{requestId}

Section titled “DELETE /api/v1/booking-requests/{requestId}”

What It Is For:

  • hard-delete a cancelled booking request (promoter owner only; status must be cancelled, canceled, or legacy withdrawn)

Frontend Use:

  • permanent remove after withdraw on Promoters /booking/requests/[id]

POST /api/v1/booking-requests/{requestId}/convert-to-offer

Section titled “POST /api/v1/booking-requests/{requestId}/convert-to-offer”

What It Is For:

  • promote a request into an offer

Frontend Use:

  • request-to-offer action in pipeline

What It Is For:

  • list offers

Frontend Use:

  • offer pipeline

What It Is For:

  • create an offer directly

Frontend Use:

  • direct offer creation

What It Is For:

  • load offer detail

Frontend Use:

  • offer detail screen

POST /api/v1/booking-offers/{offerId}/counter

Section titled “POST /api/v1/booking-offers/{offerId}/counter”

What It Is For:

  • counter an offer

Frontend Use:

  • negotiation flow

POST /api/v1/booking-offers/{offerId}/accept

Section titled “POST /api/v1/booking-offers/{offerId}/accept”

What It Is For:

  • accept an offer
  • Accept gating (2026-07-17, Phase C): if the offer is EXCLUSIVE and its offersheet carries mutualTerms, accept requires a complete, value-bound acceptance already on file — every proposed term key AND its exact current value (cancellation-ladder bands keyed ladder:<band>, bound to that band’s current charge). Missing/stale/incomplete acceptance → 422 MUTUAL_TERMS_NOT_ACCEPTED (message starts “Mutual terms”). Offers without mutualTerms skip the gate. On the actual accepted flip (not a re-accept), the availability’s contract_terms_json best-effort snapshots into the accepted version’s offersheet.artistContractTerms.

Frontend Use:

  • deal acceptance action; on 422 MUTUAL_TERMS_NOT_ACCEPTED the FE opens MutualTermsDialog automatically

POST /api/v1/booking-offers/{offerId}/mutual-terms/accept (2026-07-17, Phase C)

Section titled “POST /api/v1/booking-offers/{offerId}/mutual-terms/accept (2026-07-17, Phase C)”

What It Is For:

  • term-by-term acceptance of the offersheet’s mutualTerms — body { terms: [{ key, value, accepted: true }] }; same agency-side auth as accept
  • term keys: reschedulePeriod, rescheduleCosts, ladder:<band>, and billing:<showIndex> (2026-07-17: billing moved per-show — one accept row per show — replacing the earlier single mutualTerms.billing key)
  • persists a snapshot into booking_offers.mutual_terms_acceptance_json: { acceptedByUserId, acceptedByOrgId, acceptedAt, terms }
  • any counter or buyer revision NULLs the existing acceptance — re-acceptance is required after every new offer version
  • offer detail exposes the result as top-level mutualTermsAcceptance (alongside the proposed mutualTerms)

Frontend Use:

  • MutualTermsDialog (per-term explicit accept; “Accept terms” disabled until every term is checked; “Propose different terms” routes to counter instead of accepting); offer detail “Contract terms” card (read-only, accepted/pending badges, “Review & accept” entry point)

POST /api/v1/booking-offers/{offerId}/decline

Section titled “POST /api/v1/booking-offers/{offerId}/decline”

What It Is For:

  • decline an offer

Frontend Use:

  • decline action

POST /api/v1/booking-offers/{offerId}/cancel

Section titled “POST /api/v1/booking-offers/{offerId}/cancel”

What It Is For:

  • cancel an offer

Frontend Use:

  • offer cancellation

GET /api/v1/booking-offers/{offerId}/holds

Section titled “GET /api/v1/booking-offers/{offerId}/holds”

What It Is For:

  • list hold records on an offer

Frontend Use:

  • holds section on offer detail

POST /api/v1/booking-offers/{offerId}/holds

Section titled “POST /api/v1/booking-offers/{offerId}/holds”

What It Is For:

  • create a hold

Frontend Use:

  • add hold action

PATCH /api/v1/booking-offers/{offerId}/holds/{holdId}

Section titled “PATCH /api/v1/booking-offers/{offerId}/holds/{holdId}”

What It Is For:

  • update or release a hold

Frontend Use:

  • hold state edit

What It Is For:

  • list confirmed/current bookings

Frontend Use:

  • bookings index

What It Is For:

  • load booking detail — the confirmed deal
  • carries a deal block (detail only, never on the list): the FULL commercial terms of the offer behind the booking — channel, tour, all shows, offer-level fee (landed / withholding), paymentPlan, setLengthMinutes, keyDetails, clauses (incl. payment schedule), platformTerms, additionalConditionsHtml, offer notes. Best-effort: a missing offer never breaks the booking read. Middle-agent bookings have deal: null until the MA offersheet is wired.
  • no duplicated fields: when deal is present the top-level fee is omitted (deal.fee is the single fee source); list rows and middle-agent bookings keep the top-level fee. The deal block never repeats offerId/acceptedAt. event = this booking’s show; deal.shows = every show in the deal (distinct meanings, both present).

Frontend Use:

  • booking detail page — Summary tab renders the full deal via OffersheetSummary (single fetch, no extra offer query)

What It Is For:

  • list booking activity timeline

Frontend Use:

  • booking activity tab

POST /api/v1/bookings/{bookingId}/activity

Section titled “POST /api/v1/bookings/{bookingId}/activity”

What It Is For:

  • append manual activity/note items

Frontend Use:

  • add internal note / activity event

GET /api/v1/market-companies/{id}/contract-templates

Section titled “GET /api/v1/market-companies/{id}/contract-templates”

What It Is For:

  • list contract templates for a company

Frontend Use:

  • template library

POST /api/v1/market-companies/{id}/contract-templates

Section titled “POST /api/v1/market-companies/{id}/contract-templates”

What It Is For:

  • create a company contract template

Frontend Use:

  • create template flow

GET /api/v1/contract-templates/{templateId}

Section titled “GET /api/v1/contract-templates/{templateId}”

What It Is For:

  • load one template

Frontend Use:

  • template detail

PATCH /api/v1/contract-templates/{templateId}

Section titled “PATCH /api/v1/contract-templates/{templateId}”

What It Is For:

  • update template metadata

Frontend Use:

  • edit template flow

POST /api/v1/contract-templates/{templateId}/activate

Section titled “POST /api/v1/contract-templates/{templateId}/activate”

What It Is For:

  • activate a template

Frontend Use:

  • template status action

POST /api/v1/contract-templates/{templateId}/archive

Section titled “POST /api/v1/contract-templates/{templateId}/archive”

What It Is For:

  • archive a template

Frontend Use:

  • template status action

POST /api/v1/contract-templates/{templateId}/upload-source

Section titled “POST /api/v1/contract-templates/{templateId}/upload-source”

What It Is For:

  • upload template source document

Frontend Use:

  • template file upload

GET /api/v1/contract-templates/default/source

Section titled “GET /api/v1/contract-templates/default/source”

What It Is For:

  • download the embedded Kisum standard contract template (DOCX with the full <<PLACEHOLDER>> marker set)

Frontend Use:

  • “Download the Kisum standard template” link in the upload-source dialog

POST /api/v1/contracts/{contractId}/send · POST …/signers/{signerId}/send

Section titled “POST /api/v1/contracts/{contractId}/send · POST …/signers/{signerId}/send”

What It Is For:

  • send signature-request emails via AWS SES (same SES_AWS_*/EMAIL_FROM env as the MA enquiry notifications). Fail closed: a signer/contract is marked “sent” only after its email actually went out. Contract-level send requires ≥1 signer, emails every not-yet-signed/declined signer and returns notifiedSigners; per-signer send allows re-sends. The email links the current version’s rendered document.

Frontend Use:

  • “Send for signature” header action; per-signer Send button (toast confirms the emailed address)

GET /api/v1/contracts/{contractId}/signers

Section titled “GET /api/v1/contracts/{contractId}/signers”

What It Is For:

  • list signer rows (same data as /signatures — that endpoint predates the FE naming). Added 2026-07-16: without this route the request fell through to the Promoters BFF proxy and 403’d with WRONG_PACKAGE.

Frontend Use:

  • contract Signers panel

GET /api/v1/contracts/{contractId}/attachments

Section titled “GET /api/v1/contracts/{contractId}/attachments”

What It Is For:

  • list contract attachments (riders, addenda, supporting docs)

Frontend Use:

  • contract Attachments panel

POST /api/v1/contracts/{contractId}/generate

Section titled “POST /api/v1/contracts/{contractId}/generate”

What It Is For:

  • render the contract’s template (uploaded source or embedded default by booking channel) auto-filled with the booking’s deal data; stores the DOCX as a new contract version and returns renderUrl + unresolvedPlaceholders (complete-before-signature checklist)
  • optional body { "variables": { "<MARKER NAME>": "value" } } supplies manual values for markers the platform can’t derive; manual values win over auto-derived ones, persist on the contract (variables_json.manual) and re-apply on every regeneration (empty string clears)

Frontend Use:

  • auto-run on contract create; “Generate document” + “Fill fields” in the contract Versions panel

DELETE /api/v1/contract-templates/{templateId}/source

Section titled “DELETE /api/v1/contract-templates/{templateId}/source”

What It Is For:

  • delete the stored template source file (removes the S3 object best-effort, clears the DB reference and the derived variable manifest; the template row is kept)

Frontend Use:

  • “Delete file” action on the template detail Source file card

GET /api/v1/contract-templates/{templateId}/variables

Section titled “GET /api/v1/contract-templates/{templateId}/variables”

What It Is For:

  • list required/available variables for a template

Frontend Use:

  • template variable mapping UI

GET /api/v1/bookings/{bookingId}/contracts

Section titled “GET /api/v1/bookings/{bookingId}/contracts”

What It Is For:

  • list contracts linked to a booking

Frontend Use:

  • contracts tab inside booking detail

POST /api/v1/bookings/{bookingId}/contracts

Section titled “POST /api/v1/bookings/{bookingId}/contracts”

What It Is For:

  • create a booking-linked contract

Frontend Use:

  • create contract from booking flow

Typical Flow:

  1. open booking contracts tab
  2. choose template
  3. fill variables
  4. create contract

What It Is For:

  • load contract thread detail

Frontend Use:

  • contract detail page

What It Is For:

  • send contract for signing

Frontend Use:

  • send action in contract detail

What It Is For:

  • void a contract

Frontend Use:

  • void action

GET /api/v1/contracts/{contractId}/versions

Section titled “GET /api/v1/contracts/{contractId}/versions”

What It Is For:

  • list versions for a contract

Frontend Use:

  • version history tab

POST /api/v1/contracts/{contractId}/versions

Section titled “POST /api/v1/contracts/{contractId}/versions”

What It Is For:

  • create a new contract version

Frontend Use:

  • revise contract flow

GET /api/v1/contracts/{contractId}/signatures

Section titled “GET /api/v1/contracts/{contractId}/signatures”

What It Is For:

  • load signer and signature state

Frontend Use:

  • signer progress panel

POST /api/v1/contracts/{contractId}/attachments

Section titled “POST /api/v1/contracts/{contractId}/attachments”

What It Is For:

  • add contract attachments

Frontend Use:

  • attachment upload

What It Is For:

  • list contract audit events

Frontend Use:

  • audit timeline tab

POST /api/v1/contracts/{contractId}/signers

Section titled “POST /api/v1/contracts/{contractId}/signers”

What It Is For:

  • add signer slots

Frontend Use:

  • signer setup flow

PATCH /api/v1/contracts/{contractId}/signers/{signerId}

Section titled “PATCH /api/v1/contracts/{contractId}/signers/{signerId}”

What It Is For:

  • update signer configuration

Frontend Use:

  • signer edit

POST /api/v1/contracts/{contractId}/signers/{signerId}/send

Section titled “POST /api/v1/contracts/{contractId}/signers/{signerId}/send”

What It Is For:

  • send a signer invite/action

Frontend Use:

  • signer dispatch

POST /api/v1/contracts/{contractId}/signers/{signerId}/sign

Section titled “POST /api/v1/contracts/{contractId}/signers/{signerId}/sign”

What It Is For:

  • complete signing action

Frontend Use:

  • sign action

POST /api/v1/contracts/{contractId}/signers/{signerId}/decline

Section titled “POST /api/v1/contracts/{contractId}/signers/{signerId}/decline”

What It Is For:

  • decline signing

Frontend Use:

  • signer decline action

What It Is For:

  • list tours for an artist

Frontend Use:

  • tours index

What It Is For:

  • create a tour plan

Access:

  • requires org to manage the artist (approved representation or active staff roster / team assignment via org-linked company — see pkg/orgaccess)

Frontend Use:

  • new tour flow

What It Is For:

  • load one tour plan

Frontend Use:

  • tour detail screen

What It Is For:

  • update a tour plan

Frontend Use:

  • edit tour flow

POST /api/v1/tour-plans/{tourPlanId}/stops

Section titled “POST /api/v1/tour-plans/{tourPlanId}/stops”

What It Is For:

  • add a tour stop

Frontend Use:

  • add stop action

PATCH /api/v1/tour-plans/{tourPlanId}/stops/{stopId}

Section titled “PATCH /api/v1/tour-plans/{tourPlanId}/stops/{stopId}”

What It Is For:

  • update a stop

Frontend Use:

  • stop edit flow

GET /api/v1/tour-plans/{tourPlanId}/routing

Section titled “GET /api/v1/tour-plans/{tourPlanId}/routing”

What It Is For:

  • load route ordering and routing output

Frontend Use:

  • routing tab

POST /api/v1/tour-plans/{tourPlanId}/routing/rebuild

Section titled “POST /api/v1/tour-plans/{tourPlanId}/routing/rebuild”

What It Is For:

  • rebuild route analysis

Frontend Use:

  • recompute routing action

GET /api/v1/tour-plans/{tourPlanId}/conflicts

Section titled “GET /api/v1/tour-plans/{tourPlanId}/conflicts”

What It Is For:

  • list routing or schedule conflicts

Frontend Use:

  • conflict panel

GET /api/v1/bookings/{bookingId}/logistics

Section titled “GET /api/v1/bookings/{bookingId}/logistics”

What It Is For:

  • load booking logistics summary

Frontend Use:

  • logistics tab

POST /api/v1/bookings/{bookingId}/logistics

Section titled “POST /api/v1/bookings/{bookingId}/logistics”

What It Is For:

  • create logistics record if missing

Frontend Use:

  • initial logistics setup

PATCH /api/v1/bookings/{bookingId}/logistics

Section titled “PATCH /api/v1/bookings/{bookingId}/logistics”

What It Is For:

  • update logistics record

Frontend Use:

  • logistics editing

GET /api/v1/bookings/{bookingId}/itinerary

Section titled “GET /api/v1/bookings/{bookingId}/itinerary”

What It Is For:

  • load itinerary items for a booking

Frontend Use:

  • itinerary tab

POST /api/v1/bookings/{bookingId}/itinerary-items

Section titled “POST /api/v1/bookings/{bookingId}/itinerary-items”

What It Is For:

  • create itinerary item

Frontend Use:

  • add itinerary entry

PATCH /api/v1/bookings/{bookingId}/itinerary-items/{itemId}

Section titled “PATCH /api/v1/bookings/{bookingId}/itinerary-items/{itemId}”

What It Is For:

  • update itinerary item

Frontend Use:

  • edit itinerary entry

GET /api/v1/bookings/{bookingId}/logistics-submissions

Section titled “GET /api/v1/bookings/{bookingId}/logistics-submissions”

What It Is For:

  • list logistics submissions for a booking

Frontend Use:

  • logistics approvals tab

POST /api/v1/bookings/{bookingId}/logistics-submissions

Section titled “POST /api/v1/bookings/{bookingId}/logistics-submissions”

What It Is For:

  • create a draft logistics submission

Frontend Use:

  • promoter coordinator creates hotel / hospitality / technical / transport proposal

Typical Flow:

  1. open booking logistics approvals
  2. create submission
  3. save draft
  4. submit for artist-side review

GET /api/v1/logistics-submissions/{submissionId}

Section titled “GET /api/v1/logistics-submissions/{submissionId}”

What It Is For:

  • load one submission

Frontend Use:

  • submission detail / review screen

PATCH /api/v1/logistics-submissions/{submissionId}

Section titled “PATCH /api/v1/logistics-submissions/{submissionId}”

What It Is For:

  • edit draft or editable submission fields

Frontend Use:

  • update proposal

POST /api/v1/logistics-submissions/{submissionId}/submit

Section titled “POST /api/v1/logistics-submissions/{submissionId}/submit”

What It Is For:

  • send a draft proposal into review

Frontend Use:

  • submit action for promoter-side coordinator

POST /api/v1/logistics-submissions/{submissionId}/approve

Section titled “POST /api/v1/logistics-submissions/{submissionId}/approve”

What It Is For:

  • approve a proposal

Frontend Use:

  • artist-side approval action

POST /api/v1/logistics-submissions/{submissionId}/reject

Section titled “POST /api/v1/logistics-submissions/{submissionId}/reject”

What It Is For:

  • reject a proposal

Frontend Use:

  • artist-side rejection action

POST /api/v1/logistics-submissions/{submissionId}/request-changes

Section titled “POST /api/v1/logistics-submissions/{submissionId}/request-changes”

What It Is For:

  • send a submission back with requested changes

Frontend Use:

  • artist-side review action

GET /api/v1/logistics-submissions/{submissionId}/decisions

Section titled “GET /api/v1/logistics-submissions/{submissionId}/decisions”

What It Is For:

  • load the decision history for one submission

Frontend Use:

  • review/audit panel

What It Is For:

  • list relationships

Frontend Use:

  • relationship search/list

GET /api/v1/relationships/{relationshipId}

Section titled “GET /api/v1/relationships/{relationshipId}”

What It Is For:

  • load relationship summary

Frontend Use:

  • relationship detail

GET|POST /api/v1/relationships/{relationshipId}/notes

Section titled “GET|POST /api/v1/relationships/{relationshipId}/notes”

What It Is For:

  • read or add org-private relationship notes

Frontend Use:

  • internal notes tab

GET|POST /api/v1/relationships/{relationshipId}/flags

Section titled “GET|POST /api/v1/relationships/{relationshipId}/flags”

What It Is For:

  • read or add org-private flags

Frontend Use:

  • risk/flag section

GET|POST /api/v1/relationships/{relationshipId}/ratings

Section titled “GET|POST /api/v1/relationships/{relationshipId}/ratings”

What It Is For:

  • read or add org-private manual ratings

Frontend Use:

  • trust input section

GET /api/v1/relationships/{relationshipId}/trust-score

Section titled “GET /api/v1/relationships/{relationshipId}/trust-score”

What It Is For:

  • load normalized trust output

Frontend Use:

  • trust badge / trust panel

GET /api/v1/relationships/{relationshipId}/signals

Section titled “GET /api/v1/relationships/{relationshipId}/signals”

What It Is For:

  • load signal breakdown behind trust

Frontend Use:

  • trust explanation panel

What It Is For:

  • load artist booking history

Frontend Use:

  • history tab on artist detail

GET /api/v1/promoters/{id}/booking-history

Section titled “GET /api/v1/promoters/{id}/booking-history”

What It Is For:

  • load promoter booking history

Frontend Use:

  • promoter relationship analysis

What It Is For:

  • load agency booking history

Frontend Use:

  • agency relationship analysis

GET /api/v1/bookings/{bookingId}/finance-status

Section titled “GET /api/v1/bookings/{bookingId}/finance-status”

What It Is For:

  • show overall finance visibility for a booking

Frontend Use:

  • finance panel inside booking detail

GET /api/v1/bookings/{bookingId}/payment-schedule

Section titled “GET /api/v1/bookings/{bookingId}/payment-schedule”

What It Is For:

  • show payment schedule visibility

Frontend Use:

  • payment schedule tab/panel

GET /api/v1/bookings/{bookingId}/deposit-status

Section titled “GET /api/v1/bookings/{bookingId}/deposit-status”

What It Is For:

  • show deposit visibility

Frontend Use:

  • deposit badge / summary

POST /api/v1/bookings/{bookingId}/finance-handoff

Section titled “POST /api/v1/bookings/{bookingId}/finance-handoff”

What It Is For:

  • record that booking workflow has been handed off to Finance

Frontend Use:

  • handoff action

What It Is For:

  • load agency dashboard summary

Frontend Use:

  • agency home/dashboard

What It Is For:

  • load agency roster pipeline (artists derived from active artist_team_assignments via company_people)

Frontend Use:

  • agency pipeline screen (Frontend-Kisum-Artists /roster)

Notes:

  • roster_role is artist_team_assignments.role::text (person_role_type enum). Do not default with a free-text label that is not an enum value (e.g. 'artist' caused 500).

What It Is For:

  • load agency tasks

Frontend Use:

  • task widgets / task list

What It Is For:

  • load agency activity stream

Frontend Use:

  • dashboard activity feed

What It Is For:

  • load promoter dashboard summary from the artist-network side

Frontend Use:

  • promoter-facing artist-market dashboard

What It Is For:

  • load promoter shortlists for the caller’s Core org ({id} = canonical x-org UUID)

Response includes per-row artistUuids (directory artist UUIDs on that shortlist) so marketplace cards can show Shortlisted state without N detail fetches.

Frontend Use:

  • shortlist page

Auth:

  • Bearer + x-org; scoped by created_by_core_company_id (no artists directory company claim required)

Caching:

  • Not Redis-cached on Promoters BFF or Artists upstream (mutating resource). Frontend may pass ?live=true on reads.

What It Is For:

  • create shortlist

Frontend Use:

  • create shortlist action

GET /api/v1/promoters/{id}/shortlists/{shortlistId}

Section titled “GET /api/v1/promoters/{id}/shortlists/{shortlistId}”

What It Is For:

  • load one shortlist with nested artists array

Frontend Use:

  • /booking/shortlists/[id]

DELETE /api/v1/promoters/{id}/shortlists/{shortlistId}

Section titled “DELETE /api/v1/promoters/{id}/shortlists/{shortlistId}”

What It Is For:

  • delete shortlist and its artist rows (cascade)

Frontend Use:

  • shortlist detail delete action

POST /api/v1/promoters/{id}/shortlists/{shortlistId}/artists

Section titled “POST /api/v1/promoters/{id}/shortlists/{shortlistId}/artists”

What It Is For:

  • add artist to shortlist

Frontend Use:

  • shortlist add flow from artist marketplace/list

DELETE /api/v1/promoters/{id}/shortlists/{shortlistId}/artists/{artistId}

Section titled “DELETE /api/v1/promoters/{id}/shortlists/{shortlistId}/artists/{artistId}”

What It Is For:

  • remove artist from shortlist

Frontend Use:

  • shortlist detail remove row

What It Is For:

  • load promoter inquiries/read model

Frontend Use:

  • inquiry pipeline screen

What It Is For:

  • load promoter offers/read model

Frontend Use:

  • offers pipeline screen

What It Is For:

  • search artists in marketplace context

Frontend Use:

  • artist marketplace list

What It Is For:

  • search agencies

Response (per row, Postgres companies):

  • roster_artists_count / roster_size (JSON) — companies.roster_size, maintained by Postgres triggers from derived represented artists (distinct artists via active artist_team_assignments + company_people) union company_needs_agent_artists (migration 000031_staff_linked_roster).
  • relationship_countnot roster size; count of artists_relationships graph edges (often 0 for browse)

Source of truth: artist_team_assignments (staff) + company_needs_agent_artists (imports awaiting agent). Cache: companies.roster_size.

After bulk data reshapes, run SELECT refresh_all_companies_roster_size(); as a privileged DB user.

Query params (sort/filter):

  • q — name/slug search
  • sort or sortByrosterArtistsCount (default), rosterSize, effectiveRoster, name, claimed, relationshipCount
  • order or sortTypeasc | desc (default desc for roster)
  • page, limit

Default list order: rosterArtistsCount DESC (largest agency rosters first), then name ASC.

Frontend Use:

  • agency marketplace/research list

What It Is For:

  • search promoters

Frontend Use:

  • promoter research list

What It Is For:

  • search talent buyers

Frontend Use:

  • buyer research list

What It Is For:

  • search venues for artist-side research

Frontend Use:

  • venue research list

12. Middle Agent Workspace (parallel to direct booking)

Section titled “12. Middle Agent Workspace (parallel to direct booking)”

Tenant operator routes under /api/v1/middle-agent/*. Promoter reads use /api/v1/marketplace/middle-agent-* or Promoters BFF /api/artists-network/middle-agent/*.

GET /api/v1/middle-agent/workspace/profile

Section titled “GET /api/v1/middle-agent/workspace/profile”

What It Is For:

  • load middle-agent workspace settings (organization_type, defaults, disclaimers)

Frontend Use:

  • Frontend-Kisum-Artists /settings/middle-agent-workspace

GET|POST /api/v1/middle-agent/workspace/artists

Section titled “GET|POST /api/v1/middle-agent/workspace/artists”

What It Is For:

  • private workspace roster cards (not official directory master)

Frontend Use:

  • /middle-agent/roster

GET|POST /api/v1/middle-agent/offers (+ qualify, confirm, reject, finance-handoff, chain, sources, quotes, holds, commissions, documents, communications, AI)

Section titled “GET|POST /api/v1/middle-agent/offers (+ qualify, confirm, reject, finance-handoff, chain, sources, quotes, holds, commissions, documents, communications, AI)”

What It Is For:

  • dual-sided offer pipeline (buyer_status + source_status)

Frontend Use:

  • /middle-agent/offers, /middle-agent/offers/[id]

Permissions: artist.middle_offer.* — financial fields redacted without source_fee.view, margin.view, commission.*.

GET /api/v1/middle-agent/inbound-source-offers

Section titled “GET /api/v1/middle-agent/inbound-source-offers”

What It Is For:

  • direct/exclusive agencies respond to source-side submissions

Frontend Use:

  • /middle-agent/inbound-source-offers

GET /api/v1/marketplace/middle-agent-listings

Section titled “GET /api/v1/marketplace/middle-agent-listings”

What It Is For:

  • promoter-safe published workspace cards

Frontend Use:

  • Promoters BFF → /booking/marketplace Non-direct tab

POST /api/v1/marketplace/offers (canonical)

Section titled “POST /api/v1/marketplace/offers (canonical)”

Purpose:

  • Create a promoter marketplace offer for either an official agency availability or a middle-agent listing.
  • Requires offerChannel: exclusive|middle_agent; Artists resolves the listing and rejects mismatches.
  • Stores the verified channel in offer metadata.

Consumers:

  • Promoters BFF → shared marketplace offer wizard.

Compatibility: POST /api/v1/marketplace/middle-agent-enquiries remains available for older callers and may infer the channel from the listing.

GET|PATCH /api/v1/marketplace/offers/:id (canonical)

Section titled “GET|PATCH /api/v1/marketplace/offers/:id (canonical)”

Purpose:

  • Read or revise a promoter marketplace offer without naming its representation channel in the URL.
  • PATCH requires and revalidates offerChannel against the stored listing representation.

Compatibility: matching middle-agent-enquiries/:id routes remain aliases.

POST /api/v1/marketplace/middle-agent-enquiries (legacy)

Section titled “POST /api/v1/marketplace/middle-agent-enquiries (legacy)”

What It Is For:

  • promoter enquiry → middle-agent incoming offer (offer_origin=promoter_network)

Frontend Use:

  • Promoters BFF → SendMiddleAgentEnquirySheet

GET /api/v1/marketplace/middle-agent-enquiries/:id

Section titled “GET /api/v1/marketplace/middle-agent-enquiries/:id”

What It Is For:

  • buyer-scoped offer detail (promoter org via metadata.buyerCoreCompanyId); enriched with seller name, artist image/id, timeline, revision history

Frontend Use:

  • Promoters BFF → /booking/offers/[id]

PATCH /api/v1/marketplace/middle-agent-enquiries/:id

Section titled “PATCH /api/v1/marketplace/middle-agent-enquiries/:id”

What It Is For:

  • buyer revises declined/cancelled/lost offer (full offersheet); resubmits as buyer_status=incoming; logs buyer_offer_revised

Frontend Use:

  • Promoters BFF → edit wizard at /booking/marketplace/enquire?editOfferId=…

DELETE /api/v1/marketplace/middle-agent-enquiries/:id

Section titled “DELETE /api/v1/marketplace/middle-agent-enquiries/:id”

What It Is For:

  • buyer hard-deletes declined/cancelled/lost offer (row removed from middle_agent_offers)

Frontend Use:

  • Promoters BFF → delete from offer detail

See Middle Agent Workspace for full route list and ownership.

Response contract change — bookings & booking offers (2026-07-16)

Section titled “Response contract change — bookings & booking offers (2026-07-16)”

GET /api/v1/bookings[/:bookingId], GET /api/v1/booking-offers[/:offerId], and the create/convert/counter/accept mutations now return the Buyer/Show shape: nested artist { id, name, imageUrl, countryId, countryName }, buyer { id, name, externalBuyerId } (Kisum Core UUID as id; null for guest/external buyers; externalBuyerId reserved, always null), agency { id, name }, booking event { promoterEventId, name, date (YYYY-MM-DD), time (HH:MM), venue { id, name }, location }, offer shows[] + tour + fee { amount, currency, isLanded, withholdingTax } + clauses/keyDetails/platformTerms, and offer versions[] { version, sentBy: buyer|agency, at, fee, shows, clauses }. Accept returns { booking, bookings[] } — one booking per show. Legacy fields (promoterCompany*, talentBuyerName, targetCompany*, startsAt/endsAt, raw commercial_terms dumps) are gone from these endpoints.