Partner Management Features
Operational APIs used by authenticated partner organizations after onboarding.
1. Settings (/api/partner-settings)
GET /api/partner-settingsPATCH /api/partner-settings/profilePATCH /api/partner-settings/businessPATCH /api/partner-settings/brandingPOST /api/partner-settings/api-keys/regeneratePATCH /api/partner-settings/apiPATCH /api/partner-settings/notificationsPATCH /api/partner-settings/billingGET /api/partner-settings/commissionPATCH /api/partner-settings/commission
PATCH /api/partner-settings/commission accepts customRates[] only (display JSON). Sending defaultRate / attempting to change seller_profiles.commissionRate is rejected (403 error.partner.commission_rate_admin_only when it reaches the service). Payout rate changes go through admin partners APIs.
PATCH /api/partner-settings/api with webhookUrl must be public HTTPS. Private/metadata URLs are rejected (same SSRF + pinned-DNS policy as portal webhooks).
2. Users (/api/partners/users)
POST /api/partners/usersGET /api/partners/usersGET /api/partners/users/statisticsGET /api/partners/users/:userIdPATCH /api/partners/users/:userIdDELETE /api/partners/users/:userIdPOST /api/partners/users/inviteGET /api/partners/users/:userId/permissionsPOST /api/partners/users/:userId/update-access
POST /api/partners/users/invite creates a pending partner_user (isActive=false). It does not send email automatically (emailDelivery=pending_manual). Existing non-client system roles are rejected. New placeholder accounts stay on the client system role until accept.
3. Reports (/api/partner-reports)
GET /api/partner-reports/revenueGET /api/partner-reports/performanceGET /api/partner-reports/top-destinationsGET /api/partner-reports/daily-revenueGET /api/partner-reports/monthly-trendGET /api/partner-reports/commissionGET /api/partner-reports/cenote-comparison
4. Reservations (/api/partner-reservations)
GET /api/partner-reservationsGET /api/partner-reservations/statsGET /api/partner-reservations/:idPOST /api/partner-reservationsPATCH /api/partner-reservations/:idPOST /api/partner-reservations/:id/cancel
POST /api/partner-reservations (and public POST /api/partner/reservations) accept the same core booking fields as WEB cenote create: ageBreakdown?, nationality?, transportationType?, pickup fields, additionalServices?, couponCode?, promotionId?, locale?, paymentMethod?, plus guest/contact contact fields. List filters honor dateFrom/dateTo and sortDirection aliases alongside startDate/endDate/sortOrder.
5. Webhooks (/api/partners/webhooks)
POST /api/partners/webhooks/test— partner JWT + permissions (partner.manage_settings); partner test endpointPOST /api/partners/webhooks/trigger— ADMIN-only (@Roles(ADMIN)); distinct from the partner test endpoint above
Portal webhook CRUD lives under /api/partner-portal/webhooks* and enforces public HTTPS + no redirects + pinned DNS on outbound test/delivery.
6. Sandbox (/api/partner-sandbox) — live
Sandbox is live when schema partners_sandbox exists (migration v23.0.62+). Requires a sandbox sk_test_ API key. These keys are not valid on /api/partner/* production routes (sandbox_key_not_allowed_on_production_api). Generate counts are capped (max 50 per resource type).
POST /api/partner-sandbox/generate-dataGET /api/partner-sandbox/statisticsDELETE /api/partner-sandbox/cleanup
7. Webhook simulator (/api/partner/webhooks/simulator) — live
Requires sandbox sk_test_ key (same production-API restriction as §6).
POST /api/partner/webhooks/simulator/simulatePOST /api/partner/webhooks/simulator/simulate-batchPOST /api/partner/webhooks/simulator/test-endpointGET /api/partner/webhooks/simulator/history
delay ≤ 10s, batch size ≤ 20 events, history limit ≤ 500 (validated + server-clamped). Outbound posts use the same SSRF guard and pinned DNS (DNS is resolved after any delay).
8. Supply cenotes (/api/partner-portal/cenotes) — supply partners only
Eligible partner types: tour_operator and hotel_partner (active + verified). Demand-only types (OTA, travel agency, etc.) receive 403.
Requires JWT + partner roles (partner_admin / partner_manager) and permissions:
| Method | Path | Permission |
|---|---|---|
| GET | /api/partner-portal/cenotes | partner.view_cenotes |
| POST | /api/partner-portal/cenotes | partner.manage_cenotes |
| GET | /api/partner-portal/cenotes/:id | partner.view_cenotes |
| PATCH | /api/partner-portal/cenotes/:id | partner.manage_cenotes |
| POST | /api/partner-portal/cenotes/:id/images | partner.manage_cenotes |
| POST | /api/partner-portal/cenotes/:id/request-publish | partner.request_publish_cenote |
draft → request-publish → pending_review → admin publish (active) or reject-publish (back to draft). Admin may suspend / reactivate. Partner may edit and attach images only while draft. Attach requires a file previously uploaded by the same user (uploaded_by).
Checklist before request-publish / admin publish: Spanish name, pricing (agePricing or packages), ≥1 active image.
Owned venue metrics: GET /api/partner-reports/owned-venues.
Notes
- these routes are not part of the public API-key partner integration layer
- most of them require JWT + partner context or additional permissions
- reports and reservation statistics expose monetary values in cents at API contract level
POST /api/partner-settings/api-keys/regenerateonce-revealsapiKeyonly (auth is JWT + partner roles/permissions; no functionalx-api-secret); deactivate+insert runs in a DB transaction- Verified against partner-supply-cenotes (2026-08-04)