Files
MemeStudio/API_REFERENCE.md
2026-05-01 08:44:56 +08:00

8.0 KiB

MemeStudio API Reference

Base URL

  • Development: http://localhost:3001/studio
  • Production: https://119.91.211.52/studio

Authentication

All endpoints except /api/auth/* require a valid session cookie:

  • better-auth.session_token (HTTP)
  • __Secure-better-auth.session_token (HTTPS)

Error response if unauthorized: { error: 'Unauthorized' } (401)


Authentication Endpoints

POST /api/auth/sign-in/email

Sign in with email and password.

Request:

{
  "email": "admin@example.com",
  "password": "password123"
}

Response:

{
  "user": {
    "id": "uuid",
    "email": "admin@example.com",
    "name": "Admin",
    "emailVerified": true
  },
  "session": {
    "id": "session_id",
    "expiresAt": "2024-04-14T10:00:00Z",
    "token": "session_token"
  }
}

POST /api/auth/sign-out

Sign out and invalidate session.

Response:

{ "success": true }

Levels API

GET /api/levels

Get all levels, sorted by sortOrder.

Response:

[
  {
    "id": "uuid",
    "imageUrl": "https://bucket.myqcloud.com/mini_game/images/...",
    "answer": "答案文本",
    "hint1": "提示1",
    "hint2": "提示2",
    "hint3": "提示3",
    "sortOrder": 1,
    "createdAt": "2024-04-01T10:00:00Z",
    "updatedAt": "2024-04-01T10:00:00Z"
  }
]

POST /api/levels

Create a new level. sortOrder is auto-calculated as max+1.

Request:

{
  "imageUrl": "https://bucket.myqcloud.com/mini_game/images/...",
  "answer": "答案",
  "hint1": "提示1",
  "hint2": "提示2",
  "hint3": "提示3"
}

Response: Level object (201 Created)

Validation:

  • imageUrl and answer are required
  • Returns 400 if missing required fields

PUT /api/levels

Update a level.

Request:

{
  "id": "uuid",
  "imageUrl": "...",
  "answer": "新答案",
  "hint1": "...",
  "hint2": "...",
  "hint3": "..."
}

Response: Updated Level object

Validation:

  • id is required
  • Other fields are optional (only provided fields are updated)

DELETE /api/levels?id=

Delete a level.

Response:

{ "success": true }

Levels Reorder API

PUT /api/levels/reorder

Batch update sort order for multiple levels (atomic transaction).

Request:

{
  "orders": [
    { "id": "uuid1", "sortOrder": 1 },
    { "id": "uuid2", "sortOrder": 2 },
    { "id": "uuid3", "sortOrder": 3 }
  ]
}

Response:

{ "success": true }

Validation:

  • orders must be an array of objects with id and sortOrder

Admin Users API

GET /api/users

Get all admin users, sorted by createdAt DESC.

Response:

[
  {
    "id": "uuid",
    "email": "admin@example.com",
    "emailVerified": true,
    "name": "Admin Name",
    "image": null,
    "createdAt": "2024-04-01T10:00:00Z",
    "updatedAt": "2024-04-01T10:00:00Z"
  }
]

POST /api/users

Create a new admin user.

Request:

{
  "email": "newadmin@example.com",
  "password": "securepassword123",
  "name": "New Admin"
}

Response: User object (201 Created)

Validation:

  • email and password are required
  • email must be unique (returns 400 if already exists: "该邮箱已被注册")
  • Password is automatically hashed using Better Auth's hashPassword

PUT /api/users

Update a user.

Request:

{
  "id": "uuid",
  "email": "newemail@example.com",
  "password": "newpassword123",
  "name": "Updated Name"
}

Response: Updated User object

Validation:

  • id is required
  • Email must be unique across other users (returns 400 if taken: "该邮箱已被其他用户使用")
  • If password is provided, it's hashed and Account record is updated

DELETE /api/users?id=

Delete a user.

Response:

{ "success": true }

Validation:

  • id is required
  • Cannot delete yourself (returns 400: "不能删除自己的账户")
  • Cascading delete removes all sessions and accounts

WeChat Users API

GET /api/wx-users?search=&page=<1>&limit=<20>

Get WeChat users with pagination and search.

Query Parameters:

  • search (optional): Search in nickname or openid (contains search)
  • page (optional, default 1): Page number
  • limit (optional, default 20): Items per page

Response:

{
  "users": [
    {
      "id": "uuid",
      "openid": "oABCDEF123456",
      "nickname": "用户昵称",
      "avatarUrl": "https://...",
      "points": 100,
      "createdAt": "2024-04-01T10:00:00Z",
      "updatedAt": "2024-04-01T10:00:00Z"
    }
  ],
  "meta": {
    "total": 150,
    "page": 1,
    "limit": 20,
    "totalPages": 8
  }
}

GET /api/wx-users/

Get a specific WeChat user with their level progress.

Response:

{
  "id": "uuid",
  "openid": "oABCDEF123456",
  "nickname": "用户昵称",
  "avatarUrl": "https://...",
  "points": 100,
  "sessionKey": "...",
  "createdAt": "2024-04-01T10:00:00Z",
  "updatedAt": "2024-04-01T10:00:00Z",
  "levelProgress": [
    {
      "id": "progress_uuid",
      "userId": "uuid",
      "levelId": "uuid",
      "completedAt": "2024-04-02T15:30:00Z",
      "level": {
        "id": "uuid",
        "answer": "答案"
      }
    }
  ]
}

DELETE /api/wx-users/level-progress

Delete multiple level progress records (batch).

Request:

{
  "ids": [
    "progress_uuid1",
    "progress_uuid2",
    "progress_uuid3"
  ]
}

Response:

{ "deleted": 3 }

Validation:

  • ids must be a non-empty array of strings
  • Returns 400 if validation fails

Tencent COS API

GET /api/cos/temp-key

Get temporary credentials for uploading images to COS.

Response:

{
  "credentials": {
    "tmpSecretId": "AKIA...",
    "tmpSecretKey": "...",
    "sessionToken": "..."
  },
  "startTime": 1712000000,
  "expiredTime": 1712001800,
  "bucket": "mybucket-1234567890",
  "region": "ap-guangzhou"
}

Details:

  • Credentials are valid for 30 minutes (1800 seconds)
  • Limited to upload to mini_game/images/* directory
  • Use returned bucket and region for upload configuration
  • Browser should upload directly to COS using these credentials (S3-compatible API)

Error Handling

Standard Error Response

{
  "error": "Error message"
}

HTTP Status Codes

  • 200: Success
  • 201: Created
  • 400: Bad Request (validation error)
  • 401: Unauthorized (no session)
  • 404: Not Found (resource doesn't exist)
  • 500: Server Error

Implementation Notes

Session Validation Pattern

const session = await auth.api.getSession({ headers: request.headers })
if (!session) {
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

Pagination Pattern

  • skip = (page - 1) * limit
  • totalPages = Math.ceil(total / limit)

Transaction Pattern (Multi-step operations)

await prisma.$transaction(async (tx) => {
  // Multiple database operations in atomic transaction
})

Error Handling Pattern

All endpoints log errors to console and return appropriate status codes.


Testing with cURL

Sign In

curl -X POST http://localhost:3001/studio/api/auth/sign-in/email \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"admin123456"}' \
  -c cookies.txt
curl http://localhost:3001/studio/api/levels \
  -b cookies.txt

Create Level

curl -X POST http://localhost:3001/studio/api/levels \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "imageUrl":"https://bucket.myqcloud.com/mini_game/images/test.jpg",
    "answer":"答案",
    "hint1":"提示1",
    "hint2":"提示2",
    "hint3":"提示3"
  }'

Environment Variables Required for API

DATABASE_URL=mysql://user:pass@host:port/dbname
BETTER_AUTH_SECRET=<32+ chars>
BETTER_AUTH_URL=http://localhost:3001
NEXT_PUBLIC_APP_URL=http://localhost:3001
NEXT_PUBLIC_BASE_PATH=/studio
COS_SECRET_ID=<tencent secret>
COS_SECRET_KEY=<tencent secret>
COS_BUCKET=bucket-name
COS_REGION=ap-guangzhou
COS_APPID=<tencent app id>