On this page

Developer documentation

Review Advisor API

Bring the data your cards collect into your own reporting, BI tool or CRM. The API is read-only, works with any language that can make an HTTPS request, and returns plain JSON.

Base URL

https://api.review-advisor.com/api/v1

What you can pull:

  • Locations, cards and links — the structure of your account.
  • Clicks — every tap on a button after a guest scans a card, per card, location and platform, raw or as daily totals.
  • Review Guard — every smiley rating (happy / neutral / unhappy) and the private comments guests left.
  • Surveys — your surveys, their questions and every response.
  • Online reviews — your Google and Tripadvisor reviews and ratings, plus the competitors you track.

Getting your API key

API access is switched on per account by the Review Advisor team. Once it's on:

  1. Sign in to the Review Advisor app (web or mobile).
  2. Open Account settings → API Access.
  3. Click Generate key and copy it straight away.
For your security the full key is shown only once. Store it like a password — in a secrets manager or an environment variable on your server, never in a website or mobile app. If you lose it or think it leaked, generate a new one: the old key stops working immediately.

A key reads every location you can see in the app — the ones you own and the ones shared with you — and nothing else. Keys look like ra_live_ followed by 40 characters.

Authentication

Send the key in the Authorization header of every request:

Authorization: Bearer ra_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

If your tool can't set that header, X-API-Key: ra_live_… works too. All requests must use HTTPS. Try it with your key:

curl "https://api.review-advisor.com/api/v1/account" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Requests & responses

  • Every endpoint is a GET request; filters go in the query string.
  • Responses are JSON. Field names are snake_case; the result is always under data.
  • Timestamps are ISO-8601 in UTC, e.g. 2026-10-26T09:24:50.648Z.
  • from and to take a date or a full datetime and are both inclusive: from=2026-10-01&to=2026-10-31 is the whole of October (UTC). Use datetimes with an offset for local days, e.g. from=2026-10-26T00:00:00+01:00.
  • Ids are stable integers — use them to link records together (a click's card.id matches an id from List cards).
  • Fields may be added to responses over time; your integration should ignore fields it doesn't know.

Pagination

List endpoints marked Paginated return up to limit items (default 100, max 500), oldest first, together with a pagination object:

{
  "data": [
    "…"
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "4123"
  }
}

To get the next page, repeat the same request with cursor=<next_cursor>. When has_more is false you have everything.

Tip for incremental syncs: the cursor is the id of the last item, and new items always get higher ids. Save the last next_cursor(or the id of the last row) you processed, and next time start from it — you'll receive only what arrived since.

Errors

Errors use standard HTTP status codes and always have the same body, so you can branch on code:

{
  "error": {
    "code": "invalid_parameter",
    "message": "\"from\" must be a date (YYYY-MM-DD) or an ISO-8601 datetime."
  }
}
StatuscodeMeaning
400invalid_parameterA query parameter has the wrong format or value. The message says which one.
401missing_api_keyNo key was sent. Add the Authorization header.
401invalid_api_keyThe key is wrong, or it was replaced by a newer one.
403api_access_disabledAPI access is switched off for your account. Contact us.
404not_foundThe endpoint doesn't exist, or the location / survey isn't one of yours.
429rate_limitedMore than 120 requests in a minute. Wait the number of seconds in the Retry-After header.
500server_errorSomething went wrong on our side. Retry later; if it keeps happening, contact us.

Rate limits

Each key can make 120 requests per minute. Every response tells you where you stand:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1793011260   (Unix time when the window resets)

Over the limit you get 429 rate_limited with a Retry-After header (seconds). A nightly export with limit=500needs only a handful of requests. Data is available in the API the moment it's collected, so there's no need to poll more often than you report.

Recipe: daily export

Most integrations run once a day — for example at 03:00 — and copy the previous day into a database or reporting tool. This script fetches all of yesterday's survey responses, Review Guard feedback and clicks, following every page and waiting when rate-limited:

# First page of yesterday's survey responses
curl "https://api.review-advisor.com/api/v1/survey-responses?from=2026-10-26&to=2026-10-26&limit=500" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

# While pagination.has_more is true, ask for the next page
curl "https://api.review-advisor.com/api/v1/survey-responses?from=2026-10-26&to=2026-10-26&limit=500&cursor=5120" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

For totals rather than raw rows, add Click statistics and Feedback summary for the same day. Online reviews are collected by our monitoring with a delay, so for reviews use the cursor (see Pagination) instead of a date window.

Endpoints

Account

The account the API key belongs to.

Get your account

GET/account

Returns the company the key belongs to and how many locations it can read. Handy as a first call to check that your key works.

No parameters.

curl "https://api.review-advisor.com/api/v1/account" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": {
    "id": 2,
    "company_name": "Museum of Illusions",
    "email": "operations@example.com",
    "locations_count": 9
  }
}

Endpoints

Locations & cards

A location is one venue with its own license — a hotel, a restaurant, a museum. Every location has NFC cards (or stands, stickers) that guests tap, and links: the buttons guests see after tapping, such as “Review us on Google”.

List locations

GET/locations

All locations you can see in the app — the ones you own and the ones shared with you.

No parameters.

curl "https://api.review-advisor.com/api/v1/locations" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 1,
      "name": "Museum of Illusions Zagreb",
      "industry": "Museum",
      "license_expires_at": "2027-09-25T10:00:00.000Z",
      "review_guard_enabled": true,
      "cards_count": 10,
      "created_at": "2026-09-22T04:54:01.498Z"
    },
    {
      "id": 2,
      "name": "Museum of Illusions Split",
      "industry": "Museum",
      "license_expires_at": "2027-09-25T10:00:00.000Z",
      "review_guard_enabled": false,
      "cards_count": 5,
      "created_at": "2026-09-22T04:54:41.485Z"
    }
  ]
}

Get a location

GET/locations/{id}

One location with its cards, its links (the buttons on the guest page) and its surveys.

Links can be grouped: a link with is_group: true is a folder, and the links inside it point to it with parent_id.

Parameters

  • idinteger · in pathrequired

    The location id.

curl "https://api.review-advisor.com/api/v1/locations/1" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": {
    "id": 1,
    "name": "Museum of Illusions Zagreb",
    "industry": "Museum",
    "license_expires_at": "2027-09-25T10:00:00.000Z",
    "review_guard_enabled": true,
    "cards_count": 2,
    "created_at": "2026-09-22T04:54:01.498Z",
    "cards": [
      {
        "id": 14,
        "location_id": 1,
        "label": "Ticket desk",
        "serial_number": "00100014",
        "slug": "00100014-1790053069938",
        "is_active": true,
        "created_at": "2026-09-22T04:57:49.939Z"
      },
      {
        "id": 15,
        "location_id": 1,
        "label": "Exit",
        "serial_number": "00100015",
        "slug": "00100015-1790053073002",
        "is_active": true,
        "created_at": "2026-09-22T04:57:53.003Z"
      }
    ],
    "links": [
      {
        "id": 11,
        "label": "Google",
        "url": "https://search.google.com/local/writereview?placeid=…",
        "platform": "google",
        "is_review_platform": true,
        "is_group": false,
        "parent_id": null,
        "position": 0
      },
      {
        "id": 12,
        "label": "Tripadvisor",
        "url": "https://www.tripadvisor.com/…",
        "platform": "tripadvisor",
        "is_review_platform": true,
        "is_group": false,
        "parent_id": null,
        "position": 1
      }
    ],
    "surveys": [
      {
        "id": 3,
        "title": "Visitor experience",
        "is_active": true
      }
    ]
  }
}

List cards

GET/cards

Every card of your locations. The label is the name you gave the card in the app, the serial number is printed on the card.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

curl "https://api.review-advisor.com/api/v1/cards?location_id=1" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 14,
      "location_id": 1,
      "label": "Ticket desk",
      "serial_number": "00100014",
      "slug": "00100014-1790053069938",
      "is_active": true,
      "created_at": "2026-09-22T04:57:49.939Z"
    }
  ]
}

Endpoints

Clicks

A click is recorded every time a guest taps a button on the page that opens when they scan a card — for example “Review us on Google”. Use the raw list to copy every event into your own system, or the stats endpoint for ready-made totals.

List clicksPaginated

GET/clicks

Every click, one row per tap, oldest first.

Clicks count toward the location the card belongs to now. If you move a card to another location in the app, its earlier clicks move with it.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • card_idinteger

    Only data collected through this card.

  • link_idinteger

    Only clicks on this link (button).

  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

  • limitintegerdefault 100

    Items per page, 1–500.

  • cursorstring

    The next_cursor from the previous page. Leave out for the first page.

curl "https://api.review-advisor.com/api/v1/clicks?from=2026-10-26&to=2026-10-26" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 4122,
      "clicked_at": "2026-10-26T09:24:50.648Z",
      "location_id": 1,
      "card": {
        "id": 14,
        "label": "Ticket desk"
      },
      "link": {
        "id": 11,
        "label": "Google",
        "platform": "google"
      }
    },
    {
      "id": 4123,
      "clicked_at": "2026-10-26T10:02:36.796Z",
      "location_id": 1,
      "card": {
        "id": 15,
        "label": "Exit"
      },
      "link": {
        "id": 12,
        "label": "Tripadvisor",
        "platform": "tripadvisor"
      }
    }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "4123"
  }
}

Click statistics

GET/stats/clicks

Click totals for a period, grouped by day, location, card or link. Days are calendar days in UTC; days without clicks are left out.

group_by=location returns { location_id, name, clicks } for every location, including those with 0 clicks.

group_by=card returns { card_id, label, location_id, clicks }; group_by=link returns { link_id, label, platform, location_id, clicks }. Both are sorted by clicks, highest first.

Parameters

  • group_bystringdefault day

    How to group the totals.

    daylocationcardlink
  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • card_idinteger

    Only data collected through this card.

  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

curl "https://api.review-advisor.com/api/v1/stats/clicks?group_by=day&from=2026-10-01&to=2026-10-31" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "date": "2026-10-09",
      "clicks": 6
    },
    {
      "date": "2026-10-10",
      "clicks": 43
    },
    {
      "date": "2026-10-11",
      "clicks": 30
    }
  ],
  "meta": {
    "group_by": "day",
    "from": "2026-10-01T00:00:00.000Z",
    "to": "2026-10-31T23:59:59.999Z",
    "total_clicks": 79
  }
}

Endpoints

Review Guard

With Review Guard on, guests first rate their visit with a smiley. Happy guests go on to the review platforms; neutral and unhappy guests can leave a private comment for you instead. Every rating is stored as feedback.

List feedbackPaginated

GET/review-guard/feedback

Every smiley rating, with the guest's comment when they left one. Oldest first.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • card_idinteger

    Only data collected through this card.

  • moodstring

    Only ratings with this mood.

    happyneutralunhappy
  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

  • limitintegerdefault 100

    Items per page, 1–500.

  • cursorstring

    The next_cursor from the previous page. Leave out for the first page.

curl "https://api.review-advisor.com/api/v1/review-guard/feedback?mood=unhappy&from=2026-10-01" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 812,
      "location_id": 1,
      "card": {
        "id": 14,
        "label": "Ticket desk"
      },
      "mood": "happy",
      "comment": null,
      "created_at": "2026-10-26T09:24:51.014Z"
    },
    {
      "id": 813,
      "location_id": 1,
      "card": {
        "id": 15,
        "label": "Exit"
      },
      "mood": "unhappy",
      "comment": "The queue at the entrance was too long.",
      "created_at": "2026-10-26T11:40:12.371Z"
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}

Feedback summary

GET/review-guard/summary

Ratings per location for a period: how many guests were happy, neutral and unhappy, and the share of happy guests. happy_percent is null when a location has no ratings.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

curl "https://api.review-advisor.com/api/v1/review-guard/summary?from=2026-10-01&to=2026-10-31" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "location_id": 1,
      "name": "Museum of Illusions Zagreb",
      "total": 240,
      "happy": 221,
      "neutral": 12,
      "unhappy": 7,
      "happy_percent": 92.1
    },
    {
      "location_id": 2,
      "name": "Museum of Illusions Split",
      "total": 0,
      "happy": 0,
      "neutral": 0,
      "unhappy": 0,
      "happy_percent": null
    }
  ],
  "meta": {
    "from": "2026-10-01T00:00:00.000Z",
    "to": "2026-10-31T23:59:59.999Z"
  }
}

Endpoints

Surveys

Surveys you built in the app and every response guests submitted. A survey belongs to one location; responses remember the card the guest came from.

List surveys

GET/surveys

Your surveys with their questions. Use the question ids to match the answers in responses.

Question types: rating (1–5 stars), scale (numbers, e.g. 0–10, see the scale object), choice (one option), multi (several options), text (free text).

is_review_guard_survey: true marks the survey Review Guard sends neutral and unhappy guests to.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

curl "https://api.review-advisor.com/api/v1/surveys" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 3,
      "location_id": 1,
      "title": "Visitor experience",
      "description": null,
      "is_active": true,
      "is_review_guard_survey": false,
      "responses_count": 418,
      "questions": [
        {
          "id": 21,
          "text": "How would you rate your visit?",
          "type": "rating",
          "required": true,
          "position": 0,
          "options": null
        },
        {
          "id": 22,
          "text": "How likely are you to recommend us to a friend?",
          "type": "scale",
          "required": true,
          "position": 1,
          "options": null,
          "scale": {
            "min": 0,
            "max": 10,
            "allow_na": false,
            "min_label": "Not likely",
            "max_label": "Very likely"
          }
        },
        {
          "id": 23,
          "text": "Which rooms did you enjoy most?",
          "type": "multi",
          "required": false,
          "position": 2,
          "options": [
            "Vortex Tunnel",
            "Ames Room",
            "Infinity Room"
          ],
          "allow_other": true,
          "max_select": null
        },
        {
          "id": 24,
          "text": "Anything we could do better?",
          "type": "text",
          "required": false,
          "position": 3,
          "options": null
        }
      ],
      "created_at": "2026-09-25T08:12:44.120Z"
    }
  ]
}

List survey responsesPaginated

GET/survey-responses

Every submitted response with its answers, oldest first. Answers come typed: a number for rating and scale questions, an array of strings for multi, a string for choice and text.

An “Other” answer the guest typed in is returned as "Other: <their text>". A scale question that allows it can be answered "N/A". card is null when the guest opened the survey link directly instead of tapping a card.

Parameters

  • survey_idinteger

    Only responses to this survey.

  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • card_idinteger

    Only data collected through this card.

  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

  • limitintegerdefault 100

    Items per page, 1–500.

  • cursorstring

    The next_cursor from the previous page. Leave out for the first page.

curl "https://api.review-advisor.com/api/v1/survey-responses?survey_id=3&from=2026-10-26&to=2026-10-26" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 5120,
      "survey_id": 3,
      "survey_title": "Visitor experience",
      "location_id": 1,
      "card": {
        "id": 15,
        "label": "Exit"
      },
      "submitted_at": "2026-10-26T14:03:27.551Z",
      "answers": [
        {
          "question_id": 21,
          "question": "How would you rate your visit?",
          "type": "rating",
          "value": 5
        },
        {
          "question_id": 22,
          "question": "How likely are you to recommend us to a friend?",
          "type": "scale",
          "value": 9
        },
        {
          "question_id": 23,
          "question": "Which rooms did you enjoy most?",
          "type": "multi",
          "value": [
            "Vortex Tunnel",
            "Other: The gift shop"
          ]
        },
        {
          "question_id": 24,
          "question": "Anything we could do better?",
          "type": "text",
          "value": "More benches in the last room."
        }
      ]
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}

Endpoints

Online reviews

Public reviews of your locations on Google and Tripadvisor, and the ratings of the competitors you track — as collected by Review Advisor's competitor monitoring. A location appears here once its own business profile is connected in the Competitors screen.

List reviewsPaginated

GET/reviews

Reviews of your own locations, in the order we collected them. from and to filter on the date the review was published.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

  • sourcestring

    Only reviews from this platform.

    googletripadvisor
  • fromdate

    Start of the period, inclusive. A date (2026-10-01, from midnight UTC) or an ISO-8601 datetime.

  • todate

    End of the period, inclusive. A date (2026-10-31, until 23:59:59 UTC) or an ISO-8601 datetime.

  • limitintegerdefault 100

    Items per page, 1–500.

  • cursorstring

    The next_cursor from the previous page. Leave out for the first page.

curl "https://api.review-advisor.com/api/v1/reviews?source=google&from=2026-10-01" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 1990,
      "location_id": 1,
      "source": "google",
      "external_id": "Ci9DQUlRQUNvZENodHljRjlvT2tWTVdqUm1URjg0Y1ZrM1ZuRkxhVnB0TVZWa1NXYxAB",
      "rating": 5,
      "text": "Loved it, the kids had a great time!",
      "author": "Ana K.",
      "published_at": "2026-10-17T10:40:36.000Z"
    }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "1990"
  }
}

List ratings & competitors

GET/competitors

The current Google and Tripadvisor rating of each location (is_self: true) and of the competitors you track next to it.

Parameters

  • location_idinteger

    Only data of this location. Leave out for all your locations.

curl "https://api.review-advisor.com/api/v1/competitors" \
  -H "Authorization: Bearer $REVIEW_ADVISOR_API_KEY"

Response · 200

{
  "data": [
    {
      "id": 4,
      "location_id": 1,
      "name": "Museum of Illusions Zagreb",
      "address": "Ilica 72, 10000 Zagreb",
      "is_self": true,
      "google": {
        "place_id": "ChIJ…",
        "rating": 4.7,
        "total_reviews": 12840,
        "synced_at": "2026-10-27T02:00:53.848Z"
      },
      "tripadvisor": {
        "url": "https://www.tripadvisor.com/…",
        "rating": 4.5,
        "total_reviews": 3120,
        "synced_at": "2026-10-27T02:05:10.002Z"
      }
    },
    {
      "id": 5,
      "location_id": 1,
      "name": "Another attraction",
      "address": "…",
      "is_self": false,
      "google": {
        "place_id": "ChIJ…",
        "rating": 4.3,
        "total_reviews": 4267,
        "synced_at": "2026-10-27T02:01:34.183Z"
      },
      "tripadvisor": null
    }
  ]
}

Support & changes

This is version 1 of the API. We only add to it — new endpoints, new fields, new filters — without breaking what you've built. If we ever need a breaking change, it will come as /v2and we'll let you know well in advance.

Prefer to explore in a tool? Download the OpenAPI file and import it into Postman, Insomnia or your code generator.

Need a field or endpoint that isn't here?

Tell us what you're building — we're happy to help with your integration.

hi@review-advisor.com