The Kaxan REST API lets you build on top of the full booking platform β manage tours, users, payments, and rewards programmatically.
Content-Type: application/json. Dates use ISO 8601 format: YYYY-MM-DD.After a successful login or register call, the API returns a signed JWT token. Include this token in the Authorization header of every protected request.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
X-Admin-Key header. Store your admin key in environment variables β never expose it client-side.The API uses conventional HTTP status codes. Errors return a consistent JSON shape with a code and human-readable message.
{ "error": { "code": "INVALID_CREDENTIALS", "message": "Email or password is incorrect.", "status": 401 } }
| Status | Meaning |
|---|---|
| 200 | OK β request succeeded |
| 201 | Created β resource created |
| 400 | Bad Request β invalid parameters |
| 401 | Unauthorized β missing or invalid token |
| 403 | Forbidden β insufficient permissions |
| 404 | Not Found β resource doesn't exist |
| 409 | Conflict β e.g. email already registered |
| 429 | Too Many Requests β rate limit exceeded |
| 500 | Server Error β contact support |
Creates a new user account. Returns a JWT token and the user object. A welcome email is sent automatically via SendGrid.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Full name of the user |
| string | required | Valid email address. Must be unique. | |
| password | string | required | Min 6 characters. Stored as bcrypt hash. |
POST /auth/register Content-Type: application/json { "name": "Elena Vasquez", "email": "elena@email.com", "password": "securepass123" }
{ "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJ1c3JfMTIzIn0.abc", "user": { "id": "usr_abc123", "name": "Elena Vasquez", "email": "elena@email.com", "points": 0, "tier": "bronze", "createdAt": "2026-03-12T10:00:00Z" } }
Authenticates an existing user. Returns a JWT token valid for 7 days.
{ "email": "elena@email.com", "password": "securepass123" }
{ "token": "eyJhbGciOiJIUzI1NiJ9...", "expiresAt": "2026-03-19T10:00:00Z", "user": { /* user object */ } }
Returns the authenticated user's full profile including points balance and tier.
{ "id": "usr_abc123", "name": "Elena Vasquez", "email": "elena@email.com", "points": 1840, "tier": "silver", "bookingsCount": 4, "totalSpent": 18400, "createdAt": "2026-01-10T08:30:00Z" }
Updates the authenticated user's name or password. Email cannot be changed after registration.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | optional | New display name |
| currentPassword | string | optional | Required only when changing password |
| newPassword | string | optional | Min 6 chars. Requires currentPassword |
Returns a paginated list of all available tours. Supports filtering and sorting.
| Param | Type | Default | Description |
|---|---|---|---|
| type | string | all | hiking | wildlife | all |
| page | integer | 1 | Page number for pagination |
| limit | integer | 20 | Results per page (max 100) |
| sortBy | string | createdAt | price | rating | createdAt |
| available | boolean | false | Filter only tours with open spots |
{ "data": [ { "id": "tour_001", "name": "Torres del Paine Circuit Trek", "location": "Patagonia, Chile", "type": "hiking", "days": 10, "startTime": "07:00", "endTime": "18:00", "priceAdult": 2340, "priceChild": 1560, "rating": 4.9, "imageUrl": "https://...", "inclusions": ["Professional guide", "All meals"], "nextAvailable": "2026-04-15" } ], "pagination": { "page": 1, "limit": 20, "total": 6, "pages": 1 } }
Add, update, or remove departure dates and their available spots for a specific tour. Admin only.
{ "availability": { "2026-04-15": 12, "2026-05-01": 8, "2026-06-15": 0 // 0 = sold out } }
Creates a new booking. Requires a confirmed Stripe Payment Intent ID. Points are automatically calculated and credited to the user's account after payment. A confirmation email is sent to the traveler.
| Field | Type | Required | Description |
|---|---|---|---|
| tourId | string | required | ID of the tour to book |
| departureDate | string | required | ISO date, must match available slot |
| adults | integer | required | Ages 13β65. Min 1. |
| children | integer | optional | Ages 4β12. Defaults to 0. |
| paymentIntentId | string | required | Confirmed Stripe Payment Intent ID |
| redeemPoints | integer | optional | Points to redeem (min 100, multiples of 100) |
| contactName | string | required | Lead traveler's full name |
| contactPhone | string | optional | Lead traveler's phone number |
{ "bookingId": "bkg_xyz789", "status": "confirmed", "tourName": "Torres del Paine Circuit Trek", "departureDate": "2026-04-15", "startTime": "07:00", "endTime": "18:00", "adults": 2, "children": 1, "baseTotal": 6240, "pointsDiscount": 50, "totalCharged": 6190, "pointsEarned": 619, "confirmationEmail": "sent" }
Creates a Stripe Payment Intent for a booking. Returns a clientSecret to complete the payment on the frontend using Stripe.js. Always call this before creating a booking.
| Field | Type | Required | Description |
|---|---|---|---|
| tourId | string | required | Tour being booked |
| adults | integer | required | Number of adult travelers |
| children | integer | optional | Number of child travelers |
| redeemPoints | integer | optional | Points to deduct from total. Server validates available balance. |
| currency | string | optional | ISO currency code. Default: usd |
{ "paymentIntentId": "pi_3OxHY2...", "clientSecret": "pi_3OxHY2..._secret_abc", "amountCents": 619000, "currency": "usd", "breakdown": { "baseTotal": 6240, "pointsDiscount": 50, "finalTotal": 6190 } }
clientSecret with stripe.confirmCardPayment() on the frontend. Once confirmed, pass the paymentIntentId to POST /bookings.Initiates a full or partial refund via Stripe. Points earned from this booking are deducted from the user's balance. Admin only.
| Field | Type | Required | Description |
|---|---|---|---|
| amount | integer | optional | Refund amount in cents. Omit for full refund. |
| reason | string | optional | duplicate | fraudulent | requested_by_customer |
Returns the current authenticated user's points balance, tier, and redeemable value.
{ "points": 1840, "tier": "silver", "redeemableValue": 184.00, "nextTier": "gold", "pointsToNextTier": 160, "ratePerDollar": 0.1, "minRedeem": 100 }
Returns a paginated list of all points transactions for the authenticated user.
{ "transactions": [ { "type": "earned", "amount": +619, "description": "Torres del Paine booking", "bookingId": "bkg_xyz789", "createdAt": "2026-03-12T10:00:00Z" }, { "type": "redeemed", "amount": -500, "description": "$50 discount on Masai Mara booking", "bookingId": "bkg_abc456", "createdAt": "2026-02-20T14:30:00Z" } ], "pagination": { "page": 1, "total": 8 } }
X-Admin-Key header. Never expose the admin key in frontend code. Always call admin routes server-side.Returns aggregate statistics for the admin dashboard: revenue, bookings, new users, and top tours.
{ "revenue": { "total": 284600, "thisMonth": 42300, "growth": "+18%" }, "bookings": { "total": 340, "thisMonth": 24, "cancelled": 12 }, "users": { "total": 1204, "newThisMonth": 87 }, "topTours": [ { "id": "tour_003", "name": "Everest Base Camp", "bookings": 62 } ] }
Sends a transactional or broadcast email via SendGrid. Use for confirmations, reminders, or marketing campaigns.
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | string[] | required | Recipient email(s) |
| template | string | required | booking_confirmation | welcome | cancellation | reminder | custom |
| subject | string | optional | Required when template is custom |
| data | object | optional | Template variables (e.g. {"name": "Elena", "tourName": "..."}) |
Kaxan can push real-time events to your server via webhooks. Register a URL in the admin dashboard and we'll POST a signed payload for each event.
| Event | Trigger |
|---|---|
| booking.created | A new booking is confirmed and paid |
| booking.cancelled | A booking is cancelled |
| payment.succeeded | Stripe payment is captured |
| payment.refunded | A refund is issued |
| user.registered | A new user account is created |
| points.redeemed | A user redeems points on a booking |
X-Kaxan-Signature header. Verify it using your webhook secret to authenticate requests: HMAC-SHA256(payload, secret).{ "event": "booking.created", "timestamp": "2026-03-12T10:00:00Z", "data": { "bookingId": "bkg_xyz789", "userId": "usr_abc123", "tourId": "tour_001", "totalCharged": 6190, "pointsEarned": 619 } }