{"id":16,"date":"2026-09-16T10:28:30","date_gmt":"2026-09-16T10:28:30","guid":{"rendered":"https:\/\/docs.latw.ai\/uncategorized\/data-model\/"},"modified":"2026-09-16T10:28:30","modified_gmt":"2026-09-16T10:28:30","slug":"data-model","status":"publish","type":"post","link":"https:\/\/docs.latw.ai\/pl\/esti-to-wordpress\/data-model\/","title":{"rendered":"Data Model"},"content":{"rendered":"<h1>Data model reference<\/h1>\n<p>The plugin creates <strong>no database tables and no taxonomies<\/strong>. Everything lives in <code>wp_posts<\/code>, <code>wp_postmeta<\/code> and a handful<br \/>\nof options.<\/p>\n<h2>Post type<\/h2>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Name<\/td>\n<td><code>osfec_offer<\/code><\/td>\n<\/tr>\n<tr>\n<td>Public<\/td>\n<td>yes, <code>has_archive<\/code> = the archive slug<\/td>\n<\/tr>\n<tr>\n<td>Rewrite<\/td>\n<td><code>\/{archive_slug}\/{post_name}\/<\/code>, <code>with_front<\/code> = false<\/td>\n<\/tr>\n<tr>\n<td><code>show_in_rest<\/code><\/td>\n<td><code>true<\/code> \u2014 so the CPT works in the Query Loop block and in page-builder loops<\/td>\n<\/tr>\n<tr>\n<td><code>supports<\/code><\/td>\n<td><code>title<\/code> only<\/td>\n<\/tr>\n<tr>\n<td>Capabilities<\/td>\n<td><code>create_posts<\/code> is <code>do_not_allow<\/code>; <code>map_meta_cap<\/code> is on<\/td>\n<\/tr>\n<tr>\n<td>Menu icon<\/td>\n<td><code>dashicons-building<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>post_content<\/code> holds the imported description (<code>descriptionWebsite<\/code>, falling back to <code>description<\/code>), run through<br \/>\n<code>wp_kses_post()<\/code>. <code>post_title<\/code> comes from <code>portalWwwTitle<\/code> \/ <code>portalTitle<\/code>, falling back to &#8220;type, city&#8221;.<\/p>\n<p>The slug is built once, at creation, from the title plus the public offer number, and is <strong>never rewritten on update<\/strong> \u2014<br \/>\na price change must not move the URL.<\/p>\n<h2>Meta<\/h2>\n<p>Every key carries the <code>_osfec_<\/code> prefix. <strong>Empty values are not stored<\/strong>: a field missing from the payload has no meta<br \/>\nrow, so <code>get_post_meta()<\/code> returns <code>''<\/code>. Zero is kept \u2014 the ground floor is a real value.<\/p>\n<p>None of these are registered with <code>register_post_meta()<\/code>, and none are exposed through the REST API.<\/p>\n<h3>Identity<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_id<\/code><\/td>\n<td>int<\/td>\n<td>Esti offer ID. The upsert key<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_number<\/code><\/td>\n<td>string<\/td>\n<td>Public offer number (<code>numberExport<\/code>, falling back to <code>number<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_hash<\/code><\/td>\n<td>string<\/td>\n<td>MD5 of the mapper version plus the payload. Drives change detection<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_synced_at<\/code><\/td>\n<td>int<\/td>\n<td>Unix timestamp of the last write<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Classification<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_type<\/code><\/td>\n<td>slug<\/td>\n<td>Type name without the bracketed variant, slugified: <code>mieszkanie<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_type_label<\/code><\/td>\n<td>string<\/td>\n<td>Raw Esti type name: <code>Dzia\u0142ka (Rolna)<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_subtype<\/code><\/td>\n<td>slug<\/td>\n<td>Slugified bracketed variant: <code>rolna<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_subtype_label<\/code><\/td>\n<td>string<\/td>\n<td>The variant itself: <code>Rolna<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_transaction<\/code><\/td>\n<td>slug<\/td>\n<td><code>sale<\/code>, <code>rent<\/code>, <code>purchase<\/code>, <code>lease<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_market<\/code><\/td>\n<td>slug<\/td>\n<td><code>primary<\/code>, <code>secondary<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_tags<\/code><\/td>\n<td>CSV<\/td>\n<td>Marketing labels from Esti<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Price and size<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_price<\/code><\/td>\n<td>float<\/td>\n<td><strong>Empty when the price is hidden in Esti or is not positive<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_currency<\/code><\/td>\n<td>string<\/td>\n<td><code>PLN<\/code>, <code>EUR<\/code>, <code>USD<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_price_m<\/code><\/td>\n<td>float<\/td>\n<td>Price per m\u00b2 (<code>pricePermeter<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_price_prev<\/code><\/td>\n<td>float<\/td>\n<td>Previous price, stored only when it was higher than the current one<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_area<\/code><\/td>\n<td>float<\/td>\n<td>Total area<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_area_usable<\/code><\/td>\n<td>float<\/td>\n<td>Usable area<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_rooms<\/code><\/td>\n<td>int<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_floor<\/code><\/td>\n<td>int<\/td>\n<td>Floor the unit is on<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_floors<\/code><\/td>\n<td>int<\/td>\n<td>Floors in the building<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_year<\/code><\/td>\n<td>int<\/td>\n<td>Year built<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Location<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_city<\/code><\/td>\n<td>string<\/td>\n<td><code>locationExportCityName<\/code>, falling back to <code>locationCityName<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_commune<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_county<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_province<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_street<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_postal<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_lat<\/code>, <code>_osfec_lng<\/code><\/td>\n<td>string<\/td>\n<td>Coordinates as strings<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Location values are stored <strong>raw<\/strong>. Esti mixes upper case, lower case and trailing spaces; formatting is the template&#8217;s<br \/>\njob.<\/p>\n<h3>Media<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_photos<\/code><\/td>\n<td>JSON<\/td>\n<td>Array of full-size URLs on the Esti CDN (<code>_max<\/code> variant)<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_thumb<\/code><\/td>\n<td>string<\/td>\n<td>The first photo as its <code>_min<\/code> variant<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_video<\/code><\/td>\n<td>string<\/td>\n<td>External link<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_tour<\/code><\/td>\n<td>string<\/td>\n<td>External link to a virtual tour<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Read photos with <code>osfec_photos()<\/code> rather than decoding the JSON yourself.<\/p>\n<h3>Dictionary-backed attributes<\/h3>\n<p>These hold <strong>numeric IDs<\/strong>, not labels. Resolve them with <code>osfec_attribute_label()<\/code>; an ID the dictionary cannot name<br \/>\nyields an empty string, and the caller is expected to drop the row rather than print a number at a buyer.<\/p>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Esti payload key<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_ground_type<\/code><\/td>\n<td><code>groundType<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_ground_fencing<\/code><\/td>\n<td><code>groundFencing<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_ground_shape<\/code><\/td>\n<td><code>groundShape<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_ground_ownership<\/code><\/td>\n<td><code>groundOwnership<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_building_type<\/code><\/td>\n<td><code>buildingType<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_building_heating<\/code><\/td>\n<td><code>buildingHeating<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Agent<\/h3>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>_osfec_agent_id<\/code><\/td>\n<td>int<\/td>\n<td>Esti agent ID (<code>contactId<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_agent_name<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_agent_email<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><code>_osfec_agent_phone<\/code><\/td>\n<td>string<\/td>\n<td><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The agent is meta, <strong>not a taxonomy<\/strong>, so filtering by agent runs through <code>meta_query<\/code>. The photo, role and office are<br \/>\nnot per-offer meta: they come from the agent directory option, matched on <code>_osfec_agent_id<\/code>. <code>osfec_agent()<\/code> merges both<br \/>\nsources.<\/p>\n<h2>Options<\/h2>\n<table>\n<thead>\n<tr>\n<th>Option<\/th>\n<th>Autoloaded<\/th>\n<th>Contents<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>osfec_settings<\/code><\/td>\n<td>yes<\/td>\n<td>Every setting, one array. Read it through <code>OSFEC_Settings::get()<\/code> \/ <code>::value()<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>osfec_agents<\/code><\/td>\n<td>no<\/td>\n<td>Agent directory keyed by Esti agent ID: <code>name<\/code>, <code>photo<\/code>, <code>position<\/code>, <code>office<\/code>, <code>email<\/code>, <code>phone<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>osfec_dictionary<\/code><\/td>\n<td>no<\/td>\n<td>Flattened Esti dictionary, <code>id =&gt; label<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>osfec_runs<\/code><\/td>\n<td>no<\/td>\n<td>The last 20 sync runs, newest first, up to 200 events each<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_last_sync<\/code><\/td>\n<td>no<\/td>\n<td>Unix timestamp of the last successful cleanup<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_key<\/code><\/td>\n<td>no<\/td>\n<td>The activated license key<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_status<\/code><\/td>\n<td>no<\/td>\n<td>Last verdict from the license server: <code>active<\/code>, <code>invalid<\/code> or <code>version_mismatch<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_expires<\/code><\/td>\n<td>no<\/td>\n<td>Date the subscription is paid to, empty for a lifetime license<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_type<\/code><\/td>\n<td>no<\/td>\n<td>License type as the server names it<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_allowed_version<\/code><\/td>\n<td>no<\/td>\n<td>Newest plugin version the license covers<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_activated_at<\/code><\/td>\n<td>no<\/td>\n<td>UTC datetime of the first successful activation<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Transients<\/h2>\n<table>\n<thead>\n<tr>\n<th>Transient<\/th>\n<th>TTL<\/th>\n<th>Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>osfec_sync_ids<\/code><\/td>\n<td>1 h<\/td>\n<td>Esti ID \u2192 post ID map for the current run<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_sync_seen<\/code><\/td>\n<td>1 h<\/td>\n<td>Esti IDs seen so far in the current run; cleanup depends on it<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_sync_error<\/code><\/td>\n<td>24 h<\/td>\n<td>Last failure message, shown on the settings screen<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_map_&lt;key&gt;<\/code><\/td>\n<td>6 h<\/td>\n<td>Slug \u2192 raw value map for a meta key, e.g. <code>osfec_map_city<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>osfec_map_type_options<\/code><\/td>\n<td>6 h<\/td>\n<td>Type slug \u2192 label<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_map_subtypes<\/code><\/td>\n<td>6 h<\/td>\n<td>Subtype slug \u2192 label<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_update_latest<\/code><\/td>\n<td>12 h (1 h after a failure)<\/td>\n<td><code>plugin\/latest<\/code> payload from the license server. A <strong>site<\/strong> transient<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_update_info<\/code><\/td>\n<td>12 h (1 h after a failure)<\/td>\n<td><code>plugin\/info<\/code> payload, feeding the &#8220;View details&#8221; screen. A <strong>site<\/strong> transient<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The slug maps are flushed at the end of every successful run, so a new city shows up in the filter dropdowns as soon as<br \/>\nthe run that imported it finishes.<\/p>\n<h2>Scheduled events<\/h2>\n<table>\n<thead>\n<tr>\n<th>Hook<\/th>\n<th>Schedule<\/th>\n<th>Argument<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>osfec_sync_start<\/code><\/td>\n<td><code>osfec_6h<\/code> (every 6 hours)<\/td>\n<td>\u2014<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_sync_page<\/code><\/td>\n<td>single event, 30 s after the previous page<\/td>\n<td>zero-based page number<\/td>\n<\/tr>\n<tr>\n<td><code>osfec_license_check<\/code><\/td>\n<td><code>daily<\/code><\/td>\n<td>\u2014<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>OSFEC_API::PER_PAGE<\/code> is 100.<\/p>\n<h2>Change detection<\/h2>\n<p><code>_osfec_hash<\/code> is <code>md5( OSFEC_MAPPER_VERSION . wp_json_encode( $offer ) )<\/code>. When the stored hash matches, the offer is<br \/>\ncounted as unchanged and nothing is written.<\/p>\n<p><code>OSFEC_MAPPER_VERSION<\/code> is a constant in the main plugin file. <strong>Bump it whenever the mapping changes<\/strong>: every hash then<br \/>\ndiffers and the whole catalogue is re-imported on the next run.<\/p>\n<h2>Constants<\/h2>\n<table>\n<thead>\n<tr>\n<th>Constant<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>OSFEC_VERSION<\/code><\/td>\n<td>Plugin version, also the asset cache buster<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_FILE<\/code><\/td>\n<td>Main plugin file<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_PATH<\/code><\/td>\n<td>Plugin directory, trailing slash<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_URL<\/code><\/td>\n<td>Plugin URL, trailing slash<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_MAPPER_VERSION<\/code><\/td>\n<td>Mapping revision, part of the hash<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_BASENAME<\/code><\/td>\n<td><code>plugin_basename()<\/code> of the main file, the key core uses in the update transient<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Class map<\/h2>\n<table>\n<thead>\n<tr>\n<th>Class<\/th>\n<th>Responsibility<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>OSFEC_CPT<\/code><\/td>\n<td>Post type and rewrite rules<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_API<\/code><\/td>\n<td>Esti HTTP client: <code>fetch_page()<\/code>, <code>fetch_agents()<\/code>, <code>fetch_dictionary()<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Mapper<\/code><\/td>\n<td>Payload \u2192 post fields and meta. No side effects<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Sync<\/code><\/td>\n<td>Run loop, cron, upsert, cleanup<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Log<\/code><\/td>\n<td>Run records and the log screen<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_License<\/code><\/td>\n<td>Key verification, the License tab, the gate in front of every run<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Updater<\/code><\/td>\n<td>Updates from the license server: the update transient and <code>plugins_api<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Settings<\/code><\/td>\n<td>Settings screen, sanitization, manual sync<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Query<\/code><\/td>\n<td>GET parameters \u2192 <code>WP_Query<\/code> arguments<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Frontend<\/code><\/td>\n<td><code>template_include<\/code>, thumbnails, assets, shortcode, block<\/td>\n<\/tr>\n<tr>\n<td><code>OSFEC_Schema<\/code><\/td>\n<td>JSON-LD in <code>wp_head<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Every class exposes a static <code>init()<\/code> that registers its own hooks; the main file calls them in order on<br \/>\n<code>plugins_loaded<\/code>.<\/p>\n<h2>No hooks of its own<\/h2>\n<p>The plugin fires no custom actions and applies no custom filters. Extension points are: the template overrides, the<br \/>\n<code>osfec_*<\/code> helper functions, the shortcode and block attributes, the CSS, and WordPress&#8217;s own hooks (<code>pre_get_posts<\/code>,<br \/>\n<code>template_include<\/code>, <code>the_content<\/code>, \u2026). See <a href=\"\/esti-to-wordpress\/custom-ui\">Building a custom UI<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Data model reference The plugin creates no database tables and no taxonomies. Everything lives in wp_posts, wp_postmeta and a handful of options. Post type Name osfec_offer\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_latwm_translated_slug":"","footnotes":""},"categories":[2],"tags":[],"class_list":["post-16","post","type-post","status-publish","format-standard","hentry","category-esti-to-wordpress"],"_links":{"self":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":1,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":51,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/16\/revisions\/51"}],"wp:attachment":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}