# WeChat Work API — Raw Endpoint Reference

Consolidated from `wecom-api` skill. All endpoints use `POST https://qyapi.weixin.qq.com/cgi-bin/{endpoint}?access_token=TOKEN` unless noted.

## Architectural Constraint

**WeChat Work has two completely isolated data spaces:**

| | User space | App space |
|---|---|---|
| Created by | User in UI | API call |
| Doc ID format | `w3_XXX`, `d3_XXX` (URL) | Long base64 string (API) |
| Space ID prefix | `s.1970326072993951.XXX` | `s.{corpid}.XXX` |
| API access | ❌ 640008 perm deny / 301085 invalid docid | ✅ full CRUD |

**Applications CANNOT access user-created documents or spaces.** This is architectural, not permission-based.

## Auth

- `GET /cgi-bin/gettoken?corpid=...&corpsecret=...` → `{access_token, expires_in: 7200}`

## WeDoc Endpoints

- `wedoc/create_doc` `{doc_type: 3, doc_name: "..."}` → `{docid, url}`
- `wedoc/document/get` `{docid}` → `{version, document: {Node tree}}`
- `wedoc/document/batch_update` `{docid, version, requests: [{insert_text: {text, location: {index}}}]}`
- `wedoc/get_doc_base_info` `{docid}` → `{doc_base_info: {doc_name, create_time, doc_type}}`
- `wedoc/doc_share` `{docid}` → `{share_url}`
- `wedoc/mod_doc_member` `{docid, update_file_member_list: [{type: 1, userid, auth: 2}]}`
- `wedoc/del_doc` `{docid}`

## WeDrive Endpoints

- `wedrive/space_create` `{space_name, auth_info: [{type:1, userid, auth:7}]}` → `{spaceid}`
- `wedrive/space_info` `{spaceid}` → `{space_info: {space_name, auth_list}}`
- `wedrive/space_dismiss` `{spaceid}`
- `wedrive/space_acl_add` `{spaceid, auth_info: [{type:1, userid, auth}]}` — auth: 1=download only, 7=app space admin
- `wedrive/file_list` `{spaceid, fatherid, sort_type:1, start:0, limit:1000}`
- `wedrive/file_upload` `{spaceid, fatherid, file_name, file_base64_content}`
- `wedrive/file_download` `{fileid}`

## Non-Existing Endpoints

- No "list all spaces" API
- No "list/search all documents" API
- No URL-docid-to-API-docid conversion
- No user-level access token (OAuth only gives identity, not API delegation)

## Error Codes

| errcode | Meaning | Action |
|---------|---------|--------|
| 48002 | API forbidden | App not in allowlist |
| 301085 | Invalid docid | URL docid not supported; need API-format docid |
| 640008 | Permission deny | App can't access user-created space |
| 640001 | Space not exist | Wrong spaceid |
| 640020 | Invalid auth type | Only auth=1 and auth=7 valid |
| 60011 | No privilege | App lacks contact/department access |
| 60111 | Userid not found | Wrong userid format |
| 2050099 | Doc version invalid | batch_update needs correct version |

## Full Python Helper

```python
import json, urllib.request, urllib.error

def get_token(corpid, corpsecret):
    url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}"
    return json.loads(urllib.request.urlopen(url))["access_token"]

def api_post(token, endpoint, body):
    url = f"https://qyapi.weixin.qq.com/cgi-bin/{endpoint}?access_token={token}"
    req = urllib.request.Request(url, method='POST',
        data=json.dumps(body).encode(),
        headers={"Content-Type": "application/json"})
    try:
        return json.loads(urllib.request.urlopen(req))
    except urllib.error.HTTPError as e:
        return json.loads(e.read().decode())
```
