Skip to main content

Official Python client SDK for NeoCore API authentication using Ed25519 signatures

Project description

NeoCore Security SDK

Official Python client SDK for NeoCore API authentication using Ed25519 digital signatures.

Python Version License

๐Ÿ” Overview

This SDK provides banking-grade security for NeoCore API authentication using Ed25519 asymmetric cryptography. All requests are automatically signed with your private key, and the server verifies signatures using your registered public key.

Key Features

  • โœ… Ed25519 Digital Signatures - Industry-standard asymmetric cryptography
  • โœ… Automatic Request Signing - Zero-configuration signing for all HTTP methods
  • โœ… Smart Key Discovery - OS-specific default locations for private keys
  • โœ… Replay Attack Protection - Timestamp and nonce validation
  • โœ… Zero-Trust Architecture - Private key never leaves your machine
  • โœ… Simple, Intuitive API - Pythonic interface for all operations
  • โœ… Comprehensive Error Handling - Clear exception hierarchy

๐Ÿ“ฆ Installation

pip install neocore-sdk

Requirements:

  • Python 3.8 or higher
  • cryptography>=41.0.0
  • requests>=2.31.0

๐Ÿš€ Quick Start

1. Generate Ed25519 Key Pair

# Using the SDK CLI (recommended)
neocore-keygen

# Or using OpenSSL
openssl genpkey -algorithm ED25519 -out ~/.neocore/p_a1b2c3.pem
openssl pkey -in ~/.neocore/p_a1b2c3.pem -pubout -out ~/.neocore/pub_a1b2c3.pem

c This creates:

  • ~/.neocore/p_a1b2c3.pem - Keep secret! Never share or commit to git
  • ~/.neocore/pub_a1b2c3.pem - Safe to share with NeoCore API

2. Register Your Public Key

Register your public key with the NeoCore API (requires Firebase authentication):

import requests
import uuid

# Read your public key
with open("~/.neocore/pub_a1b2c3.pem", "r") as f:
    public_key_pem = f.read()

# Get Firebase JWT from your authentication flow
firebase_jwt = "your-firebase-jwt-token"

# Generate unique key ID
key_id = str(uuid.uuid4())

# Register with NeoCore API
response = requests.post(
    "https://api.neosapien.xyz/api/v1/dev-keys",
    headers={"Authorization": f"Bearer {firebase_jwt}"},
    json={
        "key_id": key_id,
        "public_key_pem": public_key_pem
    }
)

# Save this key_id - you'll need it for all SDK requests
print(f"Your key_id: {key_id}")

3. Make Authenticated Requests

from neocore_sdk import NeoCoreClient

# Initialize client (auto-discovers private key from default locations)
# Uses default NeoCore API URL: https://api.neosapien.xyz
client = NeoCoreClient(key_id="your-key-id-from-step-2")

# Make signed requests - that's it!
response = client.get("/api/v1/users")
print(response.json())

๐Ÿ“– Complete Usage Guide

Initialize the Client

from neocore_sdk import NeoCoreClient

# Basic initialization (uses default NeoCore API URL)
client = NeoCoreClient(key_id="your-key-id")

# Custom base URL (for different environments or custom deployments)
client = NeoCoreClient(
    key_id="your-key-id",
    base_url="https://custom-api.example.com"
)

# With custom private key path
client = NeoCoreClient(
    key_id="your-key-id",
    private_key_path="/custom/path/to/p_a1b2c3.pem"
)

# With custom timeout
client = NeoCoreClient(
    key_id="your-key-id",
    timeout=60  # seconds (default: 30)
)

# All options combined
client = NeoCoreClient(
    key_id="your-key-id",
    base_url="https://staging-api.neosapien.xyz",
    private_key_path="/secure/keys/staging_p_a1b2c3.pem",
    timeout=45
)

HTTP Methods

All HTTP methods are supported with automatic signing:

GET Request

# Simple GET
response = client.get("/api/v1/users")

# GET with query parameters
response = client.get("/api/v1/users", params={
    "page": 1,
    "limit": 20,
    "sort": "created_at",
    "order": "desc"
})

POST Request

# POST with JSON body
response = client.post("/api/v1/users", data={
    "name": "John Doe",
    "email": "john@example.com",
    "role": "developer"
})

# POST with nested data
response = client.post("/api/v1/projects", data={
    "name": "AI Assistant",
    "metadata": {
        "tech_stack": ["Python", "FastAPI"],
        "status": "active"
    },
    "tags": ["ai", "api"]
})

PUT Request (Full Update)

response = client.put("/api/v1/users/123", data={
    "name": "Jane Doe",
    "email": "jane@example.com",
    "role": "admin"
})

PATCH Request (Partial Update)

# Update only specific fields
response = client.patch("/api/v1/users/123", data={
    "email": "newemail@example.com"
})

DELETE Request

# Simple DELETE
response = client.delete("/api/v1/users/123")

# DELETE with query parameters
response = client.delete("/api/v1/sessions", params={
    "status": "expired",
    "older_than_days": 30
})

Response Handling

All methods return a requests.Response object:

response = client.get("/api/v1/users")

# Status code
print(response.status_code)  # 200, 401, 404, etc.

# JSON response
data = response.json()

# Raw text
text = response.text

# Headers
print(response.headers)

# Check if successful (2xx status)
if response.ok:
    print("Success!")
else:
    print(f"Error: {response.status_code}")

๐Ÿ”‘ Private Key Management

Default Key Locations

The SDK automatically searches for your private key in these locations (in order):

Linux/macOS

  1. ~/.neocore/p_a1b2c3.pem โญ RECOMMENDED
  2. ~/.ssh/p_a1b2c3.pem
  3. /etc/neocore/p_a1b2c3.pem
  4. ./p_a1b2c3.pem (current directory)

Windows

  1. %USERPROFILE%\.neocore\p_a1b2c3.pem โญ RECOMMENDED
  2. %APPDATA%\neocore\p_a1b2c3.pem
  3. %PROGRAMDATA%\neocore\p_a1b2c3.pem
  4. .\p_a1b2c3.pem (current directory)

Custom Key Path

client = NeoCoreClient(
    key_id="your-key-id",
    private_key_path="/secure/vault/my-key.pem"
)

๐Ÿ›ก๏ธ Exception Handling

The SDK provides a comprehensive exception hierarchy for precise error handling.

Exception Hierarchy

SecureSDKError (Base exception)
โ”œโ”€โ”€ KeyLoadError (Key loading failures)
โ”‚   โ””โ”€โ”€ KeyNotFoundError (No key found in default locations)
โ”œโ”€โ”€ SigningError (Signature generation failures)
โ”œโ”€โ”€ APIConnectionError (HTTP connection failures)
โ””โ”€โ”€ CanonicalizationError (Request canonicalization failures)

Import Exceptions

from neocore_sdk import (
    NeoCoreClient,
    SecureSDKError,
    KeyLoadError,
    KeyNotFoundError,
    SigningError,
    APIConnectionError,
    CanonicalizationError
)

Exception Examples

KeyLoadError

Raised when private key cannot be loaded or is invalid.

try:
    client = NeoCoreClient(
        key_id="your-key-id",
        private_key_path="/invalid/path/p_a1b2c3.pem"
    )
except KeyLoadError as e:
    print(f"Failed to load private key: {e}")
    print("Solution: Check the key path and file permissions")

KeyNotFoundError

Raised when no private key is found in default locations (inherits from KeyLoadError).

try:
    client = NeoCoreClient(
        key_id="your-key-id"
        # No private_key_path specified - will auto-discover
    )
except KeyNotFoundError as e:
    print(f"No private key found: {e}")
    print("Solution: Generate keys with: neocore-keygen")
except KeyLoadError as e:
    print(f"Key load error: {e}")

SigningError

Raised when signature generation fails.

try:
    response = client.post("/api/v1/users", data={"name": "John"})
except SigningError as e:
    print(f"Failed to sign request: {e}")
    print("Solution: Verify your private key is valid")

APIConnectionError

Raised when HTTP connection to API fails.

try:
    response = client.get("/api/v1/users")
except APIConnectionError as e:
    print(f"Connection failed: {e}")
    print("Solution: Check network connectivity and base_url")

CanonicalizationError

Raised when request canonicalization fails (rare).

try:
    response = client.get("/api/v1/users")
except CanonicalizationError as e:
    print(f"Canonicalization failed: {e}")
    print("Solution: Contact support - this is unusual")

Comprehensive Error Handling

from neocore_sdk import (
    NeoCoreClient,
    KeyLoadError,
    KeyNotFoundError,
    SigningError,
    APIConnectionError,
    CanonicalizationError
)

try:
    # Initialize client
    client = NeoCoreClient(key_id="your-key-id")

    # Make request
    response = client.get("/api/v1/users", params={"page": 1})

    # Handle HTTP errors
    if response.status_code == 200:
        users = response.json()
        print(f"Found {len(users)} users")
    elif response.status_code == 401:
        print("Unauthorized: Check your key_id or signature")
    elif response.status_code == 403:
        print("Forbidden: Insufficient permissions")
    elif response.status_code == 404:
        print("Not found: Check endpoint path")
    elif response.status_code == 429:
        print("Rate limited: Too many requests")
    else:
        print(f"HTTP Error {response.status_code}: {response.text}")

except KeyNotFoundError as e:
    print(f"โŒ No private key found: {e}")
    print("Run: neocore-keygen")

except KeyLoadError as e:
    print(f"โŒ Key load error: {e}")
    print("Check file path and permissions")

except SigningError as e:
    print(f"โŒ Signing failed: {e}")
    print("Verify your private key is valid")

except APIConnectionError as e:
    print(f"โŒ Connection error: {e}")
    print("Check network and base_url")

except CanonicalizationError as e:
    print(f"โŒ Canonicalization error: {e}")
    print("Contact support")

except Exception as e:
    print(f"โŒ Unexpected error: {e}")

๐Ÿ”ง CLI Tools

The SDK includes command-line tools for key management.

neocore-keygen

Generate a new Ed25519 key pair.

# Generate in default location (~/.neocore/)
neocore-keygen

# Generate in custom location
neocore-keygen --output-dir /path/to/keys

# Overwrite existing keys without prompting
neocore-keygen --force

# Combine options
neocore-keygen --output-dir /secure/keys --force

Options:

  • --output-dir DIR - Directory to save keys (default: ~/.neocore)
  • --force - Overwrite existing keys without prompting

Output:

โœ… Key pair generated successfully!
   Private key: p_a1b2c3.pem (Keep this SECRET!)
   Public key:  pub_a1b2c3.pem (Share with NeoCore API)

neocore-verify-key

Verify an Ed25519 private key and extract public key.

# Verify default key
neocore-verify-key

# Verify custom key
neocore-verify-key /path/to/p_a1b2c3.pem

Output:

โœ… Private key is valid!
   Algorithm: Ed25519
   Key file: /home/user/.neocore/p_a1b2c3.pem
   Permissions: 600 (Secure)

๐Ÿ“‹ Public Key:
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA...
-----END PUBLIC KEY-----

๐Ÿ” Security Features

How It Works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      Client Side (SDK)                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  1. Prepare Request                                         โ”‚
โ”‚     - Method: GET, POST, etc.                               โ”‚
โ”‚     - Path: /api/v1/users                                   โ”‚
โ”‚     - Query: ?page=1&limit=10                               โ”‚
โ”‚     - Body: {"name": "John"}                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  2. Generate Security Metadata                              โ”‚
โ”‚     - Timestamp: Unix seconds (e.g., 1704214800)            โ”‚
โ”‚     - Nonce: UUID v4 (e.g., a1b2c3d4-...)                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  3. Build Canonical String                                  โ”‚
โ”‚     GET                                                     โ”‚
โ”‚     /api/v1/users                                           โ”‚
โ”‚     limit=10&page=1                                         โ”‚
โ”‚     e3b0c44... (SHA256 of body)                             โ”‚
โ”‚     1704214800                                              โ”‚
โ”‚     a1b2c3d4-...                                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  4. Sign with Private Key (Ed25519)                         โ”‚
โ”‚     signature = sign(canonical_string, private_key)         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  5. Add Headers to Request                                  โ”‚
โ”‚     Content-Type: application/json                          โ”‚
โ”‚     X-Key-Id: your-key-id                                   โ”‚
โ”‚     X-Timestamp: 1704214800                                 โ”‚
โ”‚     X-Nonce: a1b2c3d4-...                                   โ”‚
โ”‚     X-Signature: abc123... (hex)                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  6. Send HTTP Request                                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      Server Side (NeoCore API)              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  1. Extract X-Key-Id from headers                           โ”‚
โ”‚  2. Fetch public key from database                          โ”‚
โ”‚  3. Rebuild canonical string from request                   โ”‚
โ”‚  4. Verify signature using public key                       โ”‚
โ”‚  5. Validate timestamp (within time window)                 โ”‚
โ”‚  6. Check nonce uniqueness (prevent replay)                 โ”‚
โ”‚  7. โœ… Authorized โ†’ Process request                         โ”‚
โ”‚     โŒ Unauthorized โ†’ Return 401                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Automatic Security Headers

Every request includes these headers (automatically added by SDK):

Header Description Example
Content-Type Request content type application/json
X-Key-Id Your registered key ID a1b2c3d4-uuid
X-Timestamp Unix timestamp (seconds) 1704214800
X-Nonce Unique request ID (UUID v4) f1e2d3c4-uuid
X-Signature Ed25519 signature (hex) 9a8b7c6d...

Security Benefits

  1. Zero-Trust Architecture

    • Private key never leaves your machine
    • Server never knows your secret
    • Database breach doesn't compromise credentials
  2. Request Integrity

    • Signature covers method, path, query, body, timestamp, nonce
    • Any tampering invalidates signature
    • Man-in-the-middle attacks prevented
  3. Replay Attack Protection

    • Timestamp validation (requests expire in 5 minutes)
    • Nonce uniqueness check (prevent duplicate requests)
    • Old requests automatically rejected
  4. Instant Revocation

    • Server can revoke key_id instantly
    • No token expiration wait time
    • Granular access control per key

๐Ÿ“‹ API Reference

NeoCoreClient

Main client class for making authenticated requests.

Constructor

NeoCoreClient(
    key_id: str,
    base_url: str = "https://api.neosapien.xyz",
    private_key_path: Optional[str] = None,
    timeout: int = 30
)

Parameters:

  • key_id (str): Your registered developer key ID (required)
  • base_url (str): API base URL (default: "https://api.neosapien.xyz")
    • Override for custom deployments, staging, or development environments
  • private_key_path (Optional[str]): Path to private key PEM file. If None, searches default locations.
  • timeout (int): Request timeout in seconds (default: 30)

Raises:

  • KeyLoadError: If private key cannot be loaded
  • KeyNotFoundError: If no key found in default locations

Examples:

# Basic (uses default NeoCore API)
client = NeoCoreClient(key_id="a1b2c3d4-5678-90ab-cdef-1234567890ab")

# Custom base URL
client = NeoCoreClient(
    key_id="a1b2c3d4-5678-90ab-cdef-1234567890ab",
    base_url="https://staging-api.neosapien.xyz"
)

Methods

All methods automatically sign requests and return requests.Response.

get()
get(endpoint: str, params: Optional[dict] = None) -> requests.Response

Send signed GET request.

Parameters:

  • endpoint (str): API endpoint path
  • params (Optional[dict]): Query parameters

Returns: requests.Response

Example:

response = client.get("/api/v1/users", params={"page": 1})
post()
post(endpoint: str, data: Optional[dict] = None) -> requests.Response

Send signed POST request.

Parameters:

  • endpoint (str): API endpoint path
  • data (Optional[dict]): JSON body data

Returns: requests.Response

Example:

response = client.post("/api/v1/users", data={"name": "John"})
put()
put(endpoint: str, data: Optional[dict] = None) -> requests.Response

Send signed PUT request (full update).

Parameters:

  • endpoint (str): API endpoint path
  • data (Optional[dict]): JSON body data

Returns: requests.Response

Example:

response = client.put("/api/v1/users/123", data={"name": "Jane"})
patch()
patch(endpoint: str, data: Optional[dict] = None) -> requests.Response

Send signed PATCH request (partial update).

Parameters:

  • endpoint (str): API endpoint path
  • data (Optional[dict]): JSON body data

Returns: requests.Response

Example:

response = client.patch("/api/v1/users/123", data={"email": "new@email.com"})
delete()
delete(endpoint: str, params: Optional[dict] = None) -> requests.Response

Send signed DELETE request.

Parameters:

  • endpoint (str): API endpoint path
  • params (Optional[dict]): Query parameters

Returns: requests.Response

Example:

response = client.delete("/api/v1/users/123")

๐ŸŽฏ Best Practices

1. Key Security

# โœ… GOOD: Keep private keys secure
# - Store in ~/.neocore/ with permissions 600
# - Never commit to git (add *.pem to .gitignore)
# - Use environment variables in production

# โŒ BAD: Don't hardcode key paths in source code
client = NeoCoreClient(
    key_id="key-123",
    private_key_path="/hardcoded/path/p_a1b2c3.pem"  # Bad!
)

# โœ… GOOD: Use environment variables
import os
client = NeoCoreClient(
    key_id=os.getenv("NEOCORE_KEY_ID"),
    base_url=os.getenv("NEOCORE_API_URL", "https://api.neosapien.xyz"),
    private_key_path=os.getenv("NEOCORE_PRIVATE_KEY_PATH")
)

2. Error Handling

# โœ… GOOD: Catch specific exceptions
try:
    response = client.get("/api/v1/users")
except KeyNotFoundError:
    # Specific handling for missing key
    print("Generate keys with: neocore-keygen")
except APIConnectionError:
    # Specific handling for network issues
    print("Check your network connection")

# โŒ BAD: Catch generic exceptions
try:
    response = client.get("/api/v1/users")
except Exception as e:
    print(f"Something went wrong: {e}")

3. Response Handling

# โœ… GOOD: Check status codes properly
response = client.get("/api/v1/users")
if response.status_code == 200:
    data = response.json()
    # Process data
elif response.status_code == 401:
    print("Unauthorized")
elif response.status_code == 404:
    print("Not found")

# โŒ BAD: Assume all responses are successful
response = client.get("/api/v1/users")
data = response.json()  # May fail if status is not 200

4. Key Rotation

# Regularly rotate your keys
# 1. Generate new key pair
# 2. Register new public key with new key_id
# 3. Update your application to use new key_id
# 4. After verification, delete old key from server
# 5. Delete old private key from your system

๐Ÿ› Troubleshooting

"No private key found"

Error:

KeyNotFoundError: No private key found in default locations

Solution:

# Generate keys
neocore-keygen

# Or specify custom path
client = NeoCoreClient(
    key_id="...",
    private_key_path="/custom/path/p_a1b2c3.pem"
)

"Invalid signature"

Error:

HTTP 401: Invalid signature

Causes & Solutions:

  1. Wrong key_id: Verify key_id matches registered public key
  2. Key mismatch: Private key doesn't match registered public key
  3. Clock skew: System time is incorrect (timestamp validation fails)
    # Sync system time
    sudo ntpdate -s time.nist.gov  # Linux/macOS
    

"Connection error"

Error:

APIConnectionError: Failed to connect to https://api.example.com

Solutions:

  1. Check network connectivity
  2. Verify base_url is correct
  3. Check if API server is running
  4. Verify firewall/proxy settings

"Permission denied" (Key file)

Error:

PermissionError: [Error no. 13] Permission denied: '/path/to/p_a1b2c3.pem'

Solution:

# Fix file permissions
chmod 600 ~/.neocore/p_a1b2c3.pem

๐Ÿ“š Examples

See the examples directory for more:


๐Ÿค Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.


๐Ÿ“„ License

This project is licensed under the MIT License - see LICENSE file for details.


๐Ÿ”— Links


๐Ÿ’ก Support

For help and support:


๐ŸŽ‰ Quick Reference

# Install
pip install neocore-sdk

# Generate keys
neocore-keygen

# Import and use
from neocore_sdk import NeoCoreClient

# Initialize (uses default NeoCore API URL)
client = NeoCoreClient(key_id="your-key-id")

# Make requests
response = client.get("/api/v1/users")
response = client.post("/api/v1/users", data={"name": "John"})
response = client.put("/api/v1/users/123", data={"name": "Jane"})
response = client.patch("/api/v1/users/123", data={"email": "new@email.com"})
response = client.delete("/api/v1/users/123")

# Custom base URL (for staging/development)
staging_client = NeoCoreClient(
    key_id="staging-key-id",
    base_url="https://staging-api.neosapien.xyz"
)

Made by NeoSapien

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

neocore_sdk-1.0.0.tar.gz (44.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

neocore_sdk-1.0.0-py3-none-any.whl (31.0 kB view details)

Uploaded Python 3

File details

Details for the file neocore_sdk-1.0.0.tar.gz.

File metadata

  • Download URL: neocore_sdk-1.0.0.tar.gz
  • Upload date:
  • Size: 44.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.4

File hashes

Hashes for neocore_sdk-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a620a1f49a9b9f21e0a0fedbcfb1e4e3522b8882bddb0d966e8b620861d19746
MD5 7bb8179df955ae1b3428b94cda964993
BLAKE2b-256 8089758f19289e20ac2dae75932eeeee56415940c9a1184e68f1ab489f9110a6

See more details on using hashes here.

File details

Details for the file neocore_sdk-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: neocore_sdk-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 31.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.4

File hashes

Hashes for neocore_sdk-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7bdfa780a06d56c71db740864f6bfb969df2a0f706f712318f5a273c1c1999a8
MD5 4a19c79a6cb082869642f41c70a99717
BLAKE2b-256 f1e1a708336b1ab0875baff756126596fc193430c31996dd796aed2f53728173

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page