---
title: Introduction
description: Look up the customer behind a Just-tap tag.
---

A customer taps a Just-tap tag at your terminal. A customer query tells you who that customer is, and which mobile-money numbers are on the tag.

Send the tag with your merchant, terminal, reference, and amount. You can list the queries you have already sent, and later report whether the terminal transaction was successful or failed.

## Environments

The paths below are the same on both hosts. Use the sandbox while you integrate. Use production for live terminals. The API reference lets you switch host when you try a request.

| Environment | Host                                 |
| ----------- | ------------------------------------ |
| Sandbox     | `https://api-uat.cards.justtap.io`   |
| Production  | `https://api.cards.justtap.io`       |

## Authentication

Send your API key in the `x-api-key` header on every request. Just-tap issues the key. The key identifies your organization, so you do not send a partner id in the body.

```http
POST /api/v1/partners/customer-queries
x-api-key: <your-api-key>
Content-Type: application/json
```

A missing, invalid, revoked, or expired key returns `401`. A key that cannot run customer queries returns `403`.

## Submit a customer query

```http
POST /api/v1/partners/customer-queries
```

`tagId` is the tag the customer tapped. `referenceId` is your id for this query, and it has to be unique. `merchantId` is your id for the shop. The first time we see that id for your organization, we store `merchantName`. Later queries for the same id keep that name. Leave `currency` out to use `ZMW`. Send the mobile money provider's `externalId` when you report the terminal result.

```json
{
  "merchantId": "YKrpx3FrpVHWjmIwpqMt",
  "merchantName": "Young Phiroz",
  "terminalId": "D1K0600000849",
  "referenceId": "8244c279-d76c-4e30-ad3b-9efdb12ca692",
  "amount": 10,
  "tagId": "VZ9T7GM1EYV5MZ"
}
```

A successful request returns `201`. The query is inside `data`, with the customer's name and every mobile-money number on the tag. Just-tap adds a service charge of 1 kwacha.

```json
{
  "data": {
    "id": "b5d746b3-d379-4900-b392-d5045abfb22c",
    "partner": {
      "partnerId": "edfa86b6-411e-4e66-a681-0cc61abba40e",
      "partnerName": "Your Organization"
    },
    "customer": {
      "firstName": "Jane",
      "lastName": "Mwansa"
    },
    "tag": {
      "tagId": "VZ9T7GM1EYV5MZ",
      "tagNumber": "TAG-000123",
      "mobileNumbers": [
        {
          "operator": "airtel_money",
          "mobileNumber": "260970371467",
          "status": "active"
        }
      ],
      "status": "active"
    },
    "transaction": {
      "merchantId": "YKrpx3FrpVHWjmIwpqMt",
      "merchantName": "Young Phiroz",
      "terminalId": "D1K0600000849",
      "referenceId": "8244c279-d76c-4e30-ad3b-9efdb12ca692",
      "externalId": null,
      "currency": "ZMW",
      "amount": 10,
      "serviceCharge": 1,
      "totalAmount": 11,
      "status": "pending"
    },
    "createdAt": "2025-04-29T10:00:00.000Z",
    "updatedAt": "2025-04-29T10:00:00.000Z"
  }
}
```

The tag must exist, be active, and have at least one mobile number. Sending a `referenceId` you have already used returns `409`.

## List your queries

```http
GET /api/v1/partners/customer-queries
```

This returns the queries submitted with your API key. `page` starts at 1. `perPage` defaults to 25 and cannot be higher than 100. The response body is `{ data, metadata }`.

Each item is shorter than the record you get when you submit a query. The customer is identified by tag id and mobile number, not by name.

## Report the terminal result

When the terminal finishes the transaction, tell us how it ended. Send `successful` or `failed`, the mobile money provider's `externalId`, and the query `id`, your `referenceId`, or both when they refer to the same query.

The query starts as `pending`. A later report replaces that status and stores the provider id. Sending the same status and provider id again returns the current record. A query that belongs to another organization returns `404`.

```http
POST /api/v1/partners/customer-queries/status
```

```json
{
  "referenceId": "8244c279-d76c-4e30-ad3b-9efdb12ca692",
  "externalId": "MM984221",
  "status": "successful"
}
```

A `200` response is the same `{ data }` record you get when you submit a query, with `transaction.status` updated.

## When something goes wrong

Responses are JSON. Timestamps are ISO 8601.

A failed request looks like this:

```json
{
  "error": "E_ALREADY_EXISTS",
  "message": "A customer query with reference 8244c279-d76c-4e30-ad3b-9efdb12ca692 already exists"
}
```

If the request itself is invalid, the status is `422` and the body also includes `errors`. Each entry has `field`, `rule`, and `message`.
