Tino Developers
View .md

Getting started with TinoPage Builder

TinoPage Builder builds websites for businesses with AI: the customer describes the business, the AI picks a template and writes the content, and the customer keeps editing in the TinoPage Builder editor. Websites take contacts and orders and run on custom domains. The service API lets your app read limits, create websites with AI, publish, pause and delete websites, add custom domains, read contacts and orders, and open TinoPage Builder with a one-time sign-in ticket.

Updated: 2026-10-26. Sources: Tino's TinoPage Builder module and the TinoPage Builder API.

Calling the API

ItemValue
Addresshttps://api.tino.vn/service/<service id>/builder/…
AuthenticationAuthorization: Bearer <token>: the TinoPage Builder service owner's sign-in token; through /v1: an OAuth app token or personal API token with a builder:* scope
BodyJSON, Content-Type: application/json
Each routethe TinoPage Builder section of the API Reference
  • Only the parameters listed on each route are relayed. Tino checks shapes before calling TinoPage Builder: a website ID that is not a UUID, a malformed domain, or an unknown query or body field answers 400 INVALID_REQUEST with details.field naming the field.
  • Website IDs in paths are UUIDs; domains in paths are lower case.
  • Editing website content (pages, blocks, images, items) and handling contacts and orders happen in TinoPage Builder: open it with a sign-in ticket.

Since 2026-10-27 the TinoPage Builder routes can also be called through the /v1 gateway: https://api.tino.vn/v1/service/<service id>/builder/… with an OAuth app token (tinoat_, scopes builder:read, builder:write) or a personal API token (tinopat_), with the same bodies and answers. Only the sign-in ticket (POST …/builder/login) is not exposed through /v1: it needs the sign-in token.

The sign-in token is the token customers use in the tino.vn client area; the SDK gets one by signing in with an OTP code:

from tino_userapi import TinoClient

client = TinoClient()
client.request_login_otp("you@example.com")
client.verify_login_otp("you@example.com", input("OTP code: "))
print(client.request("GET", "/service/100003/builder/overview"))

100003 is the TinoPage Builder service ID: see below for how to find it.

Find the TinoPage Builder service

Each Tino customer has one TinoPage Builder account, bound to the purchased TinoPage Builder service.

  1. Take candidates from List services (product_type) or Service details (ptype): the value tinobuilderpanel. For a service without it, look at acc_module: TinoPage Builder. Compare case-insensitively, ignoring spaces, _ and -.
  2. Call Account overview (GET /service/<id>/builder/overview):
ResultMeaning
200the customer's TinoPage Builder service: call the other routes with this ID
404 SERVICE_NOT_LINKEDthe TinoPage Builder account is bound to another service of the customer: try the next service
404 SERVICE_NOT_FOUND, invalid methodnot a TinoPage Builder service of the signed-in account
404 ACCOUNT_NOT_FOUNDno TinoPage Builder account for the service yet: contact Tino support

Service limits

TinoPage Builder is not sold as fixed plans: limits follow the purchased service and live in config.effective of Account overview. Read them from the API instead of hard-coding them: the numbers can change with the service. -1 means unlimited.

KeyApplies toMeaning
sitesaccountwebsites (not deleted, drafts included)
pages_per_siteeach websitepages
items_per_siteeach websiteitems
domains_per_siteeach websitecustom domains
ai_generations_dailyeach websiteAI content creations and edits in 24 hours
ai_chat_dailyeach websitemessages to the AI assistant in 24 hours
ai_images_dailyeach websiteAI images in 24 hours
  • Usage: usage of Account overview (sites, sites_paused, sites_published) and pages, items, domains (used, limit) of each website.
  • No websites left: creating a website answers 409 LIMIT_EXCEEDED with details.key sites; no domains left: domains_per_site.
  • After limits go down or the service is terminated, the account keeps its oldest websites running up to sites; the others are paused by the system (paused: true, paused_reason: over_limit): the public page says the website is paused and takes no contacts or orders. Raising the limit or deleting websites brings paused websites back, oldest first. Pages, items and domains over a lowered limit are not deleted; only new ones are blocked.
  • Suspended service: read only. Writes answer 403 ACCOUNT_SUSPENDED; GET and sign-in tickets still work (read-only access). Terminated service: writes and sign-in tickets answer 403 ACCOUNT_TERMINATED.

Create a website with AI

Create a website with AI takes intake: the business details the AI uses to pick a template and write the content.

FieldRequiredMax (characters)Notes
business_nameyes120business name
industryyes80line of business, e.g. bakery, spa, coffee shop
phoneyes20Vietnamese number: 0, 84 or +84, then 9 mobile digits (starting 3, 5, 7, 8, 9) or 10 landline digits (starting 2); spaces, dots, dashes and parentheses allowed
address—200address
city—80province or city
services—300main services or products
hours—100opening hours
zalo—100Zalo phone number or link
email—120contact email
  • A field outside the table, a field that is not a string, or one that is too long answers 400 INVALID_REQUEST (details.field: intake or intake.<field>). A missing required field or an invalid phone or email answers 422 VALIDATION_FAILED with details per intake.<field> and a reason in Vietnamese.
  • Creation runs in the background for 1–5 minutes: the create call answers HTTP 202 with state: running. Poll Website creation progress every few seconds until state is done (site_id is the new website) or failed (message is the reason in Vietnamese).
  • One creation per account at a time: a second one answers 409 CREATION_IN_PROGRESS. AI creation paused: 503 AI_UNAVAILABLE.
  • The result is kept for 1 hour; after that (or after a server restart) progress answers idle, and the created website stays in List websites.
  • Progress may also carry step (queued, design, write, images, build) and, once done, mode (design, merge): for showing progress only; do not branch on them.

Publish, pause and delete websites

StateMeaning
status: draftnot published: a new website, or one paused with Pause a website
status: publishedpublished, running on host (custom domain) or the preview link preview_url
paused: truepaused by the system (paused_reason: over_limit: the account is over its website count), overrides status
  • Publish a website publishes the latest version, which also reopens a paused website. A paused website answers 409 SITE_PAUSED: delete another website or raise the website count.
  • Pause a website takes the website off the web with its content kept.
  • Delete a website moves it to the trash (Tino can restore it on request through support), removes its custom domains and frees one of the account's websites.
  • Website details has todo: contacts not yet called back (leads_new) and orders not yet confirmed (orders_new).

Custom domains

  1. Publish the website first: an unpublished website answers 409 SITE_NOT_PUBLISHED.
  2. Add a custom domain with hostname (e.g. example.vn, banhang.example.vn): it answers 201 with the domain at status: pending and dns, the records the customer must set where the domain's DNS is managed.
  3. The customer sets the records: CNAME to dns_target (names @ and www for an apex domain, the sub-label for a subdomain) and TXT _tino-verify (value tino-site-verify=…) proving ownership. Record names are relative to the apex domain. Take dns_target and the TXT value from the API; do not hard-code them.
  4. TinoPage Builder rechecks pending domains on a schedule (next_check_at); Check DNS again checks now. With both CNAME and TXT in place status turns active and an HTTPS certificate is issued automatically (ssl_status: pending, active, error); www redirects to the apex domain.
  • cname_ok and txt_ok are the latest check's results; error says what is missing (in Vietnamese) and is empty once it passes. checked_at is 0001-01-01T00:00:00Z before the first check.
  • owner_verified: true: domain ownership is already confirmed, no TXT needed (dns only has the CNAME records).
  • Automatic checks stop after 14 failures (about 10 days); error says so, and Check DNS again tries once more.
  • No domains left for the website: 409 LIMIT_EXCEEDED (details.key: domains_per_site); domain used by another website: 409 DOMAIN_TAKEN; not a domain: 422 VALIDATION_FAILED (details.hostname).

Contacts and orders

Contacts and orders is read only: kind=lead (default) is a contact from a website form, kind=order an order; newest first, paged with page, per_page (default 20, at most 50) and meta.

statusMeaningFilterable
moinewyes
da_lien_hecontacted (contacts)yes
xac_nhanconfirmedyes
dang_lamin preparation (food orders)no
san_sangready (food orders)no
dang_giaoout for deliveryyes
hoan_tatcompletedyes
huycancelledyes
  • Contact: id, kind, name, phone, payload (the form content, keys depend on the website's form), source_page, status, created_at.
  • Order: id, code, name, phone, address, note, items (name, option, qty, subtotal), shipping, total (null when the website shows no price), payment (COD, Chuyển khoản (bank transfer) or other text), status, status_label (Vietnamese label), created_at, sheet_error (error sending the order to Google Sheets, empty when none).
  • Unknown status: show status_label when present, otherwise status as is.

Sign-in tickets

A one-time sign-in ticket opens TinoPage Builder on the service's account without the customer signing in again:

  • target: me (default) opens the dashboard; target: editor opens the editor of site_id. Without site_id: the account's oldest website (the dashboard when the account has no website yet).
  • It answers 201 {url, expires_at}: url is https on the TinoPage Builder server, single use, valid for 120 seconds. Open it right away in the service owner's browser; do not store it or send it through another channel. Chat apps that preview the link do not use up the ticket.
  • login_url of Account overview is not a ticket: it opens the TinoPage Builder sign-in page with a Tino account, and the customer signs in.

Safe retries

Every write (create, publish, pause, delete a website; add, check, remove a domain; sign-in ticket) takes idempotency_key (8–64 characters A-Za-z0-9._:-); with DELETE, send it in the query. Make one key per customer click:

  • If the connection drops midway, resend the same key with the same content: you get the earlier result and the command does not run twice. TinoPage Builder remembers keys for 24 hours; an earlier 5xx is not remembered, so a resend runs for real.
  • The same key with different content, or while the earlier call is still running: 409 IDEMPOTENCY_CONFLICT. Reload the data before trying with a new key.
  • Without a key, every call is a new command.

Responses

Success: {"data": …}, where data is TinoPage Builder's answer; lists add meta (page, per_page, total, last_page). HTTP 200, 201 when adding a domain or issuing a sign-in ticket, 202 when a website creation is accepted. Times are RFC 3339; website IDs are UUIDs.

Errors

{ "error": ["LIMIT_EXCEEDED"], "message": "Tài khoản đã dùng hết số website được phép. Nâng cấu hình dịch vụ trên Tino để tạo thêm website.", "details": { "key": "sites" }, "request_id": "…" }

Branch on error[0], not on message (a Vietnamese sentence that may change). Codes are upper case; invalid method (the route does not exist for this service) only has error. When reporting an error to Tino, include request_id.

HTTPCodeMeaning, what to do
400INVALID_REQUESTa website ID, domain, query, body or idempotency_key has the wrong shape, details.field names the field: a programming error in the app
401unauthorized, invalid_token, token_expiredthe sign-in token is wrong or expired: refresh it
403ACCOUNT_SUSPENDEDthe service is suspended: writes are blocked, GET still works
403ACCOUNT_TERMINATEDthe service is terminated: writes and sign-in tickets are blocked
404SERVICE_NOT_FOUND, invalid methodnot a TinoPage Builder service of the signed-in account: go back to the service list
404SERVICE_NOT_LINKEDthe TinoPage Builder account is bound to another service: find the service again (Find the TinoPage Builder service)
404ACCOUNT_NOT_FOUNDno TinoPage Builder account yet: contact Tino support
404RESOURCE_NOT_FOUNDthe website or domain is not in the account (or was deleted): reload the list
409LIMIT_EXCEEDEDa limit of the purchased service is used up, details.key names it: delete something or upgrade the service
409CREATION_IN_PROGRESSa website creation is running: wait for it to finish
409SITE_PAUSEDthe website is paused by the system for being over the website count: it cannot be published yet
409SITE_NOT_PUBLISHEDpublish the website before adding a custom domain
409DOMAIN_TAKENthe domain is used by another website
409INVALID_ACTIONnot possible in the current state, message says why: reload and retry
409IDEMPOTENCY_CONFLICTthe same idempotency_key with different content, or the earlier call is still running
422VALIDATION_FAILEDinvalid data: show the error under the field named in details (intake.<field>, hostname, kind, status, target)
429RATE_LIMITEDtoo fast: retry after a few seconds
503AI_UNAVAILABLEAI website creation is paused: retry later
500, 502, 503INTERNAL_ERROR, NETWORK_ERROR, INVALID_RESPONSE, NOT_CONFIGUREDthe connection between Tino and TinoPage Builder is interrupted: a Tino-side error, not a token problem. Do not sign out; retry later