# Get the calling key

> Who the calling key is: its name, the workspace it acts in, the scopes it holds, and which of them it can use right now. Make this the first call an integration makes: it confirms the key works and tells you in one answer what it may do, instead of one 403 at a time.

Source: https://docs.xplantpro.com/docs/api/account/get-me

`GET https://app.xplantpro.com/api/v1/me`

- Required scope: none
- Credentials: workspace API key (`xpk_`)
- Idempotency-Key: ignored on this endpoint

A key never does more than its owner can in xPlant. `effectiveScopes` drops any scope above the owner's current role, and on a plan that includes connected devices only (`apiAccess: "devices"`) it keeps just the device scopes.

It needs no scope, and it returns nothing about the workspace beyond its id.

## Example

**curl**

```bash
curl https://app.xplantpro.com/api/v1/me \
  -H "Authorization: Bearer $XPLANT_API_KEY"
```

**JavaScript**

```js
import { XPlantClient } from "@shmaplex/xplant-sdk";

const client = new XPlantClient({ apiKey: process.env.XPLANT_API_KEY });

const me = await client.me.get();
console.log(me.scopes); // e.g. ["read:plants", "write:sensor_readings"]
```

**Python**

```python
import os
import requests

resp = requests.get(
    "https://app.xplantpro.com/api/v1/me",
    headers={"Authorization": f"Bearer {os.environ['XPLANT_API_KEY']}"},
    timeout=10,
)
body = resp.json()
if not body["ok"]:
    raise RuntimeError(f"{resp.status_code} {body['code']}: {body['error']}")
me = body["data"]
```

## Response

`200` with `{ "ok": true, "data": … }`. `data` holds the result.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | object | Yes | The key this request was made with. |
| `key.id` | string (uuid) | Yes | The key's id. |
| `key.name` | string | Yes | The name the key was given when it was created. |
| `key.prefix` | string | Yes | The visible start of the key, as xPlant's key list shows it. Never the whole key. |
| `key.environment` | string | Yes | `production` for an `xpk_live_` key, `development` for an `xpk_dev_` key. Both act on the same workspace. |
| `key.status` | string | Yes | Always `active` here: a revoked key is refused before this endpoint answers. |
| `key.lastUsedAt` | string \| null | Yes | When the key was used before this request, or null if this is its first. |
| `key.createdAt` | string | Yes | When the key was created. |
| `scopes` | string[] | Yes | Every scope the key was created with, such as `read:plants` or `write:transfers`. |
| `effectiveScopes` | string[] | Yes | The scopes the key can use right now: its scopes, capped at what its owner's current role may do in xPlant and at what the workspace's plan includes. Check here before calling rather than discovering a limit from a `403` or a `402`. |
| `role` | string | Yes | The key owner's role in the workspace as of this request: `owner`, `admin`, `manager`, `member`, `viewer` or `guest`. A key never does more than this role can in xPlant. |
| `apiAccess` | `"full"` \| `"devices"` | Yes | `full` when the workspace's plan includes the API (xPlant+ Teams and Enterprise). `devices` on plans that include connected devices only: the key can register devices, manage their tokens, and post their readings and events. |
| `workspace` | object | Yes | The workspace the key acts in. A key belongs to exactly one. |
| `workspace.id` | string (uuid) | Yes | The workspace's id. |
| `user` | object | Yes | The xPlant account the key belongs to. |
| `user.id` | string \| null (uuid) | Yes | The person the key belongs to. |

```json title="Response"
{
  "ok": true,
  "data": {
    "key": {
      "id": "3f6a2c1e-9b7d-4e21-8c5a-1d0e7f9b2a64",
      "name": "Bench station 3",
      "prefix": "xpk_live_4f1c9e2ab70",
      "environment": "production",
      "status": "active",
      "lastUsedAt": "2026-09-24T17:02:11.000Z",
      "createdAt": "2026-08-30T09:15:00.000Z"
    },
    "scopes": [
      "read:plants",
      "read:transfers",
      "write:transfers"
    ],
    "effectiveScopes": [
      "read:plants",
      "read:transfers",
      "write:transfers"
    ],
    "role": "member",
    "apiAccess": "full",
    "workspace": {
      "id": "8c2d4f6a-1b3e-4a5c-9d7e-0f1a2b3c4d5e"
    },
    "user": {
      "id": "0d7e4b9a-6f21-4c3e-8a5b-2e9f1c7d4a60"
    }
  }
}
```

| Response header | Meaning |
| --- | --- |
| `X-Request-Id` | Identifies this request. Include it when you contact support. |

## Errors

| Status | Code | When |
| --- | --- | --- |
| `401` | `UNAUTHORIZED` | The key is missing, malformed or revoked, or its owner is no longer a member of the workspace. |
| `402` | `PAID_PLAN_REQUIRED` | The workspace's plan does not include the API. The full API is included with xPlant+ Teams and Enterprise; on Hobby and Pro Lab, keys can connect devices only. |
| `403` | `DEVICE_TOKEN_NOT_ACCEPTED` | A device token was sent; this operation needs a workspace API key. |
| `429` | `RATE_LIMIT_EXCEEDED` | Too many requests for this key, device token or workspace. Wait `Retry-After` seconds. |

This endpoint can also answer a `5xx` with a `…_FAILED` code, which is safe to retry later. Branch on `code`, never on the `error` text. See [Errors](https://docs.xplantpro.com/docs/errors.md).
