Integration Guides

Step-by-step guides for integrating GreenMonkey into your applications and workflows.

Quick Start Integration

1. Basic Product Listing

Create a simple product listing in your app:

// pages/marketplace.js
import { GreenMonkey } from '@greenmonkey/sdk';
import { useEffect, useState } from 'react';

export default function Marketplace() {
  const [products, setProducts] = useState([]);
  const gm = new GreenMonkey({ apiKey: process.env.NEXT_PUBLIC_GM_API_KEY });

  useEffect(() => {
    async function loadProducts() {
      const data = await gm.products.list({
        type: 'prompt',
        limit: 12,
      });
      setProducts(data.items);
    }
    loadProducts();
  }, []);

  return (
    <div className="grid grid-cols-3 gap-4">
      {products.map((product) => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

2. Purchase Flow

Implement a complete purchase flow:

// components/PurchaseButton.js
async function handlePurchase(productId) {
  try {
    // Create purchase
    const order = await gm.purchases.create({
      productId,
      referralCode: getReferralCode(), // Optional
    });

    // Redirect to download
    if (order.downloadUrl) {
      window.location.href = order.downloadUrl;
    }

    // Show success message
    toast.success('Purchase completed! Check your email for details.');
  } catch (error) {
    if (error.code === 'PAYMENT_REQUIRED') {
      // Redirect to payment method setup
      window.location.href = '/settings/payment';
    } else {
      toast.error('Purchase failed: ' + error.message);
    }
  }
}

Platform-Specific Integrations

Next.js App Router Integration

Complete integration for Next.js 13+ with App Router:

// app/api/greenmonkey/route.ts
import { GreenMonkey } from '@greenmonkey/sdk';
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';

const gm = new GreenMonkey({
  apiKey: process.env.GREENMONKEY_API_KEY,
});

export async function POST(request: NextRequest) {
  // Verify user session
  const session = await getServerSession();
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const { action, ...params } = await request.json();

  try {
    let result;

    switch (action) {
      case 'listProducts':
        result = await gm.products.list(params);
        break;

      case 'purchase':
        result = await gm.purchases.create({
          ...params,
          metadata: { userId: session.user.id },
        });
        break;

      case 'executePrompt':
        result = await gm.ai.executePrompt({
          ...params,
          apiKeyId: session.user.gmApiKeyId,
        });
        break;

      default:
        return NextResponse.json({ error: 'Invalid action' }, { status: 400 });
    }

    return NextResponse.json(result);
  } catch (error) {
    console.error('GreenMonkey API error:', error);
    return NextResponse.json({ error: error.message }, { status: error.status || 500 });
  }
}

Express.js Integration

// server.js
const express = require('express');
const { GreenMonkey } = require('@greenmonkey/sdk');
const session = require('express-session');

const app = express();
const gm = new GreenMonkey({
  apiKey: process.env.GREENMONKEY_API_KEY,
});

// Middleware
app.use(express.json());
app.use(
  session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
  })
);

// List products endpoint
app.get('/api/products', async (req, res) => {
  try {
    const products = await gm.products.list({
      type: req.query.type,
      category: req.query.category,
      page: parseInt(req.query.page) || 1,
      limit: parseInt(req.query.limit) || 20,
    });

    res.json(products);
  } catch (error) {
    res.status(error.status || 500).json({
      error: error.message,
    });
  }
});

// Purchase endpoint
app.post('/api/purchase', requireAuth, async (req, res) => {
  try {
    const order = await gm.purchases.create({
      productId: req.body.productId,
      metadata: {
        userId: req.user.id,
        source: 'express-app',
      },
    });

    // Store purchase in local database
    await db.purchases.create({
      userId: req.user.id,
      orderId: order.id,
      productId: req.body.productId,
    });

    res.json(order);
  } catch (error) {
    res.status(error.status || 500).json({
      error: error.message,
    });
  }
});

// Webhook handler
app.post('/webhooks/greenmonkey', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-greenmonkey-signature'];

  if (!gm.webhooks.verify(req.body, signature)) {
    return res.status(400).send('Invalid signature');
  }

  const event = JSON.parse(req.body);

  // Process webhook asynchronously
  processWebhook(event).catch(console.error);

  res.status(200).send('OK');
});

app.listen(3000);

Django Integration

# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from greenmonkey import GreenMonkey
import json

gm = GreenMonkey(api_key=settings.GREENMONKEY_API_KEY)

@login_required
def list_products(request):
    """List products from GreenMonkey"""
    try:
        products = gm.products.list(
            type=request.GET.get('type'),
            category=request.GET.get('category'),
            page=int(request.GET.get('page', 1)),
            limit=int(request.GET.get('limit', 20))
        )

        return JsonResponse({
            'success': True,
            'data': products.dict()
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)

@login_required
def purchase_product(request):
    """Purchase a product"""
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)

    data = json.loads(request.body)

    try:
        order = gm.purchases.create(
            product_id=data['product_id'],
            metadata={
                'user_id': request.user.id,
                'source': 'django-app'
            }
        )

        # Store in local database
        Purchase.objects.create(
            user=request.user,
            order_id=order.id,
            product_id=data['product_id'],
            amount=order.amount
        )

        return JsonResponse({
            'success': True,
            'data': order.dict()
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)

@csrf_exempt
def webhook_handler(request):
    """Handle GreenMonkey webhooks"""
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)

    signature = request.headers.get('X-GreenMonkey-Signature')

    if not gm.webhooks.verify(request.body, signature):
        return JsonResponse({'error': 'Invalid signature'}, status=400)

    event = json.loads(request.body)

    # Process webhook asynchronously
    process_webhook.delay(event)

    return JsonResponse({'status': 'ok'})

Workflow Integrations

Zapier Integration

Connect GreenMonkey to 5000+ apps via Zapier:

// Zapier CLI App - index.js
const { GreenMonkey } = require('@greenmonkey/sdk');

const App = {
  version: require('./package.json').version,
  platformVersion: require('zapier-platform-core').version,

  authentication: {
    type: 'custom',
    fields: [
      {
        key: 'apiKey',
        label: 'API Key',
        required: true,
        type: 'string',
        helpText: 'Found in GreenMonkey Dashboard → Settings → API',
      },
    ],
    test: async (z, bundle) => {
      const gm = new GreenMonkey({ apiKey: bundle.authData.apiKey });
      await gm.products.list({ limit: 1 });
      return true;
    },
  },

  triggers: {
    new_purchase: {
      key: 'new_purchase',
      noun: 'Purchase',
      display: {
        label: 'New Purchase',
        description: 'Triggers when someone purchases your product',
      },
      operation: {
        perform: async (z, bundle) => {
          const gm = new GreenMonkey({ apiKey: bundle.authData.apiKey });
          const purchases = await gm.purchases.list({
            limit: 10,
            sort: 'created',
            order: 'desc',
          });
          return purchases.items;
        },
      },
    },
  },

  searches: {
    find_product: {
      key: 'find_product',
      noun: 'Product',
      display: {
        label: 'Find Product',
        description: 'Search for a product by name or ID',
      },
      operation: {
        inputFields: [
          {
            key: 'query',
            label: 'Search Query',
            type: 'string',
            required: true,
          },
        ],
        perform: async (z, bundle) => {
          const gm = new GreenMonkey({ apiKey: bundle.authData.apiKey });
          const products = await gm.products.list({
            search: bundle.inputData.query,
            limit: 5,
          });
          return products.items;
        },
      },
    },
  },

  creates: {
    execute_prompt: {
      key: 'execute_prompt',
      noun: 'Prompt Execution',
      display: {
        label: 'Execute Prompt',
        description: 'Execute a purchased prompt',
      },
      operation: {
        inputFields: [
          {
            key: 'productId',
            label: 'Product ID',
            type: 'string',
            required: true,
          },
          {
            key: 'variables',
            label: 'Variables',
            type: 'text',
            helpText: 'JSON object of variables',
          },
        ],
        perform: async (z, bundle) => {
          const gm = new GreenMonkey({ apiKey: bundle.authData.apiKey });
          const result = await gm.ai.executePrompt({
            productId: bundle.inputData.productId,
            variables: JSON.parse(bundle.inputData.variables || '{}'),
          });
          return result;
        },
      },
    },
  },
};

module.exports = App;

n8n Workflow Integration

Create custom n8n nodes for GreenMonkey:

// GreenMonkeyNode.node.ts
import {
  IExecuteFunctions,
  INodeExecutionData,
  INodeType,
  INodeTypeDescription,
} from 'n8n-workflow';
import { GreenMonkey } from '@greenmonkey/sdk';

export class GreenMonkeyNode implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'GreenMonkey',
    name: 'greenMonkey',
    icon: 'file:greenmonkey.svg',
    group: ['transform'],
    version: 1,
    description: 'Interact with GreenMonkey marketplace',
    defaults: {
      name: 'GreenMonkey',
    },
    inputs: ['main'],
    outputs: ['main'],
    credentials: [
      {
        name: 'greenMonkeyApi',
        required: true,
      },
    ],
    properties: [
      {
        displayName: 'Operation',
        name: 'operation',
        type: 'options',
        options: [
          {
            name: 'List Products',
            value: 'listProducts',
          },
          {
            name: 'Execute Prompt',
            value: 'executePrompt',
          },
          {
            name: 'Get Analytics',
            value: 'getAnalytics',
          },
        ],
        default: 'listProducts',
      },
      // Additional fields based on operation
    ],
  };

  async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
    const items = this.getInputData();
    const operation = this.getNodeParameter('operation', 0) as string;
    const credentials = await this.getCredentials('greenMonkeyApi');

    const gm = new GreenMonkey({
      apiKey: credentials.apiKey as string,
    });

    const results: INodeExecutionData[] = [];

    for (let i = 0; i < items.length; i++) {
      try {
        let response;

        switch (operation) {
          case 'listProducts':
            response = await gm.products.list({
              type: this.getNodeParameter('productType', i) as string,
              limit: this.getNodeParameter('limit', i) as number,
            });
            break;

          case 'executePrompt':
            response = await gm.ai.executePrompt({
              productId: this.getNodeParameter('productId', i) as string,
              variables: this.getNodeParameter('variables', i) as object,
            });
            break;

          case 'getAnalytics':
            response = await gm.analytics.products({
              period: this.getNodeParameter('period', i) as string,
            });
            break;
        }

        results.push({
          json: response,
          pairedItem: { item: i },
        });
      } catch (error) {
        if (this.continueOnFail()) {
          results.push({
            json: { error: error.message },
            pairedItem: { item: i },
          });
        } else {
          throw error;
        }
      }
    }

    return [results];
  }
}

AI Framework Integrations

LangChain Integration

Use GreenMonkey products with LangChain:

# greenmonkey_langchain.py
from langchain.llms.base import LLM
from typing import Optional, List, Mapping, Any
from greenmonkey import GreenMonkey

class GreenMonkeyLLM(LLM):
    """Custom LangChain LLM that uses GreenMonkey prompts"""

    product_id: str
    api_key_id: str
    gm_client: GreenMonkey

    def __init__(self, product_id: str, api_key_id: str, gm_api_key: str):
        super().__init__()
        self.product_id = product_id
        self.api_key_id = api_key_id
        self.gm_client = GreenMonkey(api_key=gm_api_key)

    @property
    def _llm_type(self) -> str:
        return "greenmonkey"

    def _call(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[Any] = None,
    ) -> str:
        """Execute the GreenMonkey prompt"""
        result = self.gm_client.ai.execute_prompt(
            product_id=self.product_id,
            api_key_id=self.api_key_id,
            variables={"input": prompt},
            options={"stop": stop} if stop else {}
        )

        return result.output

    @property
    def _identifying_params(self) -> Mapping[str, Any]:
        return {
            "product_id": self.product_id,
            "api_key_id": self.api_key_id
        }

# Usage with LangChain
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

# Create custom LLM
llm = GreenMonkeyLLM(
    product_id="prod_seo_writer",
    api_key_id="key_abc123",
    gm_api_key="gm_live_..."
)

# Use in a chain
template = "{input}"
prompt = PromptTemplate(template=template, input_variables=["input"])
chain = LLMChain(llm=llm, prompt=prompt)

result = chain.run(input="Write an SEO-optimized blog post about AI trends")

AutoGPT Integration

Add GreenMonkey as an AutoGPT command:

# greenmonkey_command.py
from autogpt.commands.base import Command
from greenmonkey import GreenMonkey

class GreenMonkeyCommand(Command):
    """Execute GreenMonkey products from AutoGPT"""

    def __init__(self):
        self.gm = GreenMonkey(api_key=os.environ['GREENMONKEY_API_KEY'])

    def execute_prompt(self, product_id: str, variables: dict) -> str:
        """
        Execute a GreenMonkey prompt product

        Args:
            product_id: The ID of the prompt product
            variables: Variables to pass to the prompt

        Returns:
            The generated output
        """
        result = self.gm.ai.execute_prompt(
            product_id=product_id,
            api_key_id=os.environ['GM_API_KEY_ID'],
            variables=variables
        )

        return result.output

    def search_products(self, query: str, type: str = "prompt") -> list:
        """
        Search for GreenMonkey products

        Args:
            query: Search query
            type: Product type filter

        Returns:
            List of matching products
        """
        products = self.gm.products.list(
            search=query,
            type=type,
            limit=5
        )

        return [
            {
                "id": p.id,
                "title": p.title,
                "price": p.price,
                "rating": p.rating
            }
            for p in products.items
        ]

Browser Extension Integration

Chrome Extension

Integrate GreenMonkey into a Chrome extension:

// background.js
chrome.runtime.onInstalled.addListener(() => {
  chrome.storage.sync.get(['gmApiKey'], (result) => {
    if (!result.gmApiKey) {
      chrome.tabs.create({ url: 'options.html' });
    }
  });
});

// Listen for messages from content scripts
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'executePrompt') {
    executeGreenMonkeyPrompt(request.data)
      .then(sendResponse)
      .catch((error) => sendResponse({ error: error.message }));
    return true; // Will respond asynchronously
  }
});

async function executeGreenMonkeyPrompt(data) {
  const { gmApiKey } = await chrome.storage.sync.get(['gmApiKey']);

  const response = await fetch('https://api.greenmonkey.dev/v1/ai/execute', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${gmApiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      productId: data.productId,
      variables: data.variables,
    }),
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.statusText}`);
  }

  return response.json();
}

// content.js
// Inject GreenMonkey functionality into web pages
(function () {
  // Create floating action button
  const button = document.createElement('div');
  button.id = 'gm-float-button';
  button.innerHTML = '🐵';
  button.style.cssText = `
    position: fixed;
    bottom: 20px;
    right: 20px;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: #10b981;
    color: white;
    font-size: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    z-index: 9999;
  `;

  button.addEventListener('click', () => {
    const selectedText = window.getSelection().toString();

    if (selectedText) {
      chrome.runtime.sendMessage(
        {
          action: 'executePrompt',
          data: {
            productId: 'prod_summarizer',
            variables: {
              text: selectedText,
            },
          },
        },
        (response) => {
          if (response.error) {
            alert('Error: ' + response.error);
          } else {
            showResult(response.output);
          }
        }
      );
    }
  });

  document.body.appendChild(button);
})();

Mobile App Integration

React Native

// GreenMonkeyService.js
import AsyncStorage from '@react-native-async-storage/async-storage';

class GreenMonkeyService {
  constructor() {
    this.baseURL = 'https://api.greenmonkey.dev/v1';
  }

  async getApiKey() {
    return await AsyncStorage.getItem('gmApiKey');
  }

  async setApiKey(apiKey) {
    await AsyncStorage.setItem('gmApiKey', apiKey);
  }

  async request(endpoint, options = {}) {
    const apiKey = await this.getApiKey();

    if (!apiKey) {
      throw new Error('API key not set');
    }

    const response = await fetch(`${this.baseURL}${endpoint}`, {
      ...options,
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
        ...options.headers,
      },
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.statusText}`);
    }

    return response.json();
  }

  async listProducts(filters = {}) {
    const params = new URLSearchParams(filters);
    return this.request(`/products?${params}`);
  }

  async purchaseProduct(productId) {
    return this.request('/purchases', {
      method: 'POST',
      body: JSON.stringify({ productId }),
    });
  }

  async executePrompt(productId, variables) {
    return this.request('/ai/execute', {
      method: 'POST',
      body: JSON.stringify({
        productId,
        variables,
        apiKeyId: await AsyncStorage.getItem('gmApiKeyId'),
      }),
    });
  }
}

export default new GreenMonkeyService();

// Usage in component
import React, { useState, useEffect } from 'react';
import { View, FlatList, TouchableOpacity, Text } from 'react-native';
import GreenMonkeyService from './GreenMonkeyService';

export function ProductList() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    loadProducts();
  }, []);

  async function loadProducts() {
    try {
      const data = await GreenMonkeyService.listProducts({
        type: 'prompt',
        limit: 20,
      });
      setProducts(data.items);
    } catch (error) {
      console.error('Failed to load products:', error);
    } finally {
      setLoading(false);
    }
  }

  async function handlePurchase(productId) {
    try {
      const order = await GreenMonkeyService.purchaseProduct(productId);
      alert('Purchase successful!');
    } catch (error) {
      alert('Purchase failed: ' + error.message);
    }
  }

  return (
    <FlatList
      data={products}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <TouchableOpacity onPress={() => handlePurchase(item.id)}>
          <View style={styles.productCard}>
            <Text style={styles.title}>{item.title}</Text>
            <Text style={styles.price}>${item.price}</Text>
          </View>
        </TouchableOpacity>
      )}
    />
  );
}

Best Practices

API Key Security

// Never expose API keys in client-side code
// Bad ❌
const gm = new GreenMonkey({
  apiKey: 'gm_live_abc123...', // Exposed!
});

// Good ✅ - Use environment variables
const gm = new GreenMonkey({
  apiKey: process.env.GREENMONKEY_API_KEY,
});

// Better ✅✅ - Use server-side proxy
async function callGreenMonkeyAPI(endpoint, data) {
  const response = await fetch('/api/greenmonkey', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ endpoint, data }),
  });
  return response.json();
}

Error Handling

// Comprehensive error handling
async function safeAPICall(fn) {
  try {
    return await fn();
  } catch (error) {
    if (error.code === 'RATE_LIMIT_EXCEEDED') {
      // Implement exponential backoff
      await sleep(error.retryAfter * 1000);
      return safeAPICall(fn);
    }

    if (error.code === 'INVALID_API_KEY') {
      // Prompt user to update API key
      showApiKeyDialog();
      return null;
    }

    // Log to monitoring service
    logError(error);

    // Show user-friendly message
    showErrorMessage(getErrorMessage(error));

    throw error;
  }
}

Caching Strategy

// Implement intelligent caching
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedProducts(filters) {
  const cacheKey = JSON.stringify(filters);
  const cached = cache.get(cacheKey);

  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const data = await gm.products.list(filters);

  cache.set(cacheKey, {
    data,
    timestamp: Date.now(),
  });

  return data;
}

Next Steps