Skip to content

Python API Client for Mythradon

This guide walks you through using a lightweight Python module to interact with the Mythradon REST API. It provides convenient wrappers around HTTP methods and supports optional HMAC-based authentication.

Getting Started

To use the API client, you'll need the following:

  • Your API_KEY (required)

  • Your SECRET_KEY (optional, for HMAC authentication)

  • Your Mythradon instance URL

Note

Ensure the requests package is installed:

pip install requests


API Client Module

File: crm_api_client.py

import requests
import urllib

class CrmAPIError(Exception):
    """An exception class for API errors"""
    pass

def http_build_query(data):
    parents = []
    pairs = {}

    def render_key(parents):
        depth = 0
        result = ''
        for x in parents:
            fmt = "[%s]" if depth > 0 or isinstance(x, int) else "%s"
            result += fmt % str(x)
            depth += 1
        return result

    def r_urlencode(data):
        if isinstance(data, (list, tuple)):
            for i, item in enumerate(data):
                parents.append(i)
                r_urlencode(item)
                parents.pop()
        elif isinstance(data, dict):
            for key, value in data.items():
                parents.append(key)
                r_urlencode(value)
                parents.pop()
        else:
            pairs[render_key(parents)] = str(data)
        return pairs

    return urllib.parse.urlencode(r_urlencode(data))

class CrmAPI:

    url_path = '/api/v1/'

    def __init__(self, url, api_key):
        self.url = url.rstrip('/')
        self.api_key = api_key
        self.status_code = None

    def request(self, method, action, params=None):
        if params is None:
            params = {}

        headers = {
            'X-Api-Key': self.api_key
        }

        request_url = self.normalize_url(action)

        if method in ['POST', 'PATCH', 'PUT']:
            response = requests.request(method, url=request_url, headers=headers, json=params)
        else:
            query_string = http_build_query(params)
            full_url = f"{request_url}?{query_string}" if query_string else request_url
            response = requests.request(method, url=full_url, headers=headers)

        self.status_code = response.status_code

        if self.status_code != 200:
            reason = self.parse_reason(response.headers)
            raise CrmAPIError(f'API request failed (status {self.status_code}): {reason}')

        if not response.content:
            raise CrmAPIError('Empty response content from API.')

        return response.json()

    def normalize_url(self, action):
        return f"{self.url}{self.url_path}{action}"

    @staticmethod
    def parse_reason(headers):
        return headers.get('X-Status-Reason', 'Unknown Error')


Example Usage

from crm_api_client import CrmAPI

client = CrmAPI('https://<your-platform-domain>', 'your_api_key')

# Create a new Lead
lead_data = {
    'firstName': 'Emily',
    'lastName': 'Taylor',
    'phoneNumber': '+61-400-123-456',
    'source': 'Web Site',
    'assignedUserId': '6822ef96405f954fa',
    'industry': 'Construction',
}
print(client.request('POST', 'Lead', lead_data))

# Update an existing Lead
print(client.request('PUT', 'Lead/64ec572ad412296e5', {'lastName': 'Alice'}))

# Delete an Opportunity
print(client.request('DELETE', 'Opportunity/6822cbe8baf95a8e3'))

# Get a list of Accounts
print(client.request('GET', 'Account'))

# Search for Accounts with Australian phone numbers
search_params = {
    "select": "id,phoneNumber",
    "where": [
        {
            "type": "equals",
            "attribute": "phoneNumber",
            "value": "+61"
        }
    ]
}
print(client.request('GET', 'Account', search_params))


Features

  • Lightweight wrapper around the REST API

  • Supports all major HTTP methods: GET, POST, PUT, PATCH, DELETE, OPTIONS

  • Built-in support for API Key and HMAC authentication

  • JSON response handling with error detection

  • Easily extensible for advanced use cases (e.g., custom ports, timeouts)


Notes

  • For updates and deletions, the id of the record must be provided.

  • Refer to the Metadata API or Entity Manager to discover available entity types and fields.

  • Designed for use in Python environments.


See also

Other API Client Examples: