Tracking terminal re-authentication between locations

Greetings, we are currently exploring the use of Square Terminals for integration with in-house POS system and one detail seems to strike me odd: Location users can authenticate multiple terminals for multiple locations (and even more, do multiple sessions for single terminal on the same location).

What is confusing, there seems to be no quick programmatic way to understand on which location a given terminal is currently having an open session.

Here is a test scenario:

  • Create Location A and B
  • For Loc. A request new device code
  • Authenticate terminal with Loc. A, then logout.
  • Observe terminal still being associated in /devices/codes endpoint
  • For Loc. B request new device code
  • Authenticate terminal with Loc. B
  • Observe terminal being associated with both Loc. A and Loc. B in /devices/codes, but location is changed in list devices

At this point it seems that observing device.code.pairing works, but in fact is only usable for the first time: Device codes are multi-use and need to be deleted from merchant dashboard.

The workaround I see now is polling /devices endpoint periodically, however this has caveat:
Even after deleting device codes from dashboard the terminal is still listed on the last location it was used on.

So request is:

  • Can we have device.authenticated webhook — happens on each login action
    OR
  • Can we have device.logged_out webhook — happens on each logout?

Hey @postolati-oksana! This behavior for terminal pairing is intentional. Device codes are meant to be re-usable, not one-time logins. After a device code has been paired with a terminal for the first time, it becomes associated with that device and can be unpaired and re-paired at any time.

With the ListDeviceCodes endpoint, you can use the status field to check whether the code is actively paired with a device or not. It will have a value of PAIRED if so.

Hey @josh-square, thanks for prompt reply. I think I did not make the problem clear in initial message.

Indeed, codes are used for multi-login and that is fine. The problem I struggle with is understanding if for a given location there is any usable terminal to use for a checkout.

Here is an example I have right now: 2 locations, both have the same terminal paired:

{
  "device_codes": [
    {
      "id": "9CTB0ADZP7ZN1",
      "name": "EDITED",
      "code": "EDITED",
      "device_id": "508CS145C1000405",
      "product_type": "TERMINAL_API",
      "location_id": "LDHWD4HV1HTYE",
      "created_at": "2025-07-02T08:37:32.000Z",
      "status": "PAIRED",
      "status_changed_at": "2025-07-02T08:38:08.000Z",
      "paired_at": "2025-07-02T08:38:08.000Z"
    },
    {
      "id": "E27C7Q2WN1CJK",
      "name": "EDITED",
      "code": "EDITED",
      "device_id": "508CS145C1000405",
      "product_type": "TERMINAL_API",
      "location_id": "MAN4KV5S0VRFP",
      "created_at": "2025-07-02T08:36:11.000Z",
      "status": "PAIRED",
      "status_changed_at": "2025-07-02T08:36:46.000Z",
      "paired_at": "2025-07-02T08:36:46.000Z"
    }
  ]
}

At the point of request the terminal stays on “Sign in” page.

Now if I check device listing from /devices endpoint I get this:

{
  "devices": [
    {
      "id": "device:508CS145C1000405",
      "attributes": {
        "type": "TERMINAL",
        "manufacturer": "Square",
        "model": "Square Terminal (1st Gen, v2)",
        "name": "Square ターミナル 0405",
        "manufacturers_id": "508CS145C1000405",
        "updated_at": "2025-07-03T02:10:10.754Z",
        "version": "5.57.0122",
        "merchant_token": "EDITED"
      },
      "components": [
        {
          "type": "APPLICATION",
          "application_details": {
            "application_type": "TERMINAL_API",
            "version": "6.71.2",
            "session_location": "MAN4KV5S0VRFP",
            "device_code_id": "E27C7Q2WN1CJK"
          }
        },
        {
          "type": "CARD_READER",
          "card_reader_details": {...}
        },
        {
          "type": "BATTERY",
          "battery_details": {...}
        },
        {
          "type": "WIFI",
          "wifi_details": {...}
        },
        {
          "type": "ETHERNET",
          "ethernet_details": {...}
        }
      ],
      "status": {
        "category": "AVAILABLE"
      }
    }
  ]
}

Which means the terminal is still deemed usable on location MAN4KV5S0VRFP, but this is not exactly true. Sending checkout request to the terminal in this location produces pending checkout that will timeout, but no error or indication of no terminal being available at this point.

Sorry for the misunderstanding! Retrieving the device (via the /devices endpoint) should be what you need to do here. I would expect that in the components array, that object with application_type of TERMINAL_API would have its session_location updated based on which location’s device code was last used to log in.

I tested with my own terminal and device codes for two different locations, and that’s the behavior I’m experiencing. Are you not seeing that happen in your API response?

There is a slight delay, but this does work as intended as long as you log out, enter different login code and check devices.

However, if you just log out from terminal or switch it off completely, the /devices endpoint will still display the last used location inside session_location property.

@postolati-oksana Yes, that’s correct; session_location will only include the last paired location. If you need real-time device information, you might want to consider using the PING Terminal action instead:
Check Device Information for a Square Terminal

The action will only complete if the Terminal is paired, and the device_metadata should include the location_id currently logged into the device.

Yes, this seems to be the only viable workaround at this point.

Then one can distinguish terminal that is attached to location and terminal that is logged out (or shut down) by issuing PING, then waiting for action timeout. No fast way to detect this it seems.