Summary and recommendation
Airwallex exposes a REST API at https://api.airwallex.com/api/v1 for full member lifecycle management: invite (POST /account/members), update role (PATCH /account/members/{id}), disable (POST /account/members/{id}/disable), and re-enable (POST /account/members/{id}/enable).
Authentication uses a short-lived JWT obtained by exchanging a client_id and API key secret at POST /authentication/login;
tokens expire in approximately 30 minutes and there is no documented refresh token mechanism, so automation scripts must implement re-authentication logic.
There is no native SCIM 2.0 endpoint, meaning any IdP integration into an identity graph mapping Airwallex member records to canonical employee identities across Okta, Entra ID, or similar
must be built on top of these REST endpoints directly.
Required scopes are r:awx_action:account_members for reads and w:awx_action:account_members for writes;
the API key secret is displayed only once at creation time and must be stored securely immediately.
Numeric rate limits are not publicly documented;
contact Airwallex support before deploying high-frequency automation in production.
Pagination uses integer page_num (0-indexed) and page_size (max 100);
check the has_more field in list responses to detect additional pages.
API quick reference
| Has user API | Yes |
| Auth method | Bearer token via API key exchange (client_id + API key exchanged for a short-lived JWT access token at /authentication/login) |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | N/A |
Authentication
Auth method: Bearer token via API key exchange (client_id + API key exchanged for a short-lived JWT access token at /authentication/login)
Setup steps
- Log in to the Airwallex portal and navigate to Developer > API Keys.
- Create an API key and note the client_id and API key secret.
- POST to https://api.airwallex.com/api/v1/authentication/login with headers x-client-id and x-api-key.
- Extract the token field from the response; use it as 'Authorization: Bearer
' on subsequent requests. - Tokens are short-lived (typically 30 minutes); re-authenticate before expiry.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| r:awx_action:account_members | Read account member (user) records. | GET /account/members |
| w:awx_action:account_members | Create or modify account member records. | POST /account/members, PATCH /account/members/{id} |
| r:awx_action:accounts | Read account-level information. | GET /account |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique member identifier. | system-generated | immutable | UUID format. |
| string | Member's email address. | required | not updatable | Used as login identifier. | |
| first_name | string | Member's first name. | required | optional | |
| last_name | string | Member's last name. | required | optional | |
| mobile | string | Mobile phone number. | optional | optional | E.164 format recommended. |
| role_ids | array[string] | List of role IDs assigned to the member. | required | optional | Roles control permissions within the account. |
| status | string | Member status (e.g., ACTIVE, INVITED, DISABLED). | system-set | via dedicated enable/disable endpoints | |
| account_id | string | The Airwallex account this member belongs to. | system-set | immutable | |
| created_at | datetime | ISO 8601 timestamp of member creation. | system-generated | immutable | |
| updated_at | datetime | ISO 8601 timestamp of last update. | system-generated | system-updated |
Core endpoints
Authenticate / get access token
- Method: POST
- URL:
https://api.airwallex.com/api/v1/authentication/login - Watch out for: Token expires in ~30 minutes. Must re-authenticate; no refresh token mechanism documented.
Request example
POST /api/v1/authentication/login
Headers:
x-client-id: <client_id>
x-api-key: <api_key>
Response example
{
"token": "eyJhbGci...",
"expires_at": "2024-01-01T01:30:00Z"
}
List account members
- Method: GET
- URL:
https://api.airwallex.com/api/v1/account/members - Watch out for: Returns members for the authenticated account only; sub-account members require separate authentication.
Request example
GET /api/v1/account/members?page_num=0&page_size=20
Authorization: Bearer <token>
Response example
{
"items": [
{"id": "mbr_xxx", "email": "user@example.com",
"first_name": "Jane", "status": "ACTIVE"}
],
"has_more": false
}
Get account member by ID
- Method: GET
- URL:
https://api.airwallex.com/api/v1/account/members/{id} - Watch out for: Returns 404 if the member ID does not belong to the authenticated account.
Request example
GET /api/v1/account/members/mbr_xxx
Authorization: Bearer <token>
Response example
{
"id": "mbr_xxx",
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"status": "ACTIVE",
"role_ids": ["role_admin"]
}
Invite / create account member
- Method: POST
- URL:
https://api.airwallex.com/api/v1/account/members - Watch out for: Member receives an email invitation; status is INVITED until they accept. Duplicate email returns an error.
Request example
POST /api/v1/account/members
{
"email": "newuser@example.com",
"first_name": "John",
"last_name": "Smith",
"role_ids": ["role_viewer"]
}
Response example
{
"id": "mbr_yyy",
"email": "newuser@example.com",
"status": "INVITED"
}
Update account member
- Method: PATCH
- URL:
https://api.airwallex.com/api/v1/account/members/{id} - Watch out for: Email cannot be changed after creation. Only role and name fields are patchable.
Request example
PATCH /api/v1/account/members/mbr_yyy
{
"role_ids": ["role_admin"]
}
Response example
{
"id": "mbr_yyy",
"role_ids": ["role_admin"],
"updated_at": "2024-06-01T10:00:00Z"
}
Disable (deactivate) account member
- Method: POST
- URL:
https://api.airwallex.com/api/v1/account/members/{id}/disable - Watch out for: Disabling does not delete the member record. The member loses access immediately.
Request example
POST /api/v1/account/members/mbr_yyy/disable
Authorization: Bearer <token>
Response example
{
"id": "mbr_yyy",
"status": "DISABLED"
}
Enable account member
- Method: POST
- URL:
https://api.airwallex.com/api/v1/account/members/{id}/enable - Watch out for: Only previously DISABLED members can be re-enabled via this endpoint.
Request example
POST /api/v1/account/members/mbr_yyy/enable
Authorization: Bearer <token>
Response example
{
"id": "mbr_yyy",
"status": "ACTIVE"
}
List roles
- Method: GET
- URL:
https://api.airwallex.com/api/v1/account/roles - Watch out for: Role IDs are account-specific; do not assume role IDs are consistent across different Airwallex accounts.
Request example
GET /api/v1/account/roles
Authorization: Bearer <token>
Response example
{
"items": [
{"id": "role_admin", "name": "Admin"},
{"id": "role_viewer", "name": "Viewer"}
]
}
Rate limits, pagination, and events
Rate limits: Airwallex does not publicly document specific numeric rate limits in its developer docs as of the research date.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: No explicit rate-limit tiers, headers, or Retry-After behavior documented in official sources. Contact Airwallex support for production limits.
Pagination method: cursor
Default page size: 20
Max page size: 100
Pagination pointer: page_num / page_size (offset-style integers used in list endpoints)
Webhooks available: Yes
Webhook notes: Airwallex supports webhooks for payment and account events. Webhook configuration is done via the Developer portal or the /webhooks API endpoints.
Alternative event strategy: Poll GET /account/members for member state changes if webhook delivery is unreliable.
Webhook events: account.member.created, account.member.updated, account.member.disabled, payment.created, payment.updated
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: N/A
- Endpoint: Not documented
Limitations:
- Airwallex does not offer a native SCIM 2.0 endpoint as of the research date.
- No IdP-native SCIM connector (Okta, Entra ID, Google Workspace, OneLogin) is documented by Airwallex.
Common scenarios
Three core automation scenarios are well-supported by the API.
First, provisioning: POST /authentication/login → GET /account/roles to resolve role IDs → POST /account/members with email, name, and role_ids.
Note that the invited user must accept the email invitation before status transitions from INVITED to ACTIVE;
no API call can bypass this step, so downstream automation must handle the asynchronous activation window via polling GET /account/members/{id} or the account.member.created webhook.
Second, deprovisioning: authenticate → GET /account/members filtered by email to resolve the member id → POST /account/members/{id}/disable.
Disabling revokes access immediately but does not delete the record;
there is no documented hard-delete endpoint, so DISABLED records persist in the identity graph.
Third, role updates: PATCH /account/members/{id} with a full role_ids array.
The role_ids field is a replacement, not an additive patch - omitting a previously assigned role ID will silently remove it.
Always GET /account/roles first, as role IDs are account-scoped and not portable across Airwallex accounts.
Provision a new employee as an Airwallex account member
- POST /authentication/login with x-client-id and x-api-key to obtain a Bearer token.
- GET /account/roles to retrieve available role IDs and select the appropriate role.
- POST /account/members with email, first_name, last_name, and role_ids.
- Poll GET /account/members/{id} or listen for account.member.created webhook to confirm status transitions from INVITED to ACTIVE.
Watch out for: The invited user must accept the email invitation before their status becomes ACTIVE. Automated provisioning cannot bypass this step.
Deprovision a departing employee
- Authenticate to obtain a Bearer token.
- GET /account/members?page_num=0&page_size=100 and filter by email to find the member's id.
- POST /account/members/{id}/disable to immediately revoke access.
- Optionally verify status is DISABLED via GET /account/members/{id}.
Watch out for: Disabling is not deletion; the member record persists. There is no documented hard-delete endpoint for members.
Update a member's role (e.g., promotion to Admin)
- Authenticate to obtain a Bearer token.
- GET /account/roles to confirm the target role ID (e.g., role_admin).
- PATCH /account/members/{id} with body {"role_ids": ["role_admin"]}.
- Confirm the updated role_ids in the response body.
Watch out for: role_ids is a full replacement array, not an additive patch; include all desired roles in the array or previously assigned roles will be removed.
Why building this yourself is a trap
The primary integration trap is the short-lived token with no refresh mechanism: scripts that do not re-authenticate proactively will begin returning 401 errors mid-run, leaving provisioning or deprovisioning jobs in a partially completed state. A second trap is email immutability - member email cannot be changed after creation via PATCH;
correcting an email requires disabling the existing member and issuing a new invitation, which resets the INVITED → ACTIVE flow and may disrupt access during the transition window.
Sub-account isolation is a less obvious hazard: the parent account Bearer token does not grant access to sub-account members, and each sub-account requires its own API credentials. Any identity graph that aggregates members across a multi-account Airwallex structure must manage credential sets per account independently.
Finally, webhook event names for member lifecycle events (e.g., account.member.created, account.member.disabled) should be verified against the live API reference before production use, as the documentation notes they may change.
Automate Airwallex 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.