Kajaria Ceramics

Dashboard  /  GMB Reporting  /  v1

GMB
Reporting APIs

Google My Business performance and call history for Kajaria dealers. Look up stores by dealer SAP code or employee code, then pull day wise GMB performance for any store over any date range.

Endpoints
4
Method
POST
Format
JSON
Auth
API key header

How it works

Reports are fetched in two steps. First find which stores you are dealing with, then pull the detail for one store at a time.

Step 1 Find the stores Send a dealer SAP code or an employee code with a date range. You get every store under it, each with an encrypted store reference and its totals for the period.
Step 2 Pull the detail Send one storelookup from step 1 back, with the same or a narrower date range, to get day wise GMB performance or the call log.

Why the store reference is encrypted

Step 1 returns storelookup rather than the raw internal store ID. It is an AES-encrypted, signed value — send it back exactly as received, without URL-encoding or trimming it. An edited value is rejected rather than resolved to another store.

The same store always produces the same storelookup, so you can safely store it, cache it, or compare two responses to see whether they refer to the same store.

Dates

Base URL. All four endpoints live under https://dashboard.kajariaceramics.com/api/gmb/ and accept POST with a JSON body.

Authentication

The same key system as the Product Filter API. One key identifies one integration; requests without a valid key are rejected before any database work happens.

Header
X-API-KEY: kj_live_xxxxxxxxxxxxxxxx

Where custom headers are not possible, send "api_key" in the JSON body instead. It works the same way, but the key ends up in request logs more often.

No further filtering. A valid key can query any SAP code or employee code. There is no per-dealer or per-employee restriction, so treat any key as granting access to the whole reporting dataset and keep it server-side.

Dealer lookup

A SAP code may cover more than one store. This returns all of them, including stores that have no GMB data yet.

POST /api/gmb/dealer

Request

FieldTypeRequiredDescription
sap_codestringRequiredDealer SAP code
from_datestringRequiredStart of range, YYYY-MM-DD
to_datestringRequiredEnd of range, inclusive
JSON
{
  "sap_code": "1000234",
  "from_date": "2026-07-01",
  "to_date": "2026-07-31"
}

Response

JSON
{
  "code": 200,
  "status": true,
  "user": "dealer_portal",
  "sap_code": "1000234",
  "from_date": "2026-07-01",
  "to_date": "2026-07-31",
  "returned": 2,
  "data": [
    {
      "storelookup": "Zk9tR2h4...",
      "dealership_name": "Kajaria World Rohini",
      "city": "New Delhi",
      "state": "Delhi",
      "has_data": true,
      "message": "",
      "days_with_data": 31,
      "totals": {
        "total_search": 18420,
        "website_clicks": 342,
        "call_clicks": 210,
        "direction_requests": 985,
        "business_bookings": 0
      }
    },
    {
      "storelookup": "Qm5wT2p2...",
      "dealership_name": "Kajaria World Pitampura",
      "city": "New Delhi",
      "state": "Delhi",
      "has_data": false,
      "message": "No record found",
      "days_with_data": 0,
      "totals": {
        "total_search": 0,
        "website_clicks": 0,
        "call_clicks": 0,
        "direction_requests": 0,
        "business_bookings": 0
      }
    }
  ]
}
FieldTypeDescription
storelookupstringEncrypted store reference. Pass this to the day wise and call endpoints.
has_databooleanFalse when the store has no GMB rows in this period
messagestringEmpty, or No record found when has_data is false
days_with_dataintegerNumber of days in the range that have figures
totalsobjectMetrics summed across the whole range
If the SAP code itself is not in the dealer master, data comes back as an empty array with "message": "No record found" at the top level. That is a 200, not an error.

Employee lookup

Same shape as the dealer lookup, resolved through the employee-to-store mapping. Adds the employee's details and a grand total across all their stores.

POST /api/gmb/emp

Request

FieldTypeRequiredDescription
emp_codestringRequiredEmployee code
from_datestringRequiredStart of range, YYYY-MM-DD
to_datestringRequiredEnd of range, inclusive

Response

Each entry in data carries the same fields as the dealer lookup, plus sap_code. Two extra blocks appear at the top level:

JSON
{
  "code": 200,
  "status": true,
  "employee": {
    "emp_code": "E12345",
    "name": "Employee Name",
    "sales_off": "Delhi",
    "role": "Area Sales Manager"
  },
  "from_date": "2026-07-01",
  "to_date": "2026-07-31",
  "returned": 14,
  "message": "",
  "grand_totals": {
    "total_search": 204118,
    "website_clicks": 3912,
    "call_clicks": 2440,
    "direction_requests": 11002,
    "business_bookings": 0
  },
  "data": [ /* one entry per store */ ]
}
Unknown employee. An emp_code that is not in the employee table returns 404 with "Employee not found". This differs from the dealer lookup, which returns 200 with an empty list — an unknown employee is a mistake worth surfacing, whereas a dealer with no stores is a normal result.

Day Wise GMB Performance

One row per day for a single store. Returns the period totals alongside the rows, so a summary panel needs no second call.

POST /api/gmb/daywise

Request

FieldTypeRequiredDescription
storelookupstringRequiredStore reference from step 1, unmodified
from_datestringRequiredStart of range, YYYY-MM-DD
to_datestringRequiredEnd of range, inclusive
pageintegerOptional1-based. Defaults to 1.
limitintegerOptionalRows per page. Defaults to 31, capped at 366.
JSON
{
  "storelookup": "Zk9tR2h4...",
  "from_date": "2026-07-01",
  "to_date": "2026-07-31",
  "page": 1,
  "limit": 31
}

Response

JSON
{
  "code": 200,
  "status": true,
  "dealer": {
    "storelookup": "Zk9tR2h4...",
    "sap_code": "1000234",
    "dealership_name": "Kajaria World Rohini",
    "city": "New Delhi",
    "state": "Delhi"
  },
  "page": 1,
  "limit": 31,
  "returned": 31,
  "total": 31,
  "total_pages": 1,
  "has_more": false,
  "totals": {
    "total_search": 18420,
    "website_clicks": 342,
    "call_clicks": 210,
    "direction_requests": 985,
    "business_bookings": 0
  },
  "data": [
    {
      "performance_date": "2026-07-01",
      "total_search": 612,
      "website_clicks": 11,
      "call_clicks": 7,
      "direction_requests": 33,
      "business_bookings": 0,
      "desktop_search_impressions": 88,
      "mobile_search_impressions": 402,
      "desktop_maps_impressions": 24,
      "mobile_maps_impressions": 98
    }
  ]
}
totals always covers the full date range, not just the current page. total_search is the sum of the four impression columns, matching the figure shown on the dealer dashboard.

Call history

One row per call for a single store. This is where large result sets appear — a busy store over a long range can run to thousands of rows, so page through it.

POST /api/gmb/calls

Request

FieldTypeRequiredDescription
storelookupstringRequiredStore reference from step 1, unmodified
from_datestringRequiredStart of range, YYYY-MM-DD
to_datestringRequiredEnd of range, inclusive of the whole day
substatusstringOptionalFilter by call result, e.g. Answered, Missed
pageintegerOptional1-based. Defaults to 1.
limitintegerOptionalRows per page. Defaults to 50, capped at 500.

Response

JSON
{
  "code": 200,
  "status": true,
  "dealer": { /* same block as day wise */ },
  "page": 1,
  "limit": 50,
  "returned": 50,
  "total": 1284,
  "total_pages": 26,
  "has_more": true,
  "summary": {
    "total_calls": 1284,
    "connected_calls": 903,
    "missed_calls": 381,
    "total_minutes": 2140.75
  },
  "data": [
    {
      "call_log_id": "CL889231",
      "caller_number": "+919812345678",
      "call_start_time": "2026-07-31 17:42:11",
      "call_duration_minutes": 2.35,
      "did_number": "+911140001234",
      "call_event_type": "Inbound",
      "substatus": "Answered",
      "total_calls_from_caller": 3,
      "prev_calls_count": 2,
      "recording_url": "https://dashboard.kajariaceramics.com/gmb/audio/2050_CL889231.mp3"
    }
  ]
}

Notes on the fields

Caller numbers are personal data. This endpoint returns customer phone numbers and recordings of their calls. Do not expose the response directly to a browser, log it to a shared file, or include it in exports that circulate beyond the people who need it.

Errors

Errors return the same JSON shape with status: false and a message.

CodeMessageWhat it means
400Invalid JSONBody missing or malformed
400from_date and to_date are requiredOne or both dates missing
400Dates must be in YYYY-MM-DD formatIncludes real-looking but invalid dates such as 2026-02-30
400from_date cannot be later than to_dateRange is the wrong way round
400sap_code is requiredDealer lookup called without a SAP code
400emp_code is requiredEmployee lookup called without an employee code
400storelookup is requiredStep 2 called without a store reference
400Invalid storelookupReference was edited, truncated, or issued under a different key
401API key missingNo key in the header or the body
401Invalid API keyKey not recognised or revoked
404Employee not foundNo employee with that code
405Only POST allowedRequest used GET or another method
500Internal Server ErrorFailure on the server side
Empty is not an error. A valid request that matches no data returns 200 with "message": "No record found", zeroed totals and an empty data array. Check total or has_data rather than treating an empty list as a failure.

Worked example

Two calls, end to end: find a dealer's stores for July, then pull the day wise GMB performance for the first one.

Step 1 — find the stores

bash
curl -X POST https://dashboard.kajariaceramics.com/api/gmb/dealer \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: kj_live_xxxxxxxxxxxxxxxx" \
  -d '{"sap_code":"1000234","from_date":"2026-07-01","to_date":"2026-07-31"}'

Step 2 — pull the day wise GMB performance

bash
# storelookup copied from the step 1 response
curl -X POST https://dashboard.kajariaceramics.com/api/gmb/daywise \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: kj_live_xxxxxxxxxxxxxxxx" \
  -d '{"storelookup":"Zk9tR2h4...","from_date":"2026-07-01","to_date":"2026-07-31"}'

Paging through a long call log

js
let page = 1, all = [];

while (true) {
  const res = await fetch("https://dashboard.kajariaceramics.com/api/gmb/calls", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": process.env.KAJARIA_API_KEY
    },
    body: JSON.stringify({
      storelookup: storeRef,
      from_date: "2026-07-01",
      to_date: "2026-07-31",
      page: page,
      limit: 500
    })
  });

  const json = await res.json();
  if (!json.status) throw new Error(json.message);

  all.push(...json.data);

  if (!json.has_more) break;
  page++;
}