Summary and recommendation
Square's Team API (base URL: `https://connect.squareup.com/v2`) supports create, retrieve, update, search, bulk-create, and status-based deactivation of team members.
Auth is OAuth 2.0 Bearer token or personal access token;
required scopes are `EMPLOYEES_READ` and `EMPLOYEES_WRITE` for team member lifecycle operations.
Square does not expose a native SCIM 2.0 endpoint - IdP integrations (Okta, Entra ID, OneLogin) cover SSO/SAML only, not automated provisioning.
Any identity graph that needs to reflect Square team member state must be built and maintained against the Team API directly.
Key structural constraints to wire into your integration: - `POST /v2/team-members/search` is the only way to list or filter team members; there is no `GET /v2/team-members` collection endpoint. - All update operations (`PUT /v2/team-members/{id}`, `PUT /v2/team-members/{id}/wage-setting`) use full-replace semantics - omitting fields clears them. - Hard deletion is not supported; set `status: INACTIVE` to offboard. - `idempotency_key` is required on create operations and is valid for 24 hours.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (Bearer token) or personal access token |
| Base URL | Official docs |
| SCIM available | No |
Authentication
Auth method: OAuth 2.0 (Bearer token) or personal access token
Setup steps
- Register an application at https://developer.squareup.com/apps to obtain a client_id and client_secret.
- Direct the merchant/user to Square's OAuth authorization URL: https://connect.squareup.com/oauth2/authorize with required scopes.
- Exchange the returned authorization code for an access token via POST https://connect.squareup.com/oauth2/token.
- Include the access token in all API requests as: Authorization: Bearer {access_token}.
- For personal access tokens (own account only), retrieve from the Developer Dashboard and use directly as the Bearer token.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| EMPLOYEES_READ | Read team member profiles and employment details. | Listing and retrieving team members |
| EMPLOYEES_WRITE | Create and update team member profiles. | Creating, updating, or deactivating team members |
| TIMECARDS_READ | Read shift and timecard data for team members. | Reading shift/timecard records |
| TIMECARDS_WRITE | Create and update shift and timecard data. | Writing shift/timecard records |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique Square-assigned team member ID. | auto-generated | immutable | Format: TM{alphanumeric} |
| reference_id | string | Optional external/third-party identifier for the team member. | optional | updatable | Useful for syncing with external HR systems. |
| is_owner | boolean | Whether the team member is the account owner. | auto-set | immutable | Only one team member per account can be the owner. |
| status | enum | Employment status: ACTIVE or INACTIVE. | required | updatable | Set to INACTIVE to deactivate (soft delete). |
| given_name | string | Team member's first name. | optional | updatable | |
| family_name | string | Team member's last name. | optional | updatable | |
| email_address | string | Team member's email address. | optional | updatable | Used for Square account login if team member has a Square account. |
| phone_number | string | Team member's phone number in E.164 format. | optional | updatable | |
| created_at | string (RFC 3339) | Timestamp when the team member record was created. | auto-generated | immutable | |
| updated_at | string (RFC 3339) | Timestamp of the last update to the team member record. | auto-generated | auto-updated | |
| assigned_locations | object | Locations the team member is assigned to. Contains assignment_type (ALL_CURRENT_AND_FUTURE_LOCATIONS or EXPLICIT_LOCATIONS) and location_ids array. | optional | updatable | |
| wage_setting | object | Wage and job assignment details. Contains job_assignments array and is_overtime_exempt boolean. | optional (set via separate endpoint) | updatable via UpdateWageSetting | Managed via /v2/team-members/{id}/wage-setting endpoint. |
Core endpoints
Create Team Member
- Method: POST
- URL:
https://connect.squareup.com/v2/team-members - Watch out for: idempotency_key is required to prevent duplicate creation on retries. Must be unique per request.
Request example
POST /v2/team-members
{
"idempotency_key": "uuid-here",
"team_member": {
"given_name": "Jane",
"family_name": "Doe",
"email_address": "jane@example.com",
"status": "ACTIVE"
}
}
Response example
{
"team_member": {
"id": "TMabc123",
"given_name": "Jane",
"family_name": "Doe",
"status": "ACTIVE",
"created_at": "2024-01-01T00:00:00Z"
}
}
Retrieve Team Member
- Method: GET
- URL:
https://connect.squareup.com/v2/team-members/{team_member_id} - Watch out for: Returns 404 if the team member ID does not exist in the authenticated merchant's account.
Request example
GET /v2/team-members/TMabc123
Response example
{
"team_member": {
"id": "TMabc123",
"given_name": "Jane",
"family_name": "Doe",
"status": "ACTIVE",
"email_address": "jane@example.com"
}
}
Update Team Member
- Method: PUT
- URL:
https://connect.squareup.com/v2/team-members/{team_member_id} - Watch out for: This is a full PUT (replace), not a PATCH. Omitting fields may clear existing values. Send the full team_member object.
Request example
PUT /v2/team-members/TMabc123
{
"team_member": {
"given_name": "Jane",
"family_name": "Smith",
"status": "ACTIVE"
}
}
Response example
{
"team_member": {
"id": "TMabc123",
"given_name": "Jane",
"family_name": "Smith",
"updated_at": "2024-06-01T12:00:00Z"
}
}
Deactivate Team Member
- Method: PUT
- URL:
https://connect.squareup.com/v2/team-members/{team_member_id} - Watch out for: Square does not support hard deletion of team members via API. Set status to INACTIVE to deactivate.
Request example
PUT /v2/team-members/TMabc123
{
"team_member": {
"status": "INACTIVE"
}
}
Response example
{
"team_member": {
"id": "TMabc123",
"status": "INACTIVE",
"updated_at": "2024-06-01T13:00:00Z"
}
}
Search Team Members
- Method: POST
- URL:
https://connect.squareup.com/v2/team-members/search - Watch out for: Search uses POST, not GET. Cursor-based pagination; pass cursor from response to retrieve next page.
Request example
POST /v2/team-members/search
{
"query": {
"filter": {
"status": "ACTIVE",
"location_ids": ["LXYZ"]
}
},
"limit": 50
}
Response example
{
"team_members": [...],
"cursor": "next_page_cursor_string",
"errors": []
}
Bulk Create Team Members
- Method: POST
- URL:
https://connect.squareup.com/v2/team-members/bulk-create - Watch out for: Request body uses a map keyed by client-defined idempotency keys. Partial failures are returned per-key in the response.
Request example
POST /v2/team-members/bulk-create
{
"team_members": {
"key1": {"team_member": {"given_name": "Alice", "status": "ACTIVE"}},
"key2": {"team_member": {"given_name": "Bob", "status": "ACTIVE"}}
}
}
Response example
{
"team_members": {
"key1": {"team_member": {"id": "TM001", ...}},
"key2": {"team_member": {"id": "TM002", ...}}
}
}
Retrieve Wage Setting
- Method: GET
- URL:
https://connect.squareup.com/v2/team-members/{team_member_id}/wage-setting - Watch out for: Wage settings are managed separately from the core team member object.
Request example
GET /v2/team-members/TMabc123/wage-setting
Response example
{
"wage_setting": {
"team_member_id": "TMabc123",
"job_assignments": [{"job_title": "Cashier", "pay_type": "HOURLY"}],
"is_overtime_exempt": false
}
}
Update Wage Setting
- Method: PUT
- URL:
https://connect.squareup.com/v2/team-members/{team_member_id}/wage-setting - Watch out for: Full replace semantics. All job_assignments must be included; omitted assignments will be removed.
Request example
PUT /v2/team-members/TMabc123/wage-setting
{
"wage_setting": {
"job_assignments": [{"job_title": "Manager", "pay_type": "SALARY"}],
"is_overtime_exempt": true
}
}
Response example
{
"wage_setting": {
"team_member_id": "TMabc123",
"job_assignments": [{"job_title": "Manager", "pay_type": "SALARY"}],
"is_overtime_exempt": true
}
}
Rate limits, pagination, and events
- Rate limits: Square enforces per-endpoint rate limits. The Team API allows up to 35 requests per second per application by default. Limits vary by endpoint category.
- Rate-limit headers: Yes
- Retry-After header: No
- Rate-limit notes: Square returns HTTP 429 when rate limits are exceeded. The X-RateLimit-Limit and X-RateLimit-Remaining headers are documented. Retry-After header behavior is not explicitly documented in official sources.
- Pagination method: cursor
- Default page size: 100
- Max page size: 200
- Pagination pointer: cursor
| Plan | Limit | Concurrent |
|---|---|---|
| Default (all apps) | 35 requests/second (Team API endpoints) | 0 |
- Webhooks available: Yes
- Webhook notes: Square supports webhooks for team member events. Subscriptions are configured in the Developer Dashboard or via the Webhooks API. Payloads are delivered via HTTPS POST to a registered endpoint.
- Alternative event strategy: Poll the Search Team Members endpoint (POST /v2/team-members/search) for change detection if webhooks are not feasible.
- Webhook events: team_member.created, team_member.updated, team_member.wage_setting.updated
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Not documented
- Endpoint: Not documented
Limitations:
- Square does not offer a native SCIM 2.0 endpoint as of the current documentation.
- IdP integrations (Okta, Entra ID, OneLogin) are available but use SSO/SAML, not SCIM provisioning.
- Automated provisioning must be implemented via the Team API directly.
Common scenarios
Three integration scenarios with explicit caveats:
Onboard: POST /v2/team-members with idempotency_key, identity fields, status: ACTIVE, and assigned_locations.
Capture the returned team_member.id.
Wage settings cannot be included in the creation body - issue a separate PUT /v2/team-members/{id}/wage-setting after creation.
Use reference_id to store your internal HR system's identifier on the Square object for identity graph correlation.
Sync active members: POST /v2/team-members/search with filter.status: ACTIVE and target location_ids.
Default page size is 100, max is 200;
iterate using the cursor field until no cursor is returned.
OAuth tokens are scoped per merchant - confirm the token covers the correct location_ids before filtering.
Offboard: PUT /v2/team-members/{id} with the full team member object and status: INACTIVE.
Confirm status: INACTIVE and updated_at in the response.
Subscribe to the team_member.updated webhook for event-driven confirmation.
INACTIVE records persist in Square's system and are reactivatable - your identity graph must treat INACTIVE as the terminal offboarded state, not as deletion.
Onboard a new employee
- POST /v2/team-members with idempotency_key, given_name, family_name, email_address, status=ACTIVE, and assigned_locations.
- Capture the returned team_member.id.
- PUT /v2/team-members/{id}/wage-setting to assign job title, pay type, and overtime exemption status.
- Optionally store the Square team_member.id mapped to your internal HR system ID via reference_id.
Watch out for: Wage settings must be set in a separate API call after team member creation; they cannot be included in the initial POST body.
Sync active team members to an external system
- POST /v2/team-members/search with filter status=ACTIVE and desired location_ids.
- Iterate through returned team_members array.
- If a cursor is present in the response, repeat the POST with the cursor value to retrieve the next page.
- Continue until no cursor is returned in the response.
Watch out for: Default page size is 100, max is 200. Large teams require multiple paginated requests. There is no GET list endpoint.
Offboard (deactivate) a departing employee
- Identify the team member's Square ID (from your system's stored reference or via search by email/reference_id).
- PUT /v2/team-members/{id} with the full team_member object and status set to INACTIVE.
- Verify the response confirms status=INACTIVE and updated_at timestamp.
- Optionally subscribe to the team_member.updated webhook to confirm the status change event is received.
Watch out for: Hard deletion is not available. INACTIVE team members remain in Square's system and can be reactivated. Ensure your system treats INACTIVE as offboarded.
Why building this yourself is a trap
The most consequential API traps for integration builders:
- Full-replace PUT: Sending a partial update object will silently clear omitted fields. Always retrieve the current object first, mutate the target fields, and PUT the complete payload.
- No SCIM, no auto-provisioning: Because Square has no SCIM endpoint, any identity graph built on top of Square - including an MCP server with 60+ deep IT/identity integrations - must implement its own create/deactivate lifecycle logic against the Team API. There is no delegated provisioning path.
- API versioning is date-based: Requests without a
Square-Versionheader fall back to the application's default version set in the Developer Dashboard. Pin the version header explicitly (e.g.,Square-Version: 2024-01-17) to avoid silent behavior changes on version rollover. - Sandbox isolation: The sandbox base URL (
https://connect.squareupsandbox.com/v2) is distinct from production. Misconfigured environments will return 401s or operate against test data silently. - Rate limits: The Team API allows up to 35 requests/second per application. HTTP 429 is returned on breach;
X-RateLimit-LimitandX-RateLimit-Remainingheaders are available, butRetry-Afterheader behavior is not explicitly documented - implement exponential backoff.
Automate Square workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.