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
Purpose
Section titled “Purpose”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.
How to read this page
Section titled “How to read this page”Each section below is organized as:
EndpointWhat It Is ForFrontend UseTypical 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
Venues (read-only directory proxy)
Section titled “Venues (read-only directory proxy)”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.
GET /api/v1/venues
Section titled “GET /api/v1/venues”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=allupstream (the admin feed otherwise defaults to non-sleeping only);activeis left unfiltered.
Frontend Use:
/venuesdirectory page (src/services/venues/api.ts listVenues).
GET /api/v1/venues/:id
Section titled “GET /api/v1/venues/:id”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. :idaccepts the Venues Postgres UUID or numericvenue_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.
GET /api/v1/promoters
Section titled “GET /api/v1/promoters”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:
/promotersdirectory page (src/services/promoters/api.ts listPromoters).
GET /api/v1/promoters/:id
Section titled “GET /api/v1/promoters/:id”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. :idis the Core company UUID.
Frontend Use:
/promoters/[id]detail page (getPromoter).
GET /api/v1/promoters/:id/shows
Section titled “GET /api/v1/promoters/:id/shows”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.
0. Agency provisioning (Phase 8)
Section titled “0. Agency provisioning (Phase 8)”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_uniqkeeps 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.
GET /api/v1/artists-companies/sleeping
Section titled “GET /api/v1/artists-companies/sleeping”What It Is For:
- search the central directory of unclaimed artists-companies that a tenant could claim
- search-required: returns
[]whenq.length < 2(privacy + abuse vector — same comment as the Venues equivalent) - joins
hasPendingRequest+pendingRequestIdper caller (scoped to the requesting Auth org only — no cross-org leak)
Query params: q, country, page, limit (default 25, max 200).
Frontend Use:
SleepingCompanyBrowseron/settings/agencyempty 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? }—companyIdaccepts 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:
TakeoverRequestDialogafter 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+countryrequired; spec is stored verbatim in JSONB until approve
Pre-checks: same single-pending-per-org guard as takeover.
Frontend Use:
CreationRequestDialogon/settings/agencyempty state
GET /api/v1/artists-companies/requests
Section titled “GET /api/v1/artists-companies/requests”What It Is For:
- the caller’s own provisioning history (unified list with
kinddiscriminator, newest first) - shows admin
decisionNoteswhen present so the tenant sees rejection reasons
Query params: status (optional filter).
Frontend Use:
MyAgencyRequestsListon/settings/agencyempty state
GET /api/v1/me/agency
Section titled “GET /api/v1/me/agency”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 inFrontend-Kisum-Artists— drives both the layout’s amber no-agency banner and the/settings/agencypage’s two-mode render
Platform: company hard-delete (machine)
Section titled “Platform: company hard-delete (machine)”GET /internal/companies/:companyId/delete-preview— counts rows across Artists core-UUID columns + bridged directory companies; blockers for shared booking graph rowsPOST /internal/companies/:companyId/purge— body{ mode, force, tombstoneCompanyId }; repoints shared booking side to tombstone whenforce=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>" } }(numericartists.id) fromartist_platform_accounts+platforms.code='spotify'. Auth:X-Internal-API-Key(ARTISTS_INTERNAL_API_KEY). Does not change publicGET /api/v1/artists?q=.- Consumer:
Backend-Kisum-AdminSpotify search enrichment (kisumArtistIdonGET /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 queueGET /internal/admin/artist-company-requests/:requestId— single request detailPOST /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 frompending.
Frontend Use:
- proxied through
Backend-Kisum-Admin → /api/v1/admin/artist-company-requests/*and consumed byFrontend-Kisum-Admin → System → Artist Company Requests
1. Directory and profiles
Section titled “1. Directory and profiles”GET /api/v1/artists
Section titled “GET /api/v1/artists”What It Is For:
- list artists for search, tables, and selector UIs
Query:
q— text search (when set, uses rankedWITH search / matchesSQL: trigram%+LIKE, then exact → prefix → whole word → contains → similarity; clientsortis ignored whileqis present)sort/order— only apply whenqis empty (default sort:rankasc)
Frontend Use:
- artist directory page
- artist picker modals
- shortlist add flow
Typical Flow:
- user opens artist list
- frontend loads artists
- user filters/searches
- user opens one artist detail
POST /api/v1/artists
Section titled “POST /api/v1/artists”What It Is For:
- create a new artist record
Frontend Use:
- artist creation form
- admin/operator data entry flow
Typical Flow:
- user clicks create artist
- frontend submits form
- user lands on artist detail
GET /api/v1/artists/{id}
Section titled “GET /api/v1/artists/{id}”What It Is For:
- load artist summary/detail record
Frontend Use:
- artist detail header
- summary card
- page bootstrap
Typical Flow:
- user opens artist detail
- frontend loads main artist record
- page tabs then load subresources
PATCH /api/v1/artists/{id}
Section titled “PATCH /api/v1/artists/{id}”What It Is For:
- update core artist fields
Frontend Use:
- edit artist form
Typical Flow:
- user edits artist
- frontend submits patch
- refresh summary/header
DELETE /api/v1/artists/{id}
Section titled “DELETE /api/v1/artists/{id}”What It Is For:
- remove artist record where allowed
Frontend Use:
- destructive admin action only
Typical Flow:
- user confirms delete
- frontend calls delete
- list view refreshes
GET|PUT /api/v1/artists/{id}/profile
Section titled “GET|PUT /api/v1/artists/{id}/profile”What It Is For:
- read or update extended artist profile fields
Frontend Use:
- profile tab
- edit profile screen
Typical Flow:
- open profile tab
- load profile
- edit and save profile
GET|PUT /api/v1/artists/{id}/genres
Section titled “GET|PUT /api/v1/artists/{id}/genres”What It Is For:
- read or update artist genres
Frontend Use:
- taxonomy editor
- search tagging UI
GET|PUT /api/v1/artists/{id}/subgenres
Section titled “GET|PUT /api/v1/artists/{id}/subgenres”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
GET|PUT /api/v1/artists/{id}/team
Section titled “GET|PUT /api/v1/artists/{id}/team”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_idis set, Artists resolves company from the person’s activecompany_peopleemployment (preferscompanies.role_typematchingassignment_type, thenis_primary).company_idon assignments was removed (migration000031); staff is the only representation link.
Frontend Use:
- contacts/team tab
GET|PUT /api/v1/artists/{id}/roster
Section titled “GET|PUT /api/v1/artists/{id}/roster”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 CRUDGET|POST /api/v1/companies/{id}/needs-agent— list / add needs-agent rowsDELETE /api/v1/companies/{id}/needs-agent/{needsAgentId}— remove holding rowPOST /api/v1/companies/{id}/needs-agent/{needsAgentId}/promote— assign staff + territories, remove holding rowPUT /api/v1/people/{id}/roster— bulk replace person assignmentsPOST|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 usePOST /assignmentsfrom the browser for this flow — claims require Admin approval.territoriesis structured JSONB (migration 000036); legacy free-text lives interritories_legacy(TEXT[]).GET|POST /internal/admin/staff-roster-claims/*— Admin review queue (machine key). Approve createsartist_team_assignmentsfrom claim fields (personId,artistId,role,assignmentType,territoriesJSONB). Reject updates status only. Tables:artist_staff_roster_claims,artist_team_assignments(migration 000035 + 000036). Proxied viaBackend-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 asexcludedRegions,excludedSubregions, andexcluded(country ids). - Pre-migration free-text (
WW,Worldwide, etc.) remains interritories_legacyonly; best-effort migration mapsWW/Worldwide→{"region":[{"id":0,"excluded":null}],…}. - Middle-agent marketplace listings keep separate
territories_jsonstring-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/*.
GET /api/v1/companies
Section titled “GET /api/v1/companies”What It Is For:
- list market companies / agencies / counterparties
Frontend Use:
- company directory
- agency picker
- claim flow lookup
POST /api/v1/companies
Section titled “POST /api/v1/companies”What It Is For:
- create company/agency directory records
Frontend Use:
- create agency/company flow
GET /api/v1/companies/{id}
Section titled “GET /api/v1/companies/{id}”What It Is For:
- load company detail
Frontend Use:
- agency/company detail page
PATCH /api/v1/companies/{id}
Section titled “PATCH /api/v1/companies/{id}”What It Is For:
- update company detail fields
Frontend Use:
- edit agency/company form
DELETE /api/v1/companies/{id}
Section titled “DELETE /api/v1/companies/{id}”What It Is For:
- delete company record where allowed
Frontend Use:
- admin destructive action
GET|PUT /api/v1/companies/{id}/people
Section titled “GET|PUT /api/v1/companies/{id}/people”What It Is For:
- read or maintain company contacts
Frontend Use:
- contacts tab
GET|PUT /api/v1/companies/{id}/locations
Section titled “GET|PUT /api/v1/companies/{id}/locations”What It Is For:
- read or maintain company locations
Frontend Use:
- office/territory section
GET|PUT /api/v1/companies/{id}/genres
Section titled “GET|PUT /api/v1/companies/{id}/genres”What It Is For:
- read or maintain company genre alignment
Frontend Use:
- company profile taxonomy
GET|PUT /api/v1/companies/{id}/roster
Section titled “GET|PUT /api/v1/companies/{id}/roster”What It Is For:
- read derived staff-linked roster for a company (
PUTis 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 optionalperson_*for the chosen agent - pagination
totalusesCOUNT(DISTINCT artist_id)
GET /api/v1/people/{id}/roster
Section titled “GET /api/v1/people/{id}/roster”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 useartist_slug(fallbackartist_id), never assignmentid
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
GET /api/v1/people
Section titled “GET /api/v1/people”What It Is For:
- list people / contacts
Frontend Use:
- contacts list
- person picker
POST /api/v1/people
Section titled “POST /api/v1/people”What It Is For:
- create a person/contact
Frontend Use:
- add contact flow
GET /api/v1/people/{id}
Section titled “GET /api/v1/people/{id}”What It Is For:
- load one person/contact
Frontend Use:
- contact detail drawer/page
PATCH /api/v1/people/{id}
Section titled “PATCH /api/v1/people/{id}”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-org → artists_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/countriesand/api/v1/countries/{id}/cities; dial code select from countriesphonePrefix.
DELETE /api/v1/people/{id}
Section titled “DELETE /api/v1/people/{id}”What It Is For:
- delete contact record where allowed
Frontend Use:
- admin destructive action
GET /api/v1/people/{id}/companies
Section titled “GET /api/v1/people/{id}/companies”What It Is For:
- load the companies linked to a person (
company_people— includes per-companytitle+role)
Frontend Use:
- contact affiliations section (subtitle =
title · role). Person Title edits viaPATCH /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:
- load page
- fetch lookup data
- populate selectors
2. Ownership and representation
Section titled “2. Ownership and representation”POST /api/v1/market-companies/{id}/claims
Section titled “POST /api/v1/market-companies/{id}/claims”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:
- user opens company
- clicks claim
- submits claim
- UI shows pending review
GET /api/v1/market-companies/{id}/claims
Section titled “GET /api/v1/market-companies/{id}/claims”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:
- open artist representation tab
- submit claim
- 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
GET /api/v1/artists/{id}/representation
Section titled “GET /api/v1/artists/{id}/representation”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
3. Availability and discovery
Section titled “3. Availability and discovery”GET /api/v1/artists/{id}/availabilities
Section titled “GET /api/v1/artists/{id}/availabilities”What It Is For:
- list artist availability entries
Frontend Use:
- availabilities tab
- artist calendar
POST /api/v1/artists/{id}/availabilities
Section titled “POST /api/v1/artists/{id}/availabilities”What It Is For:
- create an availability entry
Request body (camelCase JSON):
startsAt,endsAt— RFC3339 timestampsavailabilityType—open|blackout|soft_hold|routing_hold(defaultopen)status—active|cancelled(defaultactive)territoryText,notes— optional stringsrepresentationClaimId— optional; when omitted the insert still binds a nullable$2placeholder (do not skip the arg index)
Frontend Use:
- create availability flow (
Frontend-Kisum-Artistsmaps UIavailable/hold/blocked→ backend types and sendsstartsAt/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 Postgresartists.id(filters both sources)from/to— date overlap windowofficial—true|falseto 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 showscountry— 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 togethercity— numeric city id or a partial, case-insensitive city namegenre— numeric genre id, genre slug, or a partial, case-insensitive genre namefeeMin/feeMax— asking-fee range. Middle-agent listings only: matchesfee_terms_json(artistFee, or amin/maxband) with range-overlap semantics, and listings with no numeric fee are excluded while a bound is active.artist_availabilitieshas 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:
- promoter opens marketplace
- filters by date/location
- sees matching artists (exclusive + secondary when
officialomitted) - 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:open→available,soft_hold/routing_hold→hold,blackout→blocked - 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,tois treated as an inclusive day (SQL upper bound is exclusive next-midnight) capped(final-review fix, 2026-07-14) —truewhen the window fetch behind the summary hitAgencyAvailabilityWindowCap(20,000 windows); totals/days may undercount for very wide or dense ranges when this is set, so narrowfrom/toor add filters for an exact countartistId(final-review fix, 2026-07-14) — was parsed but silently ignored by both agency endpoints (picking an artist did nothing); now applied to the SQLWHEREon both
Frontend Use:
Frontend-Kisum-Artists/availabilityMonth heatmap (density-first per-day counts); shows a muted “narrow with filters” note whencappedis 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/endsAtalways serialize with an explicit UTCZsuffix, 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
4. Booking workflow
Section titled “4. Booking workflow”GET /api/v1/booking-requests
Section titled “GET /api/v1/booking-requests”What It Is For:
- list booking requests
Frontend Use:
- requests inbox/list
POST /api/v1/booking-requests
Section titled “POST /api/v1/booking-requests”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. BodypromoterCompanyIdmay be the canonical Core org UUID (same asx-org) — noartists_company_claimsrow required.created_by_core_company_idis the buyer scope; optionalpromoter_company_idFK is filled from an approved claim when present.
Typical Flow:
- user chooses artist
- fills request (dates, territory, optional budget)
- submits request
- request appears in pipeline
Optional body fields (2026-06-26):
budgetAmount— numeric gross fee / all-in budget the promoter is willing to paybudgetCurrency— ISO currency code (defaultUSD)- On
middle_agent_broadcastrouting, budget is copied to each fan-out offer asbuyerPriceAmount/buyerPriceCurrency
Optional body fields (2026-06-30):
promoterEventId— canonical PromoterpublicEventIdUUID when linking a request to an event; not required for standalone requests (offers still require event linkage via offersheet)
GET /api/v1/booking-requests/{requestId}
Section titled “GET /api/v1/booking-requests/{requestId}”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 legacywithdrawn)
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
GET /api/v1/booking-offers
Section titled “GET /api/v1/booking-offers”What It Is For:
- list offers
Frontend Use:
- offer pipeline
POST /api/v1/booking-offers
Section titled “POST /api/v1/booking-offers”What It Is For:
- create an offer directly
Frontend Use:
- direct offer creation
GET /api/v1/booking-offers/{offerId}
Section titled “GET /api/v1/booking-offers/{offerId}”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 keyedladder:<band>, bound to that band’s current charge). Missing/stale/incomplete acceptance → 422MUTUAL_TERMS_NOT_ACCEPTED(message starts “Mutual terms”). Offers withoutmutualTermsskip the gate. On the actual accepted flip (not a re-accept), the availability’scontract_terms_jsonbest-effort snapshots into the accepted version’soffersheet.artistContractTerms.
Frontend Use:
- deal acceptance action; on 422
MUTUAL_TERMS_NOT_ACCEPTEDthe FE opensMutualTermsDialogautomatically
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>, andbilling:<showIndex>(2026-07-17: billing moved per-show — one accept row per show — replacing the earlier singlemutualTerms.billingkey) - 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 proposedmutualTerms)
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
GET /api/v1/bookings
Section titled “GET /api/v1/bookings”What It Is For:
- list confirmed/current bookings
Frontend Use:
- bookings index
GET /api/v1/bookings/{bookingId}
Section titled “GET /api/v1/bookings/{bookingId}”What It Is For:
- load booking detail — the confirmed deal
- carries a
dealblock (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 havedeal: nulluntil the MA offersheet is wired. - no duplicated fields: when
dealis present the top-levelfeeis omitted (deal.feeis the single fee source); list rows and middle-agent bookings keep the top-levelfee. The deal block never repeatsofferId/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)
GET /api/v1/bookings/{bookingId}/activity
Section titled “GET /api/v1/bookings/{bookingId}/activity”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
5. Contract workflow
Section titled “5. Contract workflow”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_FROMenv 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 returnsnotifiedSigners; 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:
- open booking contracts tab
- choose template
- fill variables
- create contract
GET /api/v1/contracts/{contractId}
Section titled “GET /api/v1/contracts/{contractId}”What It Is For:
- load contract thread detail
Frontend Use:
- contract detail page
POST /api/v1/contracts/{contractId}/send
Section titled “POST /api/v1/contracts/{contractId}/send”What It Is For:
- send contract for signing
Frontend Use:
- send action in contract detail
POST /api/v1/contracts/{contractId}/void
Section titled “POST /api/v1/contracts/{contractId}/void”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
GET /api/v1/contracts/{contractId}/events
Section titled “GET /api/v1/contracts/{contractId}/events”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
6. Touring and itinerary
Section titled “6. Touring and itinerary”GET /api/v1/artists/{id}/tour-plans
Section titled “GET /api/v1/artists/{id}/tour-plans”What It Is For:
- list tours for an artist
Frontend Use:
- tours index
POST /api/v1/artists/{id}/tour-plans
Section titled “POST /api/v1/artists/{id}/tour-plans”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
GET /api/v1/tour-plans/{tourPlanId}
Section titled “GET /api/v1/tour-plans/{tourPlanId}”What It Is For:
- load one tour plan
Frontend Use:
- tour detail screen
PATCH /api/v1/tour-plans/{tourPlanId}
Section titled “PATCH /api/v1/tour-plans/{tourPlanId}”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
7. Logistics submissions and approvals
Section titled “7. Logistics submissions and approvals”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:
- open booking logistics approvals
- create submission
- save draft
- 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
8. Relationship memory and trust
Section titled “8. Relationship memory and trust”GET /api/v1/relationships
Section titled “GET /api/v1/relationships”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
GET /api/v1/artists/{id}/booking-history
Section titled “GET /api/v1/artists/{id}/booking-history”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
GET /api/v1/agencies/{id}/booking-history
Section titled “GET /api/v1/agencies/{id}/booking-history”What It Is For:
- load agency booking history
Frontend Use:
- agency relationship analysis
9. Finance visibility
Section titled “9. Finance visibility”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
10. Dashboards and shortlists
Section titled “10. Dashboards and shortlists”GET /api/v1/agencies/{id}/dashboard
Section titled “GET /api/v1/agencies/{id}/dashboard”What It Is For:
- load agency dashboard summary
Frontend Use:
- agency home/dashboard
GET /api/v1/agencies/{id}/roster/pipeline
Section titled “GET /api/v1/agencies/{id}/roster/pipeline”What It Is For:
- load agency roster pipeline (artists derived from active
artist_team_assignmentsviacompany_people)
Frontend Use:
- agency pipeline screen (
Frontend-Kisum-Artists/roster)
Notes:
roster_roleisartist_team_assignments.role::text(person_role_typeenum). Do not default with a free-text label that is not an enum value (e.g.'artist'caused 500).
GET /api/v1/agencies/{id}/tasks
Section titled “GET /api/v1/agencies/{id}/tasks”What It Is For:
- load agency tasks
Frontend Use:
- task widgets / task list
GET /api/v1/agencies/{id}/activity
Section titled “GET /api/v1/agencies/{id}/activity”What It Is For:
- load agency activity stream
Frontend Use:
- dashboard activity feed
GET /api/v1/promoters/{id}/dashboard
Section titled “GET /api/v1/promoters/{id}/dashboard”What It Is For:
- load promoter dashboard summary from the artist-network side
Frontend Use:
- promoter-facing artist-market dashboard
GET /api/v1/promoters/{id}/shortlists
Section titled “GET /api/v1/promoters/{id}/shortlists”What It Is For:
- load promoter shortlists for the caller’s Core org (
{id}= canonicalx-orgUUID)
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 bycreated_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=trueon reads.
POST /api/v1/promoters/{id}/shortlists
Section titled “POST /api/v1/promoters/{id}/shortlists”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
artistsarray
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
GET /api/v1/promoters/{id}/inquiries
Section titled “GET /api/v1/promoters/{id}/inquiries”What It Is For:
- load promoter inquiries/read model
Frontend Use:
- inquiry pipeline screen
GET /api/v1/promoters/{id}/offers
Section titled “GET /api/v1/promoters/{id}/offers”What It Is For:
- load promoter offers/read model
Frontend Use:
- offers pipeline screen
11. Marketplace search and research
Section titled “11. Marketplace search and research”GET /api/v1/marketplace/artists
Section titled “GET /api/v1/marketplace/artists”What It Is For:
- search artists in marketplace context
Frontend Use:
- artist marketplace list
GET /api/v1/marketplace/agencies
Section titled “GET /api/v1/marketplace/agencies”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 activeartist_team_assignments+company_people) unioncompany_needs_agent_artists(migration000031_staff_linked_roster).relationship_count— not roster size; count ofartists_relationshipsgraph 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 searchsortorsortBy—rosterArtistsCount(default),rosterSize,effectiveRoster,name,claimed,relationshipCountorderorsortType—asc|desc(defaultdescfor roster)page,limit
Default list order: rosterArtistsCount DESC (largest agency rosters first), then name ASC.
Frontend Use:
- agency marketplace/research list
GET /api/v1/marketplace/promoters
Section titled “GET /api/v1/marketplace/promoters”What It Is For:
- search promoters
Frontend Use:
- promoter research list
GET /api/v1/marketplace/talent-buyers
Section titled “GET /api/v1/marketplace/talent-buyers”What It Is For:
- search talent buyers
Frontend Use:
- buyer research list
GET /api/v1/marketplace/venues
Section titled “GET /api/v1/marketplace/venues”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/marketplaceNon-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
offerChannelagainst 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; logsbuyer_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.