Skip to main content
To create a location, send a POST request to /locations:
curl -X POST https://api.qminder.com/locations \
  -H "X-Qminder-REST-API-Key: YOUR_API_KEY" \
  -H "X-Qminder-API-Version: 2020-09-01" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SF City Hall",
    "latitude": 37.7792792,
    "longitude": -122.4214304,
    "address": "1 Dr Carlton B Goodlett Pl, San Francisco, CA 94102, United States",
    "country": "US",
    "languages": ["en", "et", "fr-CA"]
  }'
Required fields:
  • name - Location name (max 30 characters)
  • latitude - Geographical latitude (-90 to 90)
  • longitude - Geographical longitude (-180 to 180)
  • address - Postal address (max 300 characters)
  • country - ISO 3166-1 alpha-2 country code (e.g. “US”, “CA”)
Optional fields:
  • languages - Languages available at this location (see below). Defaults to ["en"] if omitted.
  • inputFields - Custom input fields for the location (see below). If omitted, three default fields are created (first name, last name, phone number).
  • openingHours - Opening hours configuration (see below). If omitted, the location defaults to 24/7 (00:00-23:59 every day).
Response (201 Created):
{
  "id": "12345"
}

Languages

You can configure which languages are available at a location by providing an array of ISO 639 / BCP 47 language codes:
{
  "languages": ["en", "et", "fr-CA"]
}
  • The list must include "en" (English)
  • No duplicate codes allowed
  • All codes must be supported (e.g. en, et, fr, de, zh, zh-TW, fr-CA, pt-PT)
  • Order is preserved — the first language is the primary display language
  • If omitted, defaults to ["en"]

Input Fields

You can specify custom input fields to create with the location by providing an inputFields array. If omitted, three default fields are created: first name, last name, and phone number. Each field uses the same schema as the standalone Creating an Input Field endpoint, with these differences:
  • location — must not be provided (automatically set to the created location)
  • visibleForLines — must be omitted or empty (lines don’t exist yet at creation time)
  • id — required (client-generated UUID)
Constraints:
  • Must include at least one FIRST_NAME and one LAST_NAME field
  • Maximum 50 fields
  • FIRST_NAME, LAST_NAME, EMAIL, and PHONE_NUMBER are singleton types (only one of each allowed)
  • FIRST_NAME and LAST_NAME cannot have isMandatoryBeforeAdded or isMandatoryBeforeServed set to true
  • All field and option IDs must be unique within the request and globally
  • If fields include translations, the referenced language codes must be declared in the languages field
Example — creating a location with custom input fields:
curl -X POST https://api.qminder.com/locations \
  -H "X-Qminder-REST-API-Key: YOUR_API_KEY" \
  -H "X-Qminder-API-Version: 2020-09-01" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Downtown Office",
    "latitude": 37.7749,
    "longitude": -122.4194,
    "address": "123 Main St, San Francisco, CA 94105, United States",
    "country": "US",
    "languages": ["en", "es"],
    "inputFields": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440001",
        "type": "FIRST_NAME",
        "isMandatoryBeforeAdded": false,
        "isMandatoryBeforeServed": false,
        "isMandatoryInRemoteSignIn": false,
        "isVisibleInWaitingDrawer": true,
        "isVisibleInServingDrawer": true,
        "showInRemoteSignIn": true
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "type": "LAST_NAME",
        "isMandatoryBeforeAdded": false,
        "isMandatoryBeforeServed": false,
        "isMandatoryInRemoteSignIn": false,
        "isVisibleInWaitingDrawer": true,
        "isVisibleInServingDrawer": true,
        "showInRemoteSignIn": true
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440003",
        "type": "TEXT",
        "title": "Reason for visit",
        "visitorFacingTitle": "Why are you here today?",
        "isMandatoryBeforeAdded": true,
        "isMandatoryBeforeServed": false,
        "isMandatoryInRemoteSignIn": false,
        "isVisibleInWaitingDrawer": true,
        "isVisibleInServingDrawer": true,
        "showInRemoteSignIn": true,
        "translations": [
          { "languageCode": "es", "title": "Motivo de la visita", "visitorFacingTitle": "¿Por qué está aquí hoy?" }
        ]
      }
    ]
  }'
For full details on field types, options, translations, and constraints, see Creating an Input Field.

Opening Hours

You can set regular weekly hours and date-specific exceptions:
{
  "openingHours": {
    "regular": {
      "mon": { "businessHours": [{ "opens": { "hours": 9, "minutes": 0 }, "closes": { "hours": 17, "minutes": 0 } }] },
      "tue": { "businessHours": [{ "opens": { "hours": 9, "minutes": 0 }, "closes": { "hours": 17, "minutes": 0 } }] },
      "wed": { "businessHours": [{ "opens": { "hours": 9, "minutes": 0 }, "closes": { "hours": 17, "minutes": 0 } }] },
      "thu": { "businessHours": [{ "opens": { "hours": 9, "minutes": 0 }, "closes": { "hours": 17, "minutes": 0 } }] },
      "fri": { "businessHours": [{ "opens": { "hours": 9, "minutes": 0 }, "closes": { "hours": 17, "minutes": 0 } }] },
      "sat": { "closed": true },
      "sun": { "closed": true }
    },
    "exceptions": [
      { "date": "2026-05-01", "closed": true, "closedReason": "Holiday" },
      { "date": "2026-05-02", "businessHours": [{ "opens": { "hours": 10, "minutes": 0 }, "closes": { "hours": 15, "minutes": 0 } }] }
    ]
  }
}
Each day in regular can have either:
  • businessHours - An array of time ranges with opens and closes (each with hours 0-23 and minutes 0-59)
  • closed: true - The location is closed that day
Each entry in exceptions requires a date (ISO 8601 format) and can include:
  • closed and optional closedReason - Mark the date as closed
  • businessHours - Custom hours for that specific date

Error Responses

StatusDescriptionExample
400Name is blank{"code": "parameter_invalid_blank", "message": "...", "param": "name"}
400Name too long (>30 chars){"code": "parameter_invalid_size", "message": "...", "param": "name"}
400Invalid coordinates{"code": "parameter_too_large", "message": "...", "param": "latitude"}
400Invalid country code{"code": "parameter_invalid_country_code", "message": "...", "param": "country"}
400Invalid opening hours{"code": "parameter_invalid", "message": "...", "param": "openingHours"}
400Languages missing “en”{"code": "parameter_invalid", "message": "languages must include 'en'", "param": "languages"}
400Duplicate language codes{"code": "parameter_invalid", "message": "languages must not contain duplicates", "param": "languages"}
400Unsupported language code{"code": "language_code_not_supported", "message": "Language with the code 'xx' is not supported."}
400Invalid input field{"code": "parameter_invalid", "message": "...", "param": "inputFields"}
400Missing FIRST_NAME or LAST_NAME{"code": "parameter_invalid", "message": "...", "param": "inputFields"}
400More than 50 input fields{"code": "parameter_invalid", "message": "...", "param": "inputFields"}
400Duplicate field or option IDs{"code": "duplicate_items_in_request", "message": "..."}
400Duplicate singleton type{"code": "input_field_duplicate", "message": "..."}
400Translation language not in languages{"code": "parameter_invalid", "message": "...", "param": "inputFields"}
409Field or option ID already exists{"code": "input_field_duplicate", "message": "..."}