{
 "openapi": "3.1.0",
 "info": {
  "title": "MapX Pet Directory API",
  "version": "1.0.0",
  "description": "Read-only, no-auth, static JSON API for the MapX Pet Canadian pet directory (vets, pet stores, groomers, boarding, pet-friendly places, dog parks, shelters & rescues). For \"pet places in <city>\", GET /api/v1/cities.json to find the province+slug, then /api/v1/cities/{province}/{city}.json. Data includes OpenStreetMap (ODbL) and municipal open data: show each item's attribution.",
  "license": {
   "name": "ODbL 1.0 (OSM-derived data) + municipal Open Government Licences per item",
   "url": "https://www.openstreetmap.org/copyright"
  },
  "x-generated-at": "2026-11-01T03:01:17Z"
 },
 "servers": [
  {
   "url": "https://mapxpet.com"
  }
 ],
 "paths": {
  "/api/v1/cities.json": {
   "get": {
    "operationId": "listCities",
    "summary": "All cities with listing counts per category",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/City"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/cities/{province}/{city}.json": {
   "get": {
    "operationId": "getCityListings",
    "summary": "All pet places in one city",
    "parameters": [
     {
      "name": "province",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "ab",
        "bc",
        "mb",
        "nb",
        "nl",
        "ns",
        "nt",
        "nu",
        "on",
        "pe",
        "qc",
        "sk",
        "yt"
       ]
      },
      "description": "2-letter lowercase code"
     },
     {
      "name": "city",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "city slug, e.g. toronto, montreal, quebec"
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "object",
           "properties": {
            "city": {
             "$ref": "#/components/schemas/City"
            },
            "listings": {
             "type": "array",
             "items": {
              "$ref": "#/components/schemas/ListingBrief"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/cities/{province}/{city}/{category}.json": {
   "get": {
    "operationId": "getCityCategoryListings",
    "summary": "Pet places of one category in one city",
    "parameters": [
     {
      "name": "province",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "ab",
        "bc",
        "mb",
        "nb",
        "nl",
        "ns",
        "nt",
        "nu",
        "on",
        "pe",
        "qc",
        "sk",
        "yt"
       ]
      },
      "description": ""
     },
     {
      "name": "city",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "city slug"
     },
     {
      "name": "category",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "vets",
        "pet-stores",
        "groomers",
        "boarding",
        "pet-friendly",
        "dog-parks",
        "shelters"
       ]
      },
      "description": ""
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "object",
           "properties": {
            "city": {
             "$ref": "#/components/schemas/City"
            },
            "category": {
             "type": "string"
            },
            "listings": {
             "type": "array",
             "items": {
              "$ref": "#/components/schemas/ListingBrief"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/provinces/{province}.json": {
   "get": {
    "operationId": "getProvince",
    "summary": "Cities and counts in a province",
    "parameters": [
     {
      "name": "province",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "ab",
        "bc",
        "mb",
        "nb",
        "nl",
        "ns",
        "nt",
        "nu",
        "on",
        "pe",
        "qc",
        "sk",
        "yt"
       ]
      },
      "description": ""
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "object"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/categories.json": {
   "get": {
    "operationId": "listCategories",
    "summary": "Categories with counts (events is planned, total 0)",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Category"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/categories/{category}.json": {
   "get": {
    "operationId": "getCategoryListings",
    "summary": "All listings in a category, Canada-wide",
    "parameters": [
     {
      "name": "category",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "vets",
        "pet-stores",
        "groomers",
        "boarding",
        "pet-friendly",
        "dog-parks",
        "shelters"
       ]
      },
      "description": ""
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/ListingBrief"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/listings.json": {
   "get": {
    "operationId": "listAllListings",
    "summary": "All listings (brief), for client-side filtering by text, city, category or distance",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/ListingBrief"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/listings/{id}.json": {
   "get": {
    "operationId": "getListing",
    "summary": "One listing with full detail and sources",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "listing id, e.g. MXP-OSM-n10235940541"
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "$ref": "#/components/schemas/Listing"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  },
  "/api/v1/events.json": {
   "get": {
    "operationId": "listEvents",
    "summary": "Pet events (empty until the activity calendar launches; never contains invented events)",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "meta",
          "data"
         ],
         "properties": {
          "meta": {
           "$ref": "#/components/schemas/Meta"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Event"
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Not found (static 404 page)"
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "Meta": {
    "type": "object",
    "properties": {
     "api_version": {
      "type": "string"
     },
     "generated_at": {
      "type": "string",
      "format": "date-time"
     },
     "data_updated_at": {
      "type": "string"
     },
     "count": {
      "type": "integer"
     },
     "licence_note": {
      "type": "string"
     },
     "docs": {
      "type": "string"
     },
     "status": {
      "type": "string"
     },
     "note": {
      "type": "string"
     },
     "category": {
      "type": "string"
     }
    }
   },
   "Address": {
    "type": "object",
    "properties": {
     "street": {
      "type": [
       "string",
       "null"
      ]
     },
     "city": {
      "type": [
       "string",
       "null"
      ]
     },
     "province": {
      "type": [
       "string",
       "null"
      ]
     },
     "postal_code": {
      "type": [
       "string",
       "null"
      ]
     },
     "country": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "Geo": {
    "type": [
     "object",
     "null"
    ],
    "properties": {
     "lat": {
      "type": "number"
     },
     "lon": {
      "type": "number"
     },
     "precision": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "City": {
    "type": "object",
    "properties": {
     "slug": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "province": {
      "type": "string"
     },
     "province_name": {
      "type": "string"
     },
     "total": {
      "type": "integer"
     },
     "counts": {
      "type": "object",
      "additionalProperties": {
       "type": "integer"
      }
     },
     "url": {
      "type": "string"
     },
     "api_url": {
      "type": "string"
     }
    }
   },
   "Category": {
    "type": "object",
    "properties": {
     "slug": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "total": {
      "type": "integer"
     },
     "status": {
      "type": "string"
     },
     "api_url": {
      "type": "string"
     }
    }
   },
   "ListingBrief": {
    "type": "object",
    "required": [
     "id",
     "name",
     "category",
     "city",
     "province",
     "url"
    ],
    "properties": {
     "id": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "category": {
      "type": "string",
      "enum": [
       "vets",
       "pet-stores",
       "groomers",
       "boarding",
       "pet-friendly",
       "dog-parks",
       "shelters"
      ]
     },
     "city": {
      "type": "string"
     },
     "province": {
      "type": "string"
     },
     "city_slug": {
      "type": "string"
     },
     "address": {
      "$ref": "#/components/schemas/Address"
     },
     "phone": {
      "type": [
       "string",
       "null"
      ]
     },
     "website": {
      "type": [
       "string",
       "null"
      ]
     },
     "geo": {
      "$ref": "#/components/schemas/Geo"
     },
     "url": {
      "type": "string"
     },
     "api_url": {
      "type": "string"
     },
     "attribution": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "Listing": {
    "allOf": [
     {
      "$ref": "#/components/schemas/ListingBrief"
     },
     {
      "type": "object",
      "properties": {
       "slug": {
        "type": "string"
       },
       "subcategory": {
        "type": [
         "string",
         "null"
        ]
       },
       "schema_type": {
        "type": [
         "string",
         "null"
        ]
       },
       "email": {
        "type": [
         "string",
         "null"
        ]
       },
       "hours_text": {
        "type": [
         "string",
         "null"
        ]
       },
       "opening_hours": {
        "type": [
         "array",
         "null"
        ]
       },
       "emergency": {
        "type": [
         "boolean",
         "null"
        ]
       },
       "pet_details": {
        "type": "object"
       },
       "status": {
        "type": "string"
       },
       "confidence": {
        "type": "number"
       },
       "updated_at": {
        "type": "string"
       },
       "licences": {
        "type": "array",
        "items": {
         "type": "string"
        }
       },
       "sources": {
        "type": "array",
        "items": {
         "type": "object"
        }
       }
      }
     }
    ]
   },
   "Event": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "title": {
      "type": "string"
     },
     "start": {
      "type": "string",
      "format": "date-time"
     },
     "end": {
      "type": [
       "string",
       "null"
      ]
     },
     "venue": {
      "type": "string"
     },
     "city": {
      "type": "string"
     },
     "province": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "source_url": {
      "type": "string"
     },
     "listing_id": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   }
  }
 }
}