DEVELOPER · GUIDE

Integration guide

A step-by-step guide for partners integrating the plott LIFE Open API.

PHASE 01 · Start

From API key issuance to dev setup

STEP 01

Add app & get API keys

To call the Open API, create an app and get a Client ID and Client Secret.

Create an app

  1. App screen Fill out the application form.
  2. Enter service name, English name (channel code), and service URL, then submit.
  3. After ops review, a private channel is created and you'll get the result by email. Once approved, create API keys on the app detail page.

Issue API client

  1. App details On the API client section, [Add client] click
  2. Enter Client ID (free, up to 100 chars) and select scopes.
  3. Shown immediately after creation Save the Client Secret immediately in a safe place This value won't be shown again.

Scopes

  • buildingUnit:readBUILDING_UNIT_READView rooms
  • buildingUnit:writeBUILDING_UNIT_WRITECreate/Edit room mapping
  • booking:readBOOKING_READView bookings
  • booking:writeBOOKING_WRITECreate/Edit bookings
  • contract:readCONTRACT_READView contracts
  • contract:writeCONTRACT_WRITECreate/Edit contracts (Method B)
  • user:writeUSER_WRITECreate users (Method A · login integration)
  • userLoginTicket:writeUSER_LOGIN_TICKET_WRITEIssue login ticket (Method A · login integration)
  • chat:readCHAT_READView chats
  • chat:writeCHAT_WRITECreate/Send chats

Result

With the Client ID and Client Secret,Authorization: Basic … they are used in the request header for all API requests.

STEP 02

Register test room & set channel mapping

To register contracts/reservations via API, create a test room and set channel mapping.

Procedure

  1. Host screen Register a new room.
  2. Channel mapping screen Select the registered room and set room-level and unit-level mappings. Room-level mapping is optional, but unit-level mapping is required to register contracts via the Open API. Set the external property ID to the room ID used by that channel.
  3. To view the registered room on the guest page, /rooms/{roomId}visit the guest page.

Note

External property ID example https://www.airbnb.co.kr/rooms/1252576808547167623 1252576808547167623

STEP 03

Explore docs with MCP

Register plott LIFE Open API's MCP server with AI coding agents (Claude Code, Cursor, etc.) so agents can read the API spec immediately and speed up integration.

Register with Claude Code

claude mcp add --transport http plott-life-partner \
  https://life.plott.co.kr/api/open/mcp \
  --header "Authorization: Basic {base64(clientId:clientSecret)}"

{base64(clientId:clientSecret)} is the Client ID and Secret issued in Step 01 clientId:clientSecret concatenated with a colon and base64-encoded.

Example: AI coding agent exploring plott LIFE Open API after registering an MCP serverExample: agent writing integration code from API specs fetched via MCP

PHASE 02 · Integration

Select an integration method and implement/operate it

IMPLEMENT & OPERATE

Choose integration method

Two integration methods depending on how much your service handles Method A · Login integration One is the handoff method: integrate only listings and login, handing off contracts/payments to plott LIFE, Method B · Contract integration the other integrates contract APIs so sales finish inside the partner app. Select a tab below to view its implementation and operation steps.

Select a method based on how much your service handles. Below shows implementation and operation steps for the selected method. Common steps (app request & key, test room/channel mapping, MCP) and the public channel steps are identical for both.

Method A · Login integration (Handoff)

Show only listings in your app and hand off contracts/payments to plott LIFE. Pre-create users and issue a login ticket (SSO) so users land on plott LIFE already logged in. Required scopes are user:write, userLoginTicket:write are.

IMPLEMENT · Login integration

Implementation

1. Room list integration

This is where your service queries plott LIFE listings and shows them to users.

GET /open/v1/building-unit-type Fetch the room list via the API, GET /open/v1/building-unit-type/{id} and fetch single-room details via the API. The list uses page·size pagination, default size is 20. Infinite scroll uses the response's totalItems field to determine whether more items exist.

  • pageOptionalPage number starting at 0
  • sizeOptional · default 20Items per page
  • operationStatusRecommendedWhen showing to users, query only PUBLISHED (Operating).
const res = await fetch(
  'https://life.plott.co.kr/api/open/v1/building-unit-type?page=0&size=20&operationStatus=PUBLISHED',
  { headers: { Authorization: `Basic ${credentials}` } },
);
const { items, totalItems, totalPages } = await res.json();

Note

Pricing rules (pro-rated rent, discounts, maintenance fee, deposit, service fee) and storage method (direct call / mirroring) are the same for both methods. See detailed formulas and examples in API docs See in API docs.

2. User creation integration

POST /open/v1/user Create your users as plott LIFE members. externalUserId Idempotent using the partner's user identifier; returns the existing member ID if already created.

  • externalUserIdRequiredPartner user identifier (idempotency key)
  • emailRequiredUser email
  • firstName / lastNameRequiredFirst name / Last name
  • phoneCode / phoneNumberRequiredCountry code / phone number (e.g., 82 / 1012345678)
  • countryCodeOptionalCountry code (e.g., KR)
const res = await fetch('https://life.plott.co.kr/api/open/v1/user', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Basic ${credentials}`,
  },
  body: JSON.stringify({
    externalUserId: 'partner-user-001',
    email: 'user@example.com',
    firstName: '길동',
    lastName: '홍',
    phoneCode: '82',
    phoneNumber: '1012345678',
    countryCode: 'KR',
  }),
});

const { id } = await res.json(); // 플라트라이프 회원 ID

3. Login ticket issuance

POST /open/v1/userLoginTicket Issue a one-time login ticket for the member. The request should include userId (the member creation response's id) or externalUserId include one of them. The returned ticket is Valid for 5 minutes and single-use so issue it right before redirecting the user to plott LIFE.

  • userIdChoose one: userId or externalUserIdplott LIFE member ID (id from user creation response)
  • externalUserIdChoose one: userId or externalUserIdPartner service's user identifier
const res = await fetch(
  'https://life.plott.co.kr/api/open/v1/userLoginTicket',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Basic ${credentials}`,
    },
    body: JSON.stringify({ externalUserId: 'partner-user-001' }),
  },
);

const { ticket } = await res.json(); // 5분 TTL · 1회용

Tip

This method doesn't integrate contract APIs. Contracts and payments happen on plott LIFE, so implement only listing display and login integration.

OPERATE · Login integration

Operation

  1. Show listings in your service.
  2. When a user selects a listing, issue that member's login ticket (If no member, create one and then issue.)
  3. Include the issued ticket with https://life.plott.co.kr/rooms/{id}?ticket=<ticket> and redirect to plott LIFE. plott LIFE will exchange the ticket and auto-login log them in.
  4. Contracts and payments proceed on plott LIFE. Your service doesn't handle the contract flow.

Ticket lifespan

Login tickets are valid for 5 minutes and single-use. Issue right before redirect and deliver without delay.

PHASE 03 · Public Channel

After verification, switch to the public channel to begin full operation

PUBLIC CHANNEL

Request public channel review

If integration is verified in a private channel, request public channel access to reach all hosts' listings. This step is the same for both methods.

How to request

  1. App details On the app's status card [Request public channel access] Click it.
  2. Our operations team will review and email the result.
  3. If rejected, check the reason, fix the issue, and reapply.

PUBLIC CHANNEL

Public channel activation

When public, you can query all plott LIFE hosts' listings via Open API. Pick listings to handle, set channel mapping, and operate using your chosen integration flow.

View all listings

const res = await fetch(
  'https://life.plott.co.kr/api/open/v1/building-unit-type?page=0&size=20',
  { headers: { Authorization: `Basic ${credentials}` } },
);
const { items, totalItems, totalPages } = await res.json();

Default behavior

By default, Operating Only rooms with 'Operating' status are shown. To view only your listings, isMine=true you can request it.

REFERENCE · Common items

Notes on authentication, errors, and Rate Limit

COMMON

Authentication

All Open API requests use HTTP Basic auth. App details obtained from Client ID and Client Secret join with a colon and encode in base64 Authorization include it in the header.

const credentials = Buffer.from(
  `${process.env.CLIENT_ID}:${process.env.CLIENT_SECRET}`,
).toString('base64');

const res = await fetch('https://life.plott.co.kr/api/open/v1/contract-channel', {
  headers: {
    Authorization: `Basic ${credentials}`,
  },
});

Client Secret security

Client Secret is shown only once when issued. If it's lost or exposed, App details delete the client immediately and issue a new one.

COMMON

Error responses

When an error occurs, RFC 9457 Problem Detail it responds in the following format.

{
  "type": "about:blank",
  "title": "Not Found",
  "status": 404,
  "detail": "예약 매핑을 찾을 수 없습니다.",
  "instance": "/open/v1/booking"
}
  • typeError type URI
  • titleHTTP status text
  • statusHTTP status code
  • detailError detail
  • instanceRequest path

COMMON

Rate Limit

To ensure stability and fair use, the Open API enforces rate limits.

  • ScopeAll endpoints under /open/**
  • Limit unitHost account
  • Limit300 requests per minute
  • Refill methodGreedy refill: ~5 tokens refilled every second.

Rate-limit exceeded response

Requests exceeding the limit are rejected immediately, 429 Too Many Requests and an error response is returned.

Recommended client handling

  • 429 When you receive the response, do not retry immediately, wait a while before retrying.
  • On average about 200ms intervals is stable.
  • For batch jobs needing many requests quickly, space calls or use exponential backoff.

Tip

Under normal usage, 429 if it happens often, contact us to discuss raising your limit.

DOCUMENTATION

View full endpoint specs

See request/response schemas, parameters, and error codes in one place.

Go to API docs