# MOGU Public API Documentation

Welcome to the MOGU Public API documentation. This API allows you to programmatically manage trips and catalogs for your travel business.

## Getting Started

### Authentication

All API endpoints require authentication using API Keys.

Include your API Key in the `Authorization` header of every request:


```
Authorization: Bearer YOUR_API_KEY
```

### Base URLs

- **Trips & Catalogs**: `https://trips.api.moguplatform.com`
- **AI Trip Imports**: `https://ai.api.moguplatform.com`


## Quick Start

### 1. Obtain an API Key

To access the API, you'll need to generate an API Key from your MOGU account:

1. Log in to your MOGU account
2. Navigate to the **Integrations** tab in your account settings
3. Generate a new API Key


The API Key will start with `ak_` and will include the necessary permissions based on your account role.

**Learn how to generate an API Key**: For step-by-step instructions, see our [How to generate an API Key guide](https://help.moguplatform.com/en/articles/12868814-how-to-generate-an-api-key).

### 2. Make Your First Request

Here's a simple example to list your trips:


```bash
curl -X GET https://trips.api.moguplatform.com/trips \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
```

## Core Concepts

Most workflows are based on fetching a full resource, editing it locally, and sending it back to the API.

For trips, the most important concept is the **TripConfig**, which contains the full proposal configuration (including the block tree used by the builder).

## Blocks

A proposal is represented as a **tree of blocks** (`TripConfig.blocks`).

- Keep `id` **unique** across all blocks.
- Use `parent` + `children` to model the hierarchy.
- `children` order matters (it defines the visual order).
- Container blocks (like `itinerary`, `itineraryDay`, `group`, `box`, `dropdown`) can hold other blocks.
- `hidden: true` hides a block without removing it.
- `metadata` (optional) can store integration-specific data.


### How to build a proposal (recommended workflow)

The trip configuration endpoint is **replace-based**:

- `GET /trips/{tripId}/config` returns the full config.
- `PUT /trips/{tripId}/config` **replaces** the full config.


Recommended flow:

1. Create or pick a trip (`POST /trips` or list existing trips)
2. Fetch config: `GET /trips/{tripId}/config`
3. Modify the returned object locally (typically `blocks`)
4. Send the full updated config back: `PUT /trips/{tripId}/config`


### Rules of thumb

- Keep `id` **unique** across all blocks.
- Preserve existing blocks you don't intend to change (because `PUT` replaces the entire config).
- `children` order matters (it defines the visual order).


### Minimal example: itinerary with 2 days

This is an example of a minimal, practical block tree:


```json
{
  "blocks": [
    {
      "id": "b-itinerary",
      "type": "itinerary",
      "content": {
        "selectedDay": 0,
        "showDates": true,
        "showMap": true,
        "design": "tabs"
      },
      "children": [
        {
          "id": "b-day-1",
          "type": "itineraryDay",
          "parent": "b-itinerary",
          "content": {
            "title": "Day 1 - Arrival",
            "description": "<p>Arrival and hotel check-in.</p>"
          },
          "children": [
            {
              "id": "b-title-1",
              "type": "title",
              "parent": "b-day-1",
              "content": { "title": "Welcome" }
            },
            {
              "id": "b-text-1",
              "type": "text",
              "parent": "b-day-1",
              "content": { "text": "<p>Meet your guide at the airport.</p>" }
            },
            {
              "id": "b-transport-1",
              "type": "transport",
              "parent": "b-day-1",
              "content": {
                "title": "Private transfer",
                "description": "<p>Airport → Hotel</p>"
              }
            }
          ]
        },
        {
          "id": "b-day-2",
          "type": "itineraryDay",
          "parent": "b-itinerary",
          "content": {
            "title": "Day 2 - City highlights"
          },
          "children": [
            {
              "id": "b-activity-1",
              "type": "activity",
              "parent": "b-day-2",
              "content": {
                "title": "Guided city tour",
                "description": "<p>Walking tour of the historic center.</p>"
              }
            },
            {
              "id": "b-map-1",
              "type": "map",
              "parent": "b-day-2",
              "content": {
                "mapUrl": "https://www.google.com/maps/d/viewer?mid=..."
              }
            }
          ]
        }
      ]
    },
    {
      "id": "b-services-summary",
      "type": "servicesSummary",
      "content": {
        "included": true,
        "includedText": "<ul><li>Hotel</li><li>Transfers</li></ul>",
        "notIncluded": true,
        "notIncludedText": "<ul><li>Travel insurance</li></ul>"
      }
    }
  ]
}
```

### HTML sanitization (important)

Rich text fields are sanitized before rendering.

- `<img>` tags are not allowed.
- `style` attributes are restricted (text-align only).
- Use basic formatting tags (p, headings, lists, links, tables, etc.).


Trip content is represented as a tree of **blocks** under `TripConfig.blocks`.

Key rules:

- Every block has an `id` and a `type`.
- **`id` must be unique within the `TripConfig.blocks` array**.
- The hierarchy is defined with `parent` (parent block id) and `children` (nested blocks).


Important core block types you will commonly use:

- `itinerary` (container) with `itineraryDay` children
- service blocks such as `accomodation`, `transport`, `train`, `cruise`, `info`, `activity`, `flight`
- content blocks such as `text`, `title`, `box`, `dropdown`
- media blocks such as `map`, `video`, `file`


### HTML / Markdown content

Some block fields accept **HTML or markdown-formatted text** (for example `text.content.text`, and other block descriptions).
When integrating, treat these fields as rich text.

### Trips

Trips are the main entities in the MOGU platform. A trip represents a travel itinerary with all its details, configurations, and associated travelers.

**Key operations:**

- Create and manage trips
- Configure trip settings and branding
- Manage trip visibility (public/private)
- Track trip visualizations


### Catalogs

Catalogs are collections of trips that can be organized and shared. They allow you to group related trips for easier management and presentation.

**Key operations:**

- Create and organize catalogs
- Add/remove trips from catalogs
- Make catalogs publicly accessible
- Filter and search catalog trips


## API Features

### Versioning

The API is currently at version `1.0.0`. The version is specified in the OpenAPI specification and can be verified through the `/status` endpoint.

**Current version:** `1.0.0`

We follow semantic versioning (SemVer) principles:

- **Major version** changes indicate breaking changes
- **Minor version** changes add functionality in a backward-compatible manner
- **Patch version** changes are for backward-compatible bug fixes


When breaking changes are introduced, we will communicate them in advance through our changelog and support channels.

### Pagination

List endpoints support pagination to handle large datasets efficiently:


```bash
GET /trips?page=1&pageSize=20
```

**Parameters:**

- `page`: Page number (starts at 1)
- `pageSize`: Number of items per page (default: 20, max: 100)


**Response format:**


```json
{
  "data": [...],
  "page": 1,
  "pageSize": 20,
  "totalCount": 150,
  "totalPages": 8
}
```

### Filtering

Apply filters to narrow down results using JSON syntax:


```bash
GET /trips?filters=[{"field":"duration","operator":"gte","value":5}]
```

**Supported operators:**

- `eq`: Equal to
- `neq`: Not equal to
- `gt`: Greater than
- `gte`: Greater than or equal to
- `lt`: Less than
- `lte`: Less than or equal to
- `in`: In array
- `contains`: Contains value


### Searching

Search across multiple fields using JSON syntax:


```bash
GET /trips?search={"fields":["title","code"],"term":"Paris"}
```

### Sorting

Sort results by any field:


```bash
GET /trips?orderBy={"field":"createdAt","direction":"desc"}
```

**Directions:**

- `asc`: Ascending order
- `desc`: Descending order


## Error Handling

The API uses standard HTTP status codes to indicate success or failure:

### Success Codes

- `200 OK`: Request succeeded
- `201 Created`: Resource created successfully


### Client Error Codes

- `400 Bad Request`: Invalid request parameters or body
- `401 Unauthorized`: Missing or invalid authentication token
- `403 Forbidden`: Insufficient permissions
- `404 Not Found`: Resource not found
- `429 Too Many Requests`: Rate limit exceeded


### Server Error Codes

- `500 Internal Server Error`: Server-side error
- `503 Service Unavailable`: Service temporarily unavailable


### Error Response Format


```json
{
  "errors": {
    "title": ["Title is required"],
    "duration": ["Duration must be a positive number"]
  }
}
```

## Support

Need help? We're here for you!

- **Email**: [support@moguplatform.com](mailto:support@moguplatform.com)
- **Help Center**: [https://help.moguplatform.com](https://help.moguplatform.com)


## Terms of Service

By using the MOGU Public API, you agree to our [Terms of Service](https://moguplatform.com/terms) and [Privacy Policy](https://moguplatform.com/privacy).

**Ready to get started?** Check out our [API Reference](/openapi) for detailed endpoint documentation.