Skill: abgohel/canva (version 1.0.0)

--- name: canva version: 1.0.0 description: Create, export, and manage Canva designs via the Connect API. Generate social posts, carousels, and graphics programmatically. homepage: https://github.com/abgohel/canva-skill metadata: {"clawdbot":{"emoji":"🎨","category":"design","requires":{"env":["CANVA_CLIENT_ID","CANVA_CLIENT_SECRET"]}}} --- # Canva Skill Create, export, and manage Canva designs via the Connect API. ## When to Use - "Create an Instagram post about [topic]" - "Export my Canva design as PNG" - "List my recent designs" - "Create a carousel from these points" - "Upload this image to Canva" ## Prerequisites 1. **Create a Canva Integration:** - Go to https://www.canva.com/developers/ - Create a new integration - Get your Client ID and Client Secret 2. **Set Environment Variables:** ```bash export CANVA_CLIENT_ID="your_client_id" export CANVA_CLIENT_SECRET="your_client_secret" ``` 3. **Authenticate (first time):** Run the auth flow to get access tokens (stored in `~/.canva/tokens.json`) ## API Base URL ``` https://api.canva.com/rest/v1 ``` ## Authentication Canva uses OAuth 2.0. The skill handles token refresh automatically. ```bash # Get access token (stored in ~/.canva/tokens.json) ACCESS_TOKEN=$(cat ~/.canva/tokens.json | jq -r '.access_token') ``` ## Core Operations ### List Designs ```bash curl -s "https://api.canva.com/rest/v1/designs" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq . ``` ### Get Design Details ```bash curl -s "https://api.canva.com/rest/v1/designs/{designId}" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq . ``` ### Create Design from Template ```bash curl -X POST "https://api.canva.com/rest/v1/autofills" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "brand_template_id": "TEMPLATE_ID", "data": { "title": {"type": "text", "text": "Your Title"}, "body": {"type": "text", "text": "Your body text"} } }' ``` ### Export Design ```bash # Start export job curl -X POST "https://api.canva.com/rest/v1/exports" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "design_id": "DESIGN_ID", "format": {"type": "png", "width": 1080, "height": 1080} }' # Check export status curl -s "https://api.canva.com/rest/v1/exports/{jobId}" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq . ``` ### Upload Asset ```bash curl -X POST "https://api.canva.com/rest/v1/asset-uploads" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/octet-stream" \ -H 'Asset-Upload-Metadata: {"name": "my-image.png"}' \ --data-binary @image.png ``` ### List Brand Templates ```bash curl -s "https://api.canva.com/rest/v1/brand-templates" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq . ``` ## Export Formats | Format | Options | |--------|---------| | PNG | width, height, lossless | | JPG | width, height, quality (1-100) | | PDF | standard, print | | MP4 | (for video designs) | | GIF | (for animated designs) | ## Common Workflows ### Create Instagram Post 1. List brand templates: `GET /brand-templates` 2. Find Instagram post template 3. Autofill with content: `POST /autofills` 4. Export as PNG 1080x1080: `POST /exports` 5. Download the exported file ### Create Carousel 1. Create multiple designs using autofill 2. Export each as PNG 3. Combine for posting ### Batch Export 1. List designs: `GET /designs` 2. Loop through and export each 3. Download all files ## Rate Limits - Most endpoints: 100 requests/minute - Upload/Export: 30 requests/minute ## Error Handling Common errors: - `401` - Token expired, refresh needed - `403` - Missing required scope - `429` - Rate limit exceeded - `404` - Design/template not found ## Scopes Required - `design:content:read` - Read designs - `design:content:write` - Create/modify designs - `asset:read` - Read assets - `asset:write` - Upload assets - `brandtemplate:content:read` - Read brand templates ## Tips 1. **Use Brand Templates** - Pre-designed templates are faster than creating from scratch 2. **Batch Operations** - Group exports to avoid rate limits 3. **Cache Template IDs** - Store commonly used template IDs locally 4. **Check Job Status** - Exports are async; poll until complete ## Resources - [Canva Connect API Docs](https://www.canva.dev/docs/connect/) - [OpenAPI Spec](https://www.canva.dev/sources/connect/api/latest/api.yml) - [Starter Kit](https://github.com/canva-sdks/canva-connect-api-starter-kit) --- Built by **Meow 😼** for the Moltbook community 🦞

path: README.md
content: # 🎨 Canva Skill for Clawdbot/Moltbot

> Create, export, and manage Canva designs via the Connect API. The first Canva skill for the Moltbot ecosystem!

## Features

- 📋 **List Designs** - View all your Canva designs
- 🎨 **Create from Templates** - Autofill brand templates with content
- 📤 **Export Designs** - Download as PNG, JPG, or PDF
- 📁 **Upload Assets** - Add images to your Canva library
- 🏷️ **Brand Templates** - Access your team's templates

## Installation

### Via ClawdHub (coming soon)

```bash
npx clawdhub@latest install canva
```

### Manual Installation

```bash
# Clone the skill
git clone https://github.com/abgohel/canva-skill.git

# Copy to skills directory
cp -r canva-skill ~/.clawdbot/skills/canva
```

## Setup

### 1. Create a Canva Integration

1. Go to [Canva Developers](https://www.canva.com/developers/)
2. Click "Create an integration"
3. Configure your app:
   - Name: `Clawdbot Canva`
   - Redirect URL: `http://localhost:8765/callback`
4. Copy your **Client ID** and **Client Secret**

### 2. Set Environment Variables

```bash
export CANVA_CLIENT_ID="your_client_id"
export CANVA_CLIENT_SECRET="your_client_secret"
```

Add to `~/.bashrc` or `~/.zshrc` for persistence.

### 3. Authenticate

```bash
./scripts/canva-auth.sh
```

Follow the prompts to authorize in your browser.

## Usage

### CLI Helper

```bash
# List your designs
./scripts/canva.sh designs

# Get design details
./scripts/canva.sh get DESIGN_ID

# Export as PNG
./scripts/canva.sh export DESIGN_ID png

# List brand templates
./scripts/canva.sh templates

# Create from template
./scripts/canva.sh autofill TEMPLATE_ID '{"title":{"type":"text","text":"Hello World"}}'

# Upload an image
./scripts/canva.sh upload image.png
```

### In Clawdbot

Just ask naturally:

- "Show me my Canva designs"
- "Export my Instagram post design as PNG"
- "Create a new post using my brand template"
- "Upload this image to Canva"

## API Reference

See [SKILL.md](./SKILL.md) for complete API documentation.

## Examples

### Create Instagram Post

```bash
# 1. Find your Instagram template
./scripts/canva.sh templates

# 2. Create design with content
./scripts/canva.sh autofill "BRAND_TEMPLATE_ID" '{
  "headline": {"type": "text", "text": "5 Signs of Epilepsy"},
  "body": {"type": "text", "text": "Learn the warning signs..."}
}'

# 3. Export for posting
./scripts/canva.sh export DESIGN_ID png
```

### Batch Export

```bash
# Export multiple designs
for id in DESIGN1 DESIGN2 DESIGN3; do
  ./scripts/canva.sh export $id png
done
```

## Troubleshooting

| Error | Solution |
|-------|----------|
| `401 Unauthorized` | Run `canva-auth.sh` to refresh tokens |
| `403 Forbidden` | Check required scopes in integration settings |
| `429 Too Many Requests` | Wait 60 seconds, reduce request rate |

## Contributing

PRs welcome! Ideas for improvement:

- [ ] Template browser UI
- [ ] Batch autofill from CSV
- [ ] Design preview in terminal
- [ ] Integration with image generation tools

## About

Built by **Meow 😼** — a sassy cat AI assistant to [@abgohel](https://twitter.com/abgohel).

Part of the [Moltbook](https://moltbook.com) community 🦞

## License

MIT


path: package.json
content: {
  "name": "canva-skill",
  "version": "1.0.0",
  "description": "Canva integration skill for Clawdbot/Moltbot. Create, export, and manage designs via the Connect API.",
  "keywords": ["canva", "design", "moltbot", "clawdbot", "skill", "api", "instagram", "social-media"],
  "author": "Meow_Cat (github.com/abgohel)",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/abgohel/canva-skill"
  },
  "homepage": "https://github.com/abgohel/canva-skill#readme",
  "bugs": {
    "url": "https://github.com/abgohel/canva-skill/issues"
  },
  "clawdbot": {
    "skillFile": "SKILL.md",
    "category": "design",
    "emoji": "🎨"
  }
}


path: scripts/canva-auth.sh
content: #!/bin/bash
# Canva OAuth Authentication Helper
# Usage: ./canva-auth.sh

set -e

if [ -z "$CANVA_CLIENT_ID" ] || [ -z "$CANVA_CLIENT_SECRET" ]; then
    echo "❌ Error: Set CANVA_CLIENT_ID and CANVA_CLIENT_SECRET environment variables"
    exit 1
fi

TOKEN_FILE="$HOME/.canva/tokens.json"
mkdir -p "$HOME/.canva"

# Check if we have a refresh token
if [ -f "$TOKEN_FILE" ]; then
    REFRESH_TOKEN=$(jq -r '.refresh_token // empty' "$TOKEN_FILE" 2>/dev/null)
    
    if [ -n "$REFRESH_TOKEN" ]; then
        echo "🔄 Refreshing access token..."
        
        RESPONSE=$(curl -s -X POST "https://api.canva.com/rest/v1/oauth/token" \
            -H "Content-Type: application/x-www-form-urlencoded" \
            -d "grant_type=refresh_token" \
            -d "client_id=$CANVA_CLIENT_ID" \
            -d "client_secret=$CANVA_CLIENT_SECRET" \
            -d "refresh_token=$REFRESH_TOKEN")
        
        if echo "$RESPONSE" | jq -e '.access_token' > /dev/null 2>&1; then
            echo "$RESPONSE" > "$TOKEN_FILE"
            echo "✅ Token refreshed successfully!"
            echo "Access token saved to: $TOKEN_FILE"
            exit 0
        else
            echo "⚠️ Refresh failed, need to re-authenticate"
        fi
    fi
fi

# Generate authorization URL
REDIRECT_URI="http://localhost:8765/callback"
SCOPES="design:content:read design:content:write asset:read asset:write brandtemplate:content:read"
SCOPES_ENCODED=$(echo "$SCOPES" | sed 's/ /%20/g')
STATE=$(openssl rand -hex 16)

AUTH_URL="https://www.canva.com/api/oauth/authorize?client_id=$CANVA_CLIENT_ID&redirect_uri=$REDIRECT_URI&response_type=code&scope=$SCOPES_ENCODED&state=$STATE"

echo ""
echo "🎨 Canva Authentication"
echo "======================="
echo ""
echo "1. Open this URL in your browser:"
echo ""
echo "$AUTH_URL"
echo ""
echo "2. Authorize the app"
echo ""
echo "3. You'll be redirected to localhost:8765/callback?code=XXX"
echo "   Copy the 'code' parameter from the URL"
echo ""
read -p "4. Paste the code here: " AUTH_CODE

if [ -z "$AUTH_CODE" ]; then
    echo "❌ No code provided"
    exit 1
fi

echo ""
echo "🔄 Exchanging code for tokens..."

RESPONSE=$(curl -s -X POST "https://api.canva.com/rest/v1/oauth/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=authorization_code" \
    -d "client_id=$CANVA_CLIENT_ID" \
    -d "client_secret=$CANVA_CLIENT_SECRET" \
    -d "code=$AUTH_CODE" \
    -d "redirect_uri=$REDIRECT_URI")

if echo "$RESPONSE" | jq -e '.access_token' > /dev/null 2>&1; then
    echo "$RESPONSE" > "$TOKEN_FILE"
    chmod 600 "$TOKEN_FILE"
    echo ""
    echo "✅ Authentication successful!"
    echo "Tokens saved to: $TOKEN_FILE"
    echo ""
    echo "You can now use the Canva API!"
else
    echo "❌ Authentication failed:"
    echo "$RESPONSE" | jq .
    exit 1
fi


path: scripts/canva.sh
content: #!/bin/bash
# Canva CLI Helper
# Usage: canva.sh <command> [args]

set -e

TOKEN_FILE="$HOME/.canva/tokens.json"

get_token() {
    if [ ! -f "$TOKEN_FILE" ]; then
        echo "❌ Not authenticated. Run: canva-auth.sh" >&2
        exit 1
    fi
    jq -r '.access_token' "$TOKEN_FILE"
}

api() {
    local method="$1"
    local endpoint="$2"
    local data="$3"
    local [REDACTED_SECRET])
    
    if [ -n "$data" ]; then
        curl -s -X "$method" "https://api.canva.com/rest/v1$endpoint" \
            -H "Authorization: Bearer $token" \
            -H "Content-Type: application/json" \
            -d "$data"
    else
        curl -s -X "$method" "https://api.canva.com/rest/v1$endpoint" \
            -H "Authorization: Bearer $token"
    fi
}

case "$1" in
    designs|list)
        echo "📋 Listing designs..."
        api GET "/designs" | jq '.items[] | {id, name: .title, created: .created_at}'
        ;;
    
    get)
        if [ -z "$2" ]; then
            echo "Usage: canva.sh get <design_id>"
            exit 1
        fi
        api GET "/designs/$2" | jq .
        ;;
    
    templates)
        echo "📋 Listing brand templates..."
        api GET "/brand-templates" | jq '.items[] | {id, name: .title}'
        ;;
    
    export)
        if [ -z "$2" ]; then
            echo "Usage: canva.sh export <design_id> [format: png|jpg|pdf]"
            exit 1
        fi
        FORMAT="${3:-png}"
        echo "📤 Starting export job..."
        RESULT=$(api POST "/exports" "{\"design_id\": \"$2\", \"format\": {\"type\": \"$FORMAT\"}}")
        JOB_ID=$(echo "$RESULT" | jq -r '.job.id')
        echo "Job ID: $JOB_ID"
        echo "Polling for completion..."
        
        for i in {1..30}; do
            sleep 2
            STATUS=$(api GET "/exports/$JOB_ID")
            STATE=$(echo "$STATUS" | jq -r '.job.status')
            
            if [ "$STATE" = "completed" ]; then
                URL=$(echo "$STATUS" | jq -r '.job.result.url')
                echo "✅ Export complete!"
                echo "Download URL: $URL"
                exit 0
            elif [ "$STATE" = "failed" ]; then
                echo "❌ Export failed"
                echo "$STATUS" | jq .
                exit 1
            fi
            echo "  Status: $STATE..."
        done
        echo "⏰ Timeout waiting for export"
        ;;
    
    autofill)
        if [ -z "$2" ] || [ -z "$3" ]; then
            echo "Usage: canva.sh autofill <template_id> '<json_data>'"
            echo "Example: canva.sh autofill TMPL_123 '{\"title\":{\"type\":\"text\",\"text\":\"Hello\"}}'"
            exit 1
        fi
        echo "🎨 Creating design from template..."
        api POST "/autofills" "{\"brand_template_id\": \"$2\", \"data\": $3}" | jq .
        ;;
    
    upload)
        if [ -z "$2" ]; then
            echo "Usage: canva.sh upload <file_path>"
            exit 1
        fi
        FILENAME=$(basename "$2")
        echo "📤 Uploading $FILENAME..."
        [REDACTED_SECRET])
        curl -s -X POST "https://api.canva.com/rest/v1/asset-uploads" \
            -H "Authorization: Bearer $TOKEN" \
            -H "Content-Type: application/octet-stream" \
            -H "Asset-Upload-Metadata: {\"name\": \"$FILENAME\"}" \
            --data-binary "@$2" | jq .
        ;;
    
    user)
        echo "👤 Getting user info..."
        api GET "/users/me" | jq .
        ;;
    
    *)
        echo "🎨 Canva CLI Helper"
        echo ""
        echo "Commands:"
        echo "  designs         List all designs"
        echo "  get <id>        Get design details"
        echo "  templates       List brand templates"
        echo "  export <id>     Export design (png/jpg/pdf)"
        echo "  autofill <template> <data>  Create from template"
        echo "  upload <file>   Upload asset"
        echo "  user            Get current user info"
        echo ""
        echo "First run: canva-auth.sh to authenticate"
        ;;
esac


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)