OneDrive

SkillFiles & storage

OneDrive API integration with managed OAuth via Microsoft Graph. Manage files, folders, and sharing. Use this skill when users want to upload, download, organize, or share files in OneDrive. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the OneDrive skill

What this skill tells your AI

The instructions your AI receives, as published by craftos-dev/craftbot in skills/one-drive/SKILL.md and read by ahel’s review.

Access the OneDrive API with managed OAuth authentication via Microsoft Graph. Manage files, folders, drives, and sharing with full CRUD operations.

Quick Start

# List files in OneDrive root
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/one-drive/v1.0/me/drive/root/children')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://gateway.maton.ai/one-drive/v1.0/{resource}

The gateway proxies requests to graph.microsoft.com and automatically injects your OAuth token.

Authentication

All requests require the Maton API key in the Authorization header:

Authorization: Bearer $MATON_API_KEY

Environment Variable: Set your API key as MATON_API_KEY:

export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key

Connection Management

Manage your OneDrive OAuth connections at https://ctrl.maton.ai.

List Connections

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=one-drive&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'one-drive'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "3f17fb58-4515-4840-8ef6-2bbf0fa67e2c",
    "status": "ACTIVE",
    "creation_time": "2026-02-07T08:23:30.317909Z",
    "last_updated_time": "2026-02-07T08:24:04.925298Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "one-drive",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple OneDrive connections, specify which one to use with the Maton-Connection header:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/one-drive/v1.0/me/drive')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '3f17fb58-4515-4840-8ef6-2bbf0fa67e2c')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If omitted, the gateway uses the default (oldest) active connection.

API Reference

Drives

Get Current User's Drive
GET /one-drive/v1.0/me/drive

Response:

{
  "id": "b!F3Y7M0VT80OO9iu_D6Z-LA...",
  "driveType": "personal",
  "name": "OneDrive",
  "owner": {
    "user": {
      "displayName": "John Doe",
      "id": "d4648f06c91d9d3d"
    }
  },
  "quota": {
    "total": 5368709120,
    "used": 1234567,
    "remaining": 5367474553
  }
}
List User's Drives
GET /one-drive/v1.0/me/drives
Get Drive by ID
GET /one-drive/v1.0/drives/{drive-id}

Files and Folders

Get Drive Root
GET /one-drive/v1.0/me/drive/root
List Root Children
GET /one-drive/v1.0/me/drive/root/children

Response:

{
  "value": [
    {
      "id": "F33B7653325337C3!s88...",
      "name": "Documents",
      "folder": {
        "childCount": 5
      },
      "createdDateTime": "2024-01-15T10:30:00Z",
      "lastModifiedDateTime": "2024-02-01T14:20:00Z"
    },
    {
      "id": "F33B7653325337C3!s3f...",
      "name": "report.pdf",
      "file": {
        "mimeType": "application/pdf",
        "hashes": {
          "sha1Hash": "cf23df2207d99a74fbe169e3eba035e633b65d94"
        }
      },
      "size": 35212
    }
  ]
}
Get Item by ID
GET /one-drive/v1.0/me/drive/items/{item-id}
Get Item by Path

Use colon (:) syntax to access items by path:

GET /one-drive/v1.0/me/drive/root:/Documents/report.pdf
List Folder Children by Path
GET /one-drive/v1.0/me/drive/root:/Documents:/children
Get Item Children
GET /one-drive/v1.0/me/drive/items/{item-id}/children

Special Folders

Access known folders by name:

GET /one-drive/v1.0/me/drive/special/documents
GET /one-drive/v1.0/me/drive/special/photos
GET /one-drive/v1.0/me/drive/special/music
GET /one-drive/v1.0/me/drive/special/approot

Recent and Shared

Get Recent Files
GET /one-drive/v1.0/me/drive/recent
Get Files Shared With Me
GET /one-drive/v1.0/me/drive/sharedWithMe

Search

GET /one-drive/v1.0/me/drive/root/search(q='{query}')

Example:

GET /one-drive/v1.0/me/drive/root/search(q='budget')

Create Folder

POST /one-drive/v1.0/me/drive/root/children
Content-Type: application/json

{
  "name": "New Folder",
  "folder": {},
  "@microsoft.graph.conflictBehavior": "rename"
}

Create folder inside another folder:

POST /one-drive/v1.0/me/drive/items/{parent-id}/children
Content-Type: application/json

{
  "name": "Subfolder",
  "folder": {}
}

Upload File (Simple - up to 4MB)

PUT /one-drive/v1.0/me/drive/items/{parent-id}:/{filename}:/content
Content-Type: application/octet-stream

{file binary content}

Example - upload to root:

PUT /one-drive/v1.0/me/drive/root:/document.txt:/content
Content-Type: text/plain

Hello, OneDrive!

Upload File (Large - resumable)

For files over 4MB, use resumable upload:

Step 1: Create upload session

POST /one-drive/v1.0/me/drive/root:/{filename}:/createUploadSession
Content-Type: application/json

{
  "item": {
    "@microsoft.graph.conflictBehavior": "rename"
  }
}

Response:

{
  "uploadUrl": "https://sn3302.up.1drv.com/up/...",
  "expirationDateTime": "2024-02-08T10:00:00Z"
}

Step 2: Upload bytes to the uploadUrl

Download File

Get the file metadata to retrieve the download URL:

GET /one-drive/v1.0/me/drive/items/{item-id}

The response includes @microsoft.graph.downloadUrl - a pre-authenticated URL valid for a short time:

{
  "id": "...",
  "name": "document.pdf",
  "@microsoft.graph.downloadUrl": "https://public-sn3302.files.1drv.com/..."
}

Use this URL directly to download the file content (no auth header needed).

Update Item (Rename/Move)

PATCH /one-drive/v1.0/me/drive/items/{item-id}
Content-Type: application/json

{
  "name": "new-name.txt"
}

Move to different folder:

PATCH /one-drive/v1.0/me/drive/items/{item-id}
Content-Type: application/json

{
  "parentReference": {
    "id": "{new-parent-id}"
  }
}

Copy Item

POST /one-drive/v1.0/me/drive/items/{item-id}/copy
Content-Type: application/json

{
  "parentReference": {
    "id": "{destination-folder-id}"
  },
  "name": "copied-file.txt"
}

Returns 202 Accepted with a Location header to monitor the copy operation.

Delete Item

DELETE /one-drive/v1.0/me/drive/items/{item-id}

Returns 204 No Content on success.

Sharing

Create Sharing Link
POST /one-drive/v1.0/me/drive/items/{item-id}/createLink
Content-Type: application/json

{
  "type": "view",
  "scope": "anonymous"
}

Link types:

  • view - Read-only access
  • edit - Read-write access
  • embed - Embeddable link

Scopes:

  • anonymous - Anyone with the link
  • organization - Anyone in your organization

Response:

{
  "id": "...",
  "link": {
    "type": "view",
    "scope": "anonymous",
    "webUrl": "https://1drv.ms/b/..."
  }
}
Invite Users (Share with specific people)
POST /one-drive/v1.0/me/drive/items/{item-id}/invite
Content-Type: application/json

{
  "recipients": [
    {"email": "user@example.com"}
  ],
  "roles": ["read"],
  "sendInvitation": true,
  "message": "Check out this file!"
}

Query Parameters

Customize responses with OData query parameters:

  • $select - Choose specific properties: ?$select=id,name,size
  • $expand - Include related resources: ?$expand=children
  • $filter - Filter results: ?$filter=file ne null (files only)
  • $orderby - Sort results: ?$orderby=name
  • $top - Limit results: ?$top=10

Example:

GET /one-drive/v1.0/me/drive/root/children?$select=id,name,size&$top=20&$orderby=name

Pagination

Results are paginated. The response includes @odata.nextLink for additional pages:

{
  "value": [...],
  "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/drive/root/children?$skiptoken=..."
}

Use the full URL from @odata.nextLink (without the gateway prefix) to fetch the next page.

Code Examples

JavaScript

// List files in root
const response = await fetch(
  'https://gateway.maton.ai/one-drive/v1.0/me/drive/root/children',
  {
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`
    }
  }
);
const data = await response.json();

// Upload a file
const uploadResponse = await fetch(
  'https://gateway.maton.ai/one-drive/v1.0/me/drive/root:/myfile.txt:/content',
  {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
      'Content-Type': 'text/plain'
    },
    body: 'Hello, OneDrive!'
  }
);

Python

import os
import requests

# List files in root
response = requests.get(
    "https://gateway.maton.ai/one-drive/v1.0/me/drive/root/children",
    headers={"Authorization": f"Bearer {os.environ['MATON_API_KEY']}"},
)
files = response.json()

# Upload a file
upload_response = requests.put(
    "https://gateway.maton.ai/one-drive/v1.0/me/drive/root:/myfile.txt:/content",
    headers={
        "Authorization": f"Bearer {os.environ['MATON_API_KEY']}",
        "Content-Type": "text/plain",
    },
    data="Hello, OneDrive!",
)

Notes

  • OneDrive uses Microsoft Graph API (graph.microsoft.com)
  • Item IDs are unique within a drive
  • Use colon (:) syntax for path-based addressing: /root:/path/to/file
  • Simple uploads are limited to 4MB; use resumable upload for larger files
  • Download URLs from @microsoft.graph.downloadUrl are pre-authenticated and temporary
  • Conflict behavior options: fail, replace, rename
  • IMPORTANT: When using curl commands, use curl -g when URLs contain brackets to disable glob parsing
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

StatusMeaning
400Missing OneDrive connection or invalid request
401Invalid or missing Maton API key
403Insufficient permissions
404Item not found
409Conflict (e.g., item already exists)
429Rate limited (check Retry-After header)
4xx/5xxPassthrough error from Microsoft Graph API

Error Response Format

{
  "error": {
    "code": "itemNotFound",
    "message": "The resource could not be found."
  }
}

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with one-drive. For example:
  • Correct: https://gateway.maton.ai/one-drive/v1.0/me/drive/root/children
  • Incorrect: https://gateway.maton.ai/v1.0/me/drive/root/children

Resources

Signals

GitHub stars
382
Forks
45
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
one-drive
Source
github.com/craftos-dev/craftbot