POST Revoke Member
End a member's funded seat and revoke your app's grant, member tokens and unfinished Connect flows. The account is released to the member, with its broker links and settings retained. Revocation does not flatten positions or cancel protective orders. App-owned copiers lose execution authority; protective monitors continue enforcing limits.
Endpoint
POST https://app.crosstrade.io/v1/api/partner/users/{external_id}/revoke
Headers
| Name | Required | Value |
|---|---|---|
| Authorization | Yes | Bearer <partner access token> with partner:provision |
| Content-Type | Yes | application/json (UTF-8) |
Neither Idempotency-Key nor If-Match is required. Repeated calls against a revoked member return the current state without ending another seat or incrementing the version again.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
external_id | string | Yes | Member id used at creation; 1–64 ASCII letters, digits, periods, underscores or hyphens |
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | subscription_canceled, payment_failed, member_request, partner_terminated, abuse or other |
No query parameters. Unknown body fields are rejected; the maximum body size is 64 KiB.
Code examples
Set PARTNER_TOKEN and replace th_8831 with your member id.
- Python
- JavaScript
- cURL
import json
import os
import requests
response = requests.post(
"https://app.crosstrade.io/v1/api/partner/users/th_8831/revoke",
headers={"Authorization": f"Bearer {os.environ['PARTNER_TOKEN']}"},
json={"reason": "subscription_canceled"},
timeout=30,
)
response.raise_for_status()
print("ETag:", response.headers.get("ETag"))
print(json.dumps(response.json(), indent=2))
const response = await fetch(
"https://app.crosstrade.io/v1/api/partner/users/th_8831/revoke",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PARTNER_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ reason: "subscription_canceled" }),
},
);
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log("ETag:", response.headers.get("etag"));
console.log(JSON.stringify(await response.json(), null, 2));
curl -sS -i -X POST "https://app.crosstrade.io/v1/api/partner/users/th_8831/revoke" \
-H "Authorization: Bearer $PARTNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "subscription_canceled"
}'
Response
200 OK, with ETag: "v2" in this example. already_revoked is false for the request that ends the seat, then true on repeats. An already exchanged authorization stays exchanged in the summary, while its grant becomes inactive.
{
"success": true,
"member": {
"external_id": "th_8831",
"uid": "k3Qz9pLa",
"email": "member@example.com",
"name": "Jamie Rivera",
"status": "revoked",
"ownership_verified": true,
"version": 2,
"environments": [
"demo"
],
"metadata": {},
"seat": {
"started": "2026-10-15T14:02:11Z",
"ended": "2026-11-02T09:30:00Z"
},
"created": "2026-10-15T14:02:11Z",
"authorization": {
"status": "exchanged",
"flow_id": "pcf_a1b2c3d4e5f6",
"purpose": "authorize",
"generation": 1
},
"grant": {
"version": 2,
"active": false
}
},
"already_revoked": false,
"meta": {
"requestId": "preq_6b5a4938271605f4",
"etag": "\"v2\""
}
}
The seat's final billable UTC day still counts if it had any positive billable overlap. See Billing and usage. To fund the member again, use POST Reopen Member with the current ETag and a fresh authorization request.
Errors
| Status | Error | Meaning |
|---|---|---|
| 400 | validation_failed | Missing or invalid reason, malformed path or unsupported query parameter |
| 401 | unauthorized | Invalid partner token |
| 403 | insufficient_scope, partner_not_enabled, partner_not_active | Scope, platform enablement or provisioning state blocks the request |
| 404 | member_not_found | Unknown member |
| 413 / 415 | validation_failed | Body too large or unsupported content type/encoding |
| 429 | rate_limited, too_many_concurrent_requests | Honor Retry-After |
| 503 | outcome_unknown | The commit result is uncertain; read the member state and retry revoke if needed |
The service policy permits revoke while past due, suspended or disabled, provided authentication and platform enablement still allow the request. See Partner errors for common availability errors and response shapes.