{"id":4613,"date":"2026-06-20T08:11:23","date_gmt":"2026-06-20T08:11:23","guid":{"rendered":"https:\/\/www.centralyachtagent.com\/welcome\/?page_id=4613"},"modified":"2026-06-20T08:21:55","modified_gmt":"2026-06-20T08:21:55","slug":"api-documentation","status":"publish","type":"page","link":"https:\/\/www.centralyachtagent.com\/welcome\/api-documentation\/","title":{"rendered":"API Documentation"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4613\" class=\"elementor elementor-4613\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f085580 e-flex e-con-boxed e-con e-parent\" data-id=\"f085580\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4c37328 e-flex e-con-boxed e-con e-parent\" data-id=\"4c37328\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f0a1e96 elementor-widget elementor-widget-html\" data-id=\"f0a1e96\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!--\r\n  Central Yacht Agent \u2014 Public API Guide\r\n  Self-contained HTML for WordPress.\r\n\r\n  HOW TO USE:\r\n  1. In WordPress, create\/edit a Page.\r\n  2. Add a \"Custom HTML\" block (or switch the editor to \"Code editor\").\r\n  3. Paste EVERYTHING below this comment (from the opening <div ...> to the closing <\/script>).\r\n  4. Publish. No Bootstrap, jQuery or external CSS is required \u2014 it's all inline and\r\n     scoped under .cya-api-doc so it won't fight your theme styles.\r\n-->\r\n\r\n<div class=\"cya-api-doc\">\r\n  <style>\r\n    .cya-api-doc{--cya-primary:#2f5fe0;--cya-text:#1f2933;--cya-muted:#6b7280;--cya-border:#e5e7eb;--cya-light:#f3f4f6;color:var(--cya-text);font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif;line-height:1.6;font-size:15px;max-width:1100px;margin:0 auto}\r\n    .cya-api-doc *{box-sizing:border-box}\r\n    .cya-api-doc h1,.cya-api-doc h2,.cya-api-doc h3,.cya-api-doc h4,.cya-api-doc h5,.cya-api-doc h6{color:var(--cya-text);margin:0 0 .5rem;line-height:1.25}\r\n    .cya-api-doc a{color:var(--cya-primary);text-decoration:none}\r\n    .cya-api-doc a:hover{text-decoration:underline}\r\n    .cya-api-doc p{margin:0 0 1rem}\r\n    .cya-api-doc .cya-layout{display:flex;gap:1.5rem;align-items:flex-start;flex-wrap:wrap}\r\n    .cya-api-doc .cya-main{flex:1 1 640px;min-width:0}\r\n    .cya-api-doc .cya-side{flex:0 0 260px;position:sticky;top:1rem}\r\n    @media(max-width:900px){.cya-api-doc .cya-side{position:static;flex-basis:100%;order:-1}}\r\n    .cya-api-doc .cya-card{background:#fff;border:1px solid var(--cya-border);border-radius:.6rem;margin-bottom:1.25rem;overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.04)}\r\n    .cya-api-doc .cya-card-head{padding:.85rem 1.15rem;border-bottom:1px solid var(--cya-border);background:#fafafa}\r\n    .cya-api-doc .cya-card-head h5{margin:0;font-size:1.02rem}\r\n    .cya-api-doc .cya-card-body{padding:1.15rem}\r\n    .cya-api-doc code{background:var(--cya-light);color:#b03a5b;padding:.12rem .35rem;border-radius:.25rem;font-family:Menlo,Consolas,monospace;font-size:.84em;word-break:break-word}\r\n    .cya-api-doc pre{background:#0d1117;color:#e6edf3;padding:1rem 1.1rem;border-radius:.5rem;font-size:.82rem;line-height:1.55;overflow:auto;margin:0}\r\n    .cya-api-doc pre code{background:transparent;color:inherit;padding:0;white-space:pre;font-size:inherit}\r\n    .cya-api-doc .cya-code{position:relative;margin-bottom:1rem}\r\n    .cya-api-doc .cya-copy{position:absolute;top:.5rem;right:.5rem;font-size:.7rem;padding:.2rem .55rem;border:1px solid rgba(255,255,255,.25);background:rgba(255,255,255,.1);color:#fff;border-radius:.3rem;cursor:pointer;opacity:.85}\r\n    .cya-api-doc .cya-copy:hover{opacity:1}\r\n    .cya-api-doc table{width:100%;border-collapse:collapse;margin-bottom:1rem;font-size:.9rem}\r\n    .cya-api-doc table.cya-auto{width:auto}\r\n    .cya-api-doc th,.cya-api-doc td{border:1px solid var(--cya-border);padding:.5rem .65rem;text-align:left;vertical-align:middle}\r\n    .cya-api-doc thead th{background:var(--cya-light);font-weight:600}\r\n    .cya-api-doc .cya-table-wrap{overflow-x:auto}\r\n    .cya-api-doc blockquote{border-left:3px solid var(--cya-primary);background:var(--cya-light);padding:.65rem .9rem;border-radius:.35rem;margin:0 0 1rem;font-size:.92rem}\r\n    .cya-api-doc ul{margin:0 0 1rem;padding-left:1.3rem}\r\n    .cya-api-doc li{margin-bottom:.3rem}\r\n    .cya-api-doc .cya-alert{display:flex;gap:.6rem;padding:.85rem 1rem;border-radius:.5rem;margin-bottom:1.25rem;font-size:.92rem;align-items:flex-start}\r\n    .cya-api-doc .cya-alert-warn{background:#fff8e6;border:1px solid #f5d57e;color:#7a5b00}\r\n    .cya-api-doc .cya-muted{color:var(--cya-muted)}\r\n    .cya-api-doc .cya-small{font-size:.85rem}\r\n    .cya-api-doc .cya-grid3{display:flex;flex-wrap:wrap;gap:1rem}\r\n    .cya-api-doc .cya-grid3>div{flex:1 1 180px}\r\n    .cya-api-doc .cya-badge{display:inline-block;font-family:Menlo,Consolas,monospace;font-weight:600;font-size:.72rem;padding:.15rem .5rem;border-radius:.3rem;color:#fff;min-width:46px;text-align:center}\r\n    .cya-api-doc .cya-get{background:#198754}\r\n    .cya-api-doc .cya-post{background:#2f5fe0}\r\n    .cya-api-doc .cya-s400{background:#f0ad4e}.cya-api-doc .cya-s403{background:#dc3545}.cya-api-doc .cya-s404{background:#6c757d}.cya-api-doc .cya-s429{background:#f0ad4e}.cya-api-doc .cya-s500{background:#212529}\r\n    .cya-api-doc .cya-tabs{display:flex;flex-wrap:wrap;gap:.25rem;border-bottom:1px solid var(--cya-border);margin-bottom:1rem;list-style:none;padding:0}\r\n    .cya-api-doc .cya-tabs button{border:none;background:none;padding:.5rem .85rem;font-size:.88rem;cursor:pointer;color:var(--cya-muted);border-bottom:2px solid transparent;margin-bottom:-1px}\r\n    .cya-api-doc .cya-tabs button.active{color:var(--cya-primary);border-bottom-color:var(--cya-primary);font-weight:600}\r\n    .cya-api-doc .cya-pane{display:none}\r\n    .cya-api-doc .cya-pane.active{display:block}\r\n    .cya-api-doc .cya-toc a{display:block;padding:.3rem .5rem;border-radius:.35rem;color:var(--cya-text);font-size:.88rem}\r\n    .cya-api-doc .cya-toc a:hover{background:var(--cya-light);text-decoration:none}\r\n    .cya-api-doc .cya-toc hr{border:none;border-top:1px solid var(--cya-border);margin:.5rem 0}\r\n    .cya-api-doc h5[id],.cya-api-doc div[id]{scroll-margin-top:1rem}\r\n  <\/style>\r\n\r\n  <div class=\"cya-alert cya-alert-warn\">\r\n    <strong>\u26a0<\/strong>\r\n    <div>\r\n      <strong>New features are available only in the new API.<\/strong>\r\n      <div style=\"margin-top:.25rem\">\r\n        All the new features \u2014 <strong>Seasons<\/strong>, <strong>Crew Details<\/strong> (images &amp; descriptions),\r\n        <strong>Menu Details<\/strong>, <strong>More videos &amp; more photos<\/strong> (over 20),\r\n        <strong>new Amenities &amp; Watersports<\/strong>, and every other new feature \u2014\r\n        are available <strong>only in the new API<\/strong>, <u>not<\/u> in the legacy API.\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"cya-layout\">\r\n    <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Main content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n    <div class=\"cya-main\">\r\n\r\n      <!-- Intro -->\r\n      <div class=\"cya-card\" id=\"top\">\r\n        <div class=\"cya-card-body\">\r\n          <h4 style=\"font-size:1.3rem;margin-bottom:.25rem\">Central Yacht Agent \u2014 Public API Guide<\/h4>\r\n          <p class=\"cya-muted\" style=\"margin-bottom:1rem\">Integrate yacht data (listings, details, seasons, availability) into your website or app.<\/p>\r\n          <p style=\"margin-bottom:1rem\">\r\n            <a href=\"https:\/\/api.centralyachtagent.com\/public\/documentation\" target=\"_blank\" rel=\"noopener\">\u2197 Interactive Docs<\/a>\r\n          <\/p>\r\n          <hr style=\"border:none;border-top:1px solid var(--cya-border);margin:0 0 1rem\">\r\n          <div class=\"cya-grid3\">\r\n            <div>\r\n              <span class=\"cya-muted cya-small\" style=\"display:block\">Base URL<\/span>\r\n              <code>https:\/\/api.centralyachtagent.com\/public\/api\/v1<\/code>\r\n            <\/div>\r\n            <div>\r\n              <span class=\"cya-muted cya-small\" style=\"display:block\">Format<\/span>\r\n              <span>JSON over HTTPS<\/span>\r\n            <\/div>\r\n            <div>\r\n              <span class=\"cya-muted cya-small\" style=\"display:block\">Interactive docs<\/span>\r\n              <a href=\"https:\/\/api.centralyachtagent.com\/public\/documentation\" target=\"_blank\" rel=\"noopener\">\/public\/documentation<\/a>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 1. Authentication -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"authentication\">1. Authentication<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <p>Every request <strong>must<\/strong> include your API key in the <code>X-API-Key<\/code> header.\r\n             Requests without a valid key return <code>403<\/code>.<\/p>\r\n          <div class=\"cya-code\">\r\n            <pre><code>X-API-Key: your_api_key_here<\/code><\/pre>\r\n          <\/div>\r\n          <div class=\"cya-alert cya-alert-warn\">\r\n            <span>\ud83d\udd11<\/span>\r\n            <div>Generate your key on the <strong>API Connections<\/strong> page in your Central Yacht Agent account (requires a plan with API access).<\/div>\r\n          <\/div>\r\n          <blockquote>\r\n            Keep your API key server-side. Never expose it in browser\/frontend code \u2014 proxy the calls through your own backend (see examples below).\r\n          <\/blockquote>\r\n          <p style=\"margin-bottom:0\">A key may also be restricted to a specific <strong>server IP<\/strong> (<code>allowed_ip<\/code>) or\r\n             <strong>domain<\/strong> (<code>allowed_domain<\/code>). If your key is IP-restricted, calls must originate\r\n             from that server's egress IP \u2014 another reason to call the API from your backend, not the browser.<\/p>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 2. Rate Limits -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"rate-limits\">2. Rate Limits<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <table class=\"cya-auto\">\r\n            <thead><tr><th>Scope<\/th><th>Limit<\/th><\/tr><\/thead>\r\n            <tbody><tr><td>Per API key<\/td><td><strong>60 requests \/ minute<\/strong><\/td><\/tr><\/tbody>\r\n          <\/table>\r\n          <ul>\r\n            <li>The limiter is keyed by your API key (fallback to client IP if no key).<\/li>\r\n            <li>Window strategy: fixed window (resets each minute).<\/li>\r\n            <li>When you exceed the limit you get <strong>HTTP 429<\/strong> with a <code>Retry-After<\/code> header.<\/li>\r\n          <\/ul>\r\n          <p style=\"font-weight:600;margin-bottom:.25rem\">429 response body<\/p>\r\n          <div class=\"cya-code\">\r\n            <pre><code>{\r\n  \"error\": \"rate_limit_exceeded\",\r\n  \"message\": \"Rate limit exceeded: 60 per 1 minute\",\r\n  \"detail\": \"Too many requests. Please slow down and try again later.\",\r\n  \"retry_after\": 60\r\n}<\/code><\/pre>\r\n          <\/div>\r\n          <p style=\"font-weight:600;margin-bottom:.25rem\">Response headers on 429<\/p>\r\n          <div class=\"cya-code\">\r\n            <pre><code>Retry-After: 60\r\nX-RateLimit-Limit: 60 per 1 minute<\/code><\/pre>\r\n          <\/div>\r\n          <p style=\"font-weight:600;margin-bottom:.25rem\">Best practices<\/p>\r\n          <ul style=\"margin-bottom:0\">\r\n            <li>Cache responses where you can. <code>\/yachts\/{user_id}<\/code> is cached server-side for 60s\r\n                and <code>\/bookings<\/code> for 30s, so you don't need to poll them aggressively.<\/li>\r\n            <li>On a <code>429<\/code>, back off and retry after the number of seconds in <code>Retry-After<\/code>.<\/li>\r\n            <li>Batch\/queue your sync jobs instead of firing 60+ calls in one burst.<\/li>\r\n          <\/ul>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 3. Endpoints -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"endpoints\">3. Endpoints<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <p class=\"cya-muted\">All paths are relative to the base URL <code>https:\/\/api.centralyachtagent.com\/public\/api\/v1<\/code>.<\/p>\r\n\r\n          <h6 style=\"margin-top:.5rem\">Reference data (Labels)<\/h6>\r\n          <p class=\"cya-small cya-muted\" style=\"margin-bottom:.5rem\">Use these to map filter IDs to human labels (areas, amenities, watersports).<\/p>\r\n          <div class=\"cya-table-wrap\">\r\n            <table>\r\n              <thead><tr><th>Method<\/th><th>Path<\/th><th>Description<\/th><\/tr><\/thead>\r\n              <tbody>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/operating_areas<\/code><\/td><td>All cruising\/operating areas with IDs + labels<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/amenities<\/code><\/td><td>All yacht amenities with IDs + labels<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/watersports<\/code><\/td><td>All watersports equipment with IDs + labels<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n\r\n          <h6 style=\"margin-top:.5rem\">Yachts<\/h6>\r\n          <div class=\"cya-table-wrap\">\r\n            <table>\r\n              <thead><tr><th>Method<\/th><th>Path<\/th><th>Description<\/th><\/tr><\/thead>\r\n              <tbody>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/yachts\/{user_id}<\/code><\/td><td>List yachts owned by a user (cached 60s)<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/yachts_get\/{yacht_id}<\/code><\/td><td>Get one yacht by ID. Optional <code>?include=<\/code> to limit fields<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-post\">POST<\/span><\/td><td><code>\/yachts_search<\/code><\/td><td>Search yachts with filters + pagination<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/{yacht_id}\/yacht\/seasons<\/code><\/td><td>Seasons + pricing for a yacht<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n\r\n          <p style=\"font-weight:600;margin-bottom:.25rem\"><code>\/yachts_get\/{yacht_id}<\/code> include parameter<\/p>\r\n          <p>By default the full yacht document is returned. Use <code>include<\/code> (comma-separated)\r\n             to return only specific sub-collections and keep responses small:<\/p>\r\n          <div class=\"cya-code\">\r\n            <pre><code>GET \/yachts_get\/670f8ec038d3078885154e8d?include=images,seasons,reviews<\/code><\/pre>\r\n          <\/div>\r\n          <p>Available values: <code>images<\/code>, <code>amenities<\/code>, <code>watersports<\/code>, <code>videos<\/code>, <code>reviews<\/code>, <code>seasons<\/code>.<\/p>\r\n\r\n          <h6 style=\"margin-top:.5rem\">Bookings \/ Availability<\/h6>\r\n          <div class=\"cya-table-wrap\">\r\n            <table style=\"margin-bottom:0\">\r\n              <thead><tr><th>Method<\/th><th>Path<\/th><th>Description<\/th><\/tr><\/thead>\r\n              <tbody>\r\n                <tr><td><span class=\"cya-badge cya-get\">GET<\/span><\/td><td><code>\/bookings?yacht_id={yacht_id}<\/code><\/td><td>Bookings for a yacht for the current year (cached 30s)<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 4. yachts_search body -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"search-body\"><code>POST \/yachts_search<\/code> \u2014 request body<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <div class=\"cya-code\">\r\n            <pre><code>{\r\n  \"page\": 1,\r\n  \"limit\": 10,\r\n  \"searchTerm\": \"\",\r\n  \"filters\": {\r\n    \"yachtTypes\": [\"motor\", \"sail\"],\r\n    \"cabins\": [3, 8],\r\n    \"guests\": [6, 16],\r\n    \"length\": [20, 60],\r\n    \"length_unit\": \"meter\",\r\n    \"yearBuild\": [2018, 2026],\r\n    \"season_price\": [20000, 100000],\r\n    \"user_currency\": \"USD\",\r\n    \"location_areas\": [25, 20],\r\n    \"watersports\": [3, 13, 17],\r\n    \"start_date\": \"2026-07-01\",\r\n    \"end_date\": \"2026-07-14\",\r\n    \"available_days\": 7\r\n  }\r\n}<\/code><\/pre>\r\n          <\/div>\r\n\r\n          <div class=\"cya-table-wrap\">\r\n            <table>\r\n              <thead><tr><th>Field<\/th><th>Type<\/th><th>Default<\/th><th>Notes<\/th><\/tr><\/thead>\r\n              <tbody>\r\n                <tr><td><code>page<\/code><\/td><td>int<\/td><td>1<\/td><td>Pagination page<\/td><\/tr>\r\n                <tr><td><code>limit<\/code><\/td><td>int<\/td><td>10<\/td><td>Items per page<\/td><\/tr>\r\n                <tr><td><code>searchTerm<\/code><\/td><td>string<\/td><td>\"\"<\/td><td>Matches yacht name<\/td><\/tr>\r\n                <tr><td><code>filters.yachtTypes<\/code><\/td><td>string[]<\/td><td>\u2014<\/td><td>e.g. <code>[\"sail\",\"motor\"]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.cabins<\/code><\/td><td>int[2]<\/td><td>\u2014<\/td><td><code>[min, max]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.guests<\/code><\/td><td>int[2]<\/td><td>\u2014<\/td><td><code>[min, max]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.length<\/code><\/td><td>float[2]<\/td><td>\u2014<\/td><td><code>[min, max]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.length_unit<\/code><\/td><td>string<\/td><td>\"meter\"<\/td><td><code>\"meter\"<\/code> or <code>\"feet\"<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.yearBuild<\/code><\/td><td>int[2]<\/td><td>\u2014<\/td><td><code>[min, max]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.season_price<\/code><\/td><td>float[2]<\/td><td>\u2014<\/td><td><code>[min, max]<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.user_currency<\/code><\/td><td>string<\/td><td>\"USD\"<\/td><td><code>USD<\/code>, <code>Euro<\/code>, <code>Pounds<\/code>, <code>CAD<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.location_areas<\/code><\/td><td>int[]<\/td><td>\u2014<\/td><td>Area IDs from <code>\/operating_areas<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.watersports<\/code><\/td><td>int[]<\/td><td>\u2014<\/td><td>IDs from <code>\/watersports<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.start_date<\/code><\/td><td>string<\/td><td>\u2014<\/td><td><code>YYYY-MM-DD<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.end_date<\/code><\/td><td>string<\/td><td>\u2014<\/td><td><code>YYYY-MM-DD<\/code><\/td><\/tr>\r\n                <tr><td><code>filters.available_days<\/code><\/td><td>int<\/td><td>\u2014<\/td><td>Min available days in date range<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n\r\n          <p style=\"font-weight:600;margin-bottom:.25rem\">Response shape (search &amp; list)<\/p>\r\n          <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n            <pre><code>{\r\n  \"yachts\": [\r\n    {\r\n      \"id\": \"670f8ec038d3078885154e8d\",\r\n      \"yachtName\": \"Ocean Spirit\",\r\n      \"yachtType\": \"sail\",\r\n      \"length\": 24.5,\r\n      \"units\": \"meter\",\r\n      \"year_build\": 2020,\r\n      \"cabins\": 4,\r\n      \"pax\": 8,\r\n      \"seasonAreas\": [\"Greece\", \"Croatia\"],\r\n      \"image\": \"https:\/\/cya.sfo3.cdn.digitaloceanspaces.com\/yachts\/ocean_spirit_main.jpg\",\r\n      \"min_price\": 35000,\r\n      \"currency\": \"Euro\"\r\n    }\r\n  ],\r\n  \"totalYachts\": 1\r\n}<\/code><\/pre>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 5. Examples -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"examples\">5. Examples<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <blockquote>Replace <code>YOUR_API_KEY<\/code> with your key. Server-side calls only.<\/blockquote>\r\n\r\n          <ul class=\"cya-tabs\" role=\"tablist\">\r\n            <li><button class=\"active\" data-tab=\"ex-curl\">cURL<\/button><\/li>\r\n            <li><button data-tab=\"ex-laravel\">PHP \u00b7 Laravel<\/button><\/li>\r\n            <li><button data-tab=\"ex-php\">PHP \u00b7 raw cURL<\/button><\/li>\r\n            <li><button data-tab=\"ex-fetch\">JS \u00b7 fetch<\/button><\/li>\r\n            <li><button data-tab=\"ex-axios\">JS \u00b7 axios<\/button><\/li>\r\n          <\/ul>\r\n\r\n          <div class=\"cya-pane active\" id=\"ex-curl\">\r\n            <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n              <pre><code># List yachts for a user\r\ncurl -X GET \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\/yachts\/12345\" \\\r\n  -H \"X-API-Key: YOUR_API_KEY\"\r\n\r\n# Get one yacht, only images + seasons\r\ncurl -X GET \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\/yachts_get\/670f8ec038d3078885154e8d?include=images,seasons\" \\\r\n  -H \"X-API-Key: YOUR_API_KEY\"\r\n\r\n# Search yachts\r\ncurl -X POST \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\/yachts_search\" \\\r\n  -H \"X-API-Key: YOUR_API_KEY\" \\\r\n  -H \"Content-Type: application\/json\" \\\r\n  -d '{\r\n    \"page\": 1,\r\n    \"limit\": 10,\r\n    \"filters\": { \"yachtTypes\": [\"motor\"], \"guests\": [6, 16] }\r\n  }'\r\n\r\n# Bookings for a yacht\r\ncurl -X GET \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\/bookings?yacht_id=670f8ec038d3078885154e8d\" \\\r\n  -H \"X-API-Key: YOUR_API_KEY\"<\/code><\/pre>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"cya-pane\" id=\"ex-laravel\">\r\n            <p class=\"cya-small cya-muted\">Store the key in <code>config\/services.php<\/code> and <code>.env<\/code>, never hard-coded.<\/p>\r\n            <div class=\"cya-code\">\r\n              <pre><code># .env\r\nCYA_API_BASE=https:\/\/api.centralyachtagent.com\/public\/api\/v1\r\nCYA_API_KEY=YOUR_API_KEY<\/code><\/pre>\r\n            <\/div>\r\n            <div class=\"cya-code\">\r\n              <pre><code>\/\/ config\/services.php\r\n'cya' => [\r\n    'base' => env('CYA_API_BASE'),\r\n    'key'  => env('CYA_API_KEY'),\r\n],<\/code><\/pre>\r\n            <\/div>\r\n            <div class=\"cya-code\">\r\n              <pre><code>use Illuminate\\Support\\Facades\\Http;\r\n\r\nclass CyaApi\r\n{\r\n    private function client()\r\n    {\r\n        return Http::baseUrl(config('services.cya.base'))\r\n            ->withHeaders(['X-API-Key' => config('services.cya.key')])\r\n            ->acceptJson()\r\n            ->timeout(15);\r\n    }\r\n\r\n    \/\/ GET \/yachts\/{user_id}\r\n    public function yachtsForUser(string $userId): array\r\n    {\r\n        return $this->client()->get(\"\/yachts\/{$userId}\")->throw()->json();\r\n    }\r\n\r\n    \/\/ GET \/yachts_get\/{yacht_id}?include=...\r\n    public function yacht(string $yachtId, array $include = []): array\r\n    {\r\n        $query = $include ? ['include' => implode(',', $include)] : [];\r\n        return $this->client()\r\n            ->get(\"\/yachts_get\/{$yachtId}\", $query)\r\n            ->throw()->json();\r\n    }\r\n\r\n    \/\/ POST \/yachts_search\r\n    public function search(array $filters = [], int $page = 1, int $limit = 10): array\r\n    {\r\n        $res = $this->client()->post('\/yachts_search', [\r\n            'page'    => $page,\r\n            'limit'   => $limit,\r\n            'filters' => $filters,\r\n        ]);\r\n\r\n        \/\/ Handle rate limiting gracefully\r\n        if ($res->status() === 429) {\r\n            $retryAfter = (int) $res->header('Retry-After', 60);\r\n            throw new \\RuntimeException(\"Rate limited. Retry after {$retryAfter}s.\");\r\n        }\r\n\r\n        return $res->throw()->json();\r\n    }\r\n\r\n    \/\/ GET \/bookings?yacht_id=...\r\n    public function bookings(string $yachtId): array\r\n    {\r\n        return $this->client()\r\n            ->get('\/bookings', ['yacht_id' => $yachtId])\r\n            ->throw()->json();\r\n    }\r\n}<\/code><\/pre>\r\n            <\/div>\r\n            <p style=\"font-weight:600;margin-bottom:.25rem\">Usage in a controller<\/p>\r\n            <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n              <pre><code>$api = new CyaApi();\r\n\r\n$results = $api->search(\r\n    filters: ['yachtTypes' => ['motor'], 'guests' => [6, 16]],\r\n    page: 1,\r\n    limit: 10\r\n);\r\n\r\n$yacht = $api->yacht('670f8ec038d3078885154e8d', ['images', 'seasons']);<\/code><\/pre>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"cya-pane\" id=\"ex-php\">\r\n            <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n              <pre><code>&lt;?php\r\n$base = 'https:\/\/api.centralyachtagent.com\/public\/api\/v1';\r\n$key  = 'YOUR_API_KEY';\r\n\r\n\/\/ --- GET example ---\r\n$ch = curl_init(\"$base\/yachts\/12345\");\r\ncurl_setopt_array($ch, [\r\n    CURLOPT_RETURNTRANSFER => true,\r\n    CURLOPT_HTTPHEADER     => [\"X-API-Key: $key\"],\r\n]);\r\n$body   = curl_exec($ch);\r\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\r\ncurl_close($ch);\r\n\r\nif ($status === 429) {\r\n    \/\/ back off and retry later\r\n}\r\n$data = json_decode($body, true);\r\n\r\n\/\/ --- POST example ---\r\n$payload = json_encode([\r\n    'page'    => 1,\r\n    'limit'   => 10,\r\n    'filters' => ['yachtTypes' => ['motor'], 'guests' => [6, 16]],\r\n]);\r\n\r\n$ch = curl_init(\"$base\/yachts_search\");\r\ncurl_setopt_array($ch, [\r\n    CURLOPT_RETURNTRANSFER => true,\r\n    CURLOPT_POST           => true,\r\n    CURLOPT_POSTFIELDS     => $payload,\r\n    CURLOPT_HTTPHEADER     => [\r\n        \"X-API-Key: $key\",\r\n        'Content-Type: application\/json',\r\n    ],\r\n]);\r\n$response = json_decode(curl_exec($ch), true);\r\ncurl_close($ch);<\/code><\/pre>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"cya-pane\" id=\"ex-fetch\">\r\n            <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n              <pre><code>const BASE = \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\";\r\nconst API_KEY = process.env.CYA_API_KEY; \/\/ keep server-side\r\n\r\nasync function searchYachts() {\r\n  const res = await fetch(`${BASE}\/yachts_search`, {\r\n    method: \"POST\",\r\n    headers: {\r\n      \"X-API-Key\": API_KEY,\r\n      \"Content-Type\": \"application\/json\",\r\n    },\r\n    body: JSON.stringify({\r\n      page: 1,\r\n      limit: 10,\r\n      filters: { yachtTypes: [\"motor\"], guests: [6, 16] },\r\n    }),\r\n  });\r\n\r\n  if (res.status === 429) {\r\n    const retryAfter = Number(res.headers.get(\"Retry-After\") || 60);\r\n    throw new Error(`Rate limited. Retry after ${retryAfter}s.`);\r\n  }\r\n  if (!res.ok) throw new Error(`API error ${res.status}`);\r\n\r\n  return res.json();\r\n}\r\n\r\nasync function getYacht(id, include = []) {\r\n  const qs = include.length ? `?include=${include.join(\",\")}` : \"\";\r\n  const res = await fetch(`${BASE}\/yachts_get\/${id}${qs}`, {\r\n    headers: { \"X-API-Key\": API_KEY },\r\n  });\r\n  return res.json();\r\n}<\/code><\/pre>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"cya-pane\" id=\"ex-axios\">\r\n            <div class=\"cya-code\" style=\"margin-bottom:0\">\r\n              <pre><code>import axios from \"axios\";\r\n\r\nconst cya = axios.create({\r\n  baseURL: \"https:\/\/api.centralyachtagent.com\/public\/api\/v1\",\r\n  headers: { \"X-API-Key\": process.env.CYA_API_KEY },\r\n  timeout: 15000,\r\n});\r\n\r\n\/\/ GET\r\nconst { data } = await cya.get(\"\/yachts\/12345\");\r\n\r\n\/\/ POST\r\nconst search = await cya.post(\"\/yachts_search\", {\r\n  page: 1,\r\n  limit: 10,\r\n  filters: { yachtTypes: [\"motor\"], guests: [6, 16] },\r\n});<\/code><\/pre>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 6. Error reference -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"errors\">6. Error reference<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <div class=\"cya-table-wrap\">\r\n            <table style=\"margin-bottom:0\">\r\n              <thead><tr><th>Status<\/th><th>Meaning<\/th><th>What to do<\/th><\/tr><\/thead>\r\n              <tbody>\r\n                <tr><td><span class=\"cya-badge cya-s400\">400<\/span><\/td><td>Bad request (invalid ID or filter value)<\/td><td>Check the yacht\/user ID format and filter types<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-s403\">403<\/span><\/td><td>Missing \/ invalid API key, or IP\/domain not allowed<\/td><td>Verify the <code>X-API-Key<\/code> header and key restrictions<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-s404\">404<\/span><\/td><td>Resource not found (or hidden <code>no_api<\/code> yacht)<\/td><td>The yacht\/user doesn't exist or isn't public<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-s429\">429<\/span><\/td><td>Rate limit exceeded<\/td><td>Back off and retry after <code>Retry-After<\/code> seconds<\/td><\/tr>\r\n                <tr><td><span class=\"cya-badge cya-s500\">500<\/span><\/td><td>Internal server error<\/td><td>Retry with backoff; contact support if it persists<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- 7. Checklist -->\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h5 id=\"checklist\">7. Quick checklist for integrators<\/h5><\/div>\r\n        <div class=\"cya-card-body\">\r\n          <ul style=\"list-style:none;padding-left:0;margin-bottom:0\">\r\n            <li>\u2611 Call the API <strong>from your own backend<\/strong>, not the browser.<\/li>\r\n            <li>\u2611 Send <code>X-API-Key<\/code> on every request.<\/li>\r\n            <li>\u2611 Cache responses; respect the 60 req\/min limit.<\/li>\r\n            <li>\u2611 Handle <code>429<\/code> with <code>Retry-After<\/code> backoff.<\/li>\r\n            <li>\u2611 Use <code>\/operating_areas<\/code>, <code>\/amenities<\/code>, <code>\/watersports<\/code> to resolve filter IDs.<\/li>\r\n            <li>\u2611 Use <code>?include=<\/code> on <code>\/yachts_get<\/code> to keep payloads small.<\/li>\r\n          <\/ul>\r\n        <\/div>\r\n      <\/div>\r\n\r\n    <\/div>\r\n\r\n    <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Sticky TOC \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n    <div class=\"cya-side\">\r\n      <div class=\"cya-card\">\r\n        <div class=\"cya-card-head\"><h6 style=\"margin:0\">On this page<\/h6><\/div>\r\n        <div class=\"cya-card-body cya-toc\" style=\"padding:.5rem .75rem\">\r\n          <a href=\"#authentication\">1. Authentication<\/a>\r\n          <a href=\"#rate-limits\">2. Rate Limits<\/a>\r\n          <a href=\"#endpoints\">3. Endpoints<\/a>\r\n          <a href=\"#search-body\">4. yachts_search body<\/a>\r\n          <a href=\"#examples\">5. Examples<\/a>\r\n          <a href=\"#errors\">6. Error reference<\/a>\r\n          <a href=\"#checklist\">7. Checklist<\/a>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n(function () {\r\n  var root = document.currentScript ? document.currentScript.previousElementSibling : null;\r\n  \/\/ Fallback: grab the last .cya-api-doc on the page.\r\n  var docs = document.querySelectorAll('.cya-api-doc');\r\n  var scope = docs[docs.length - 1];\r\n  if (!scope) return;\r\n\r\n  \/\/ Tabs\r\n  scope.querySelectorAll('.cya-tabs button').forEach(function (btn) {\r\n    btn.addEventListener('click', function () {\r\n      var target = btn.getAttribute('data-tab');\r\n      scope.querySelectorAll('.cya-tabs button').forEach(function (b) { b.classList.remove('active'); });\r\n      scope.querySelectorAll('.cya-pane').forEach(function (p) { p.classList.remove('active'); });\r\n      btn.classList.add('active');\r\n      var pane = scope.querySelector('#' + target);\r\n      if (pane) pane.classList.add('active');\r\n    });\r\n  });\r\n\r\n  \/\/ Copy buttons on every code block\r\n  scope.querySelectorAll('.cya-code').forEach(function (wrap) {\r\n    var pre = wrap.querySelector('pre');\r\n    if (!pre) return;\r\n    var btn = document.createElement('button');\r\n    btn.type = 'button';\r\n    btn.className = 'cya-copy';\r\n    btn.textContent = 'Copy';\r\n    btn.addEventListener('click', function () {\r\n      navigator.clipboard.writeText(pre.innerText).then(function () {\r\n        btn.textContent = 'Copied!';\r\n        setTimeout(function () { btn.textContent = 'Copy'; }, 1500);\r\n      });\r\n    });\r\n    wrap.appendChild(btn);\r\n  });\r\n})();\r\n<\/script>\r\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\u26a0 New features are available only in the new API. All the new features \u2014 Seasons, Crew Details (images &amp; descriptions), Menu Details, More videos &amp; more photos (over 20), new Amenities &amp; Watersports, and every other new feature \u2014 are available only in the new API, not in the legacy API. Central Yacht Agent [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-4613","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/pages\/4613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/comments?post=4613"}],"version-history":[{"count":7,"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/pages\/4613\/revisions"}],"predecessor-version":[{"id":4620,"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/pages\/4613\/revisions\/4620"}],"wp:attachment":[{"href":"https:\/\/www.centralyachtagent.com\/welcome\/wp-json\/wp\/v2\/media?parent=4613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}