MOO-AI REST API • v1

Moo-AI API Documentation

Connect websites, apps, servers, desktop software, and mobile applications to Moo-AI using HTTPS and JSON. The examples below use the public Moo-AI API at https://moozonian.com/moo-ai.

Overview

Moo-AI uses a REST-style JSON API. Send requests over HTTPS, authenticate with a moo_sk_... secret key, and receive JSON responses.

Base URLhttps://moozonian.com/moo-ai
Content typeapplication/json
AuthenticationBearer API key

Authentication

Protected endpoints require a Moo-AI API key in the HTTP Authorization header.

Authorization header
Authorization: Bearer moo_sk_YOUR_API_KEY
Never put a secret API key in public browser JavaScript, HTML, a Git repository, or a mobile bundle.

For browser-based websites, call Moo-AI from your own server-side PHP/Node/Ruby/etc. endpoint. Your browser should call your backend, and your backend should attach the Moo-AI key.

Models & reasoning levels

ModelUsePlan
moo-miniFast general requestsFree, Pro, Business
moo-coreGeneral production workloadsPro, Business
moo-reasonHigher-effort reasoningPro, Business
reasoning_effortAvailability
instantFree, Pro, Business
standardFree, Pro, Business
deepPro, Business

Endpoints

MethodEndpointAuthenticationDescription
GET/healthNoAPI health status
GET/v1/plansNoAvailable plans and limits
GET/v1/modelsYesModels available to the account
GET/v1/accountYesCurrent account and plan
GET/v1/usageYesCurrent usage
POST/v1/chat/completionsYesGenerate a Moo-AI response
POST/v1/billing/checkoutYesCreate Pro checkout session
POST/v1/billing/portalYesOpen billing management

Chat completions

POSThttps://moozonian.com/moo-ai/v1/chat/completions

Request body

JSON
{
  "model": "moo-mini",
  "reasoning_effort": "standard",
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant."
    },
    {
      "role": "user",
      "content": "Explain how solar panels work."
    }
  ],
  "max_tokens": 800,
  "temperature": 0.7
}
FieldTypeRequiredDescription
modelstringNoDefaults to moo-mini.
reasoning_effortstringNoinstant, standard, or deep.
messagesarrayYesConversation messages.
max_tokensintegerNoMaximum generated output tokens, bounded by plan limits.
temperaturenumberNoSampling temperature from 0 to 2.

Response format

JSON response
{
  "id": "chatcmpl_...",
  "object": "chat.completion",
  "created": 1788750000,
  "model": "moo-mini",
  "reasoning_effort": "standard",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 42,
    "completion_tokens": 116,
    "total_tokens": 158
  },
  "moo": {
    "plan": "free",
    "latency_ms": 842,
    "backend": "local"
  }
}

The generated assistant text is located at choices[0].message.content.

Programming language examples

Replace moo_sk_YOUR_API_KEY with a key generated from your Moo-AI developer dashboard.

PHP

PHP 8+
<?php
$apiKey = getenv('MOO_AI_API_KEY');

$payload = [
    'model' => 'moo-mini',
    'reasoning_effort' => 'standard',
    'messages' => [
        ['role' => 'user', 'content' => 'Hello from PHP']
    ]
];

$ch = curl_init('https://moozonian.com/moo-ai/v1/chat/completions');

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_TIMEOUT => 120
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}

curl_close($ch);

$data = json_decode($response, true);

if ($status >= 400) {
    throw new RuntimeException($data['error']['message'] ?? 'Moo-AI request failed');
}

echo $data['choices'][0]['message']['content'];

JavaScript / Node.js

Use this server-side in Node.js 18+ so the secret key remains private.

Node.js
const response = await fetch('https://moozonian.com/moo-ai/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MOO_AI_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    model: 'moo-mini',
    reasoning_effort: 'standard',
    messages: [
      { role: 'user', content: 'Hello from Node.js' }
    ]
  })
});

const data = await response.json();

if (!response.ok) {
  throw new Error(data?.error?.message || 'Moo-AI request failed');
}

console.log(data.choices[0].message.content);

jQuery

Browser-safe pattern:

Do not put moo_sk_... in jQuery. Have jQuery call your own server endpoint, and let that server endpoint call Moo-AI.

jQuery browser client
$.ajax({
  url: '/api/ask-moo.php',
  method: 'POST',
  contentType: 'application/json',
  data: JSON.stringify({
    message: 'Hello from my website'
  }),
  success: function (data) {
    $('#answer').text(data.answer);
  },
  error: function () {
    $('#answer').text('Moo-AI request failed');
  }
});

Your /api/ask-moo.php server route should use the PHP example above and inject the secret key from an environment variable.

HTML5

HTML5 itself cannot securely store a secret API key. Submit to your own backend endpoint.

HTML5
<form id="moo-form">
  <textarea id="prompt" required></textarea>
  <button type="submit">Ask Moo-AI</button>
</form>

<pre id="answer"></pre>

<script>
document.getElementById('moo-form').addEventListener('submit', async (event) => {
  event.preventDefault();

  const response = await fetch('/api/ask-moo.php', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({
      message: document.getElementById('prompt').value
    })
  });

  const data = await response.json();
  document.getElementById('answer').textContent = data.answer;
});
</script>

Ruby

Ruby
require 'net/http'
require 'json'
require 'uri'

uri = URI('https://moozonian.com/moo-ai/v1/chat/completions')

request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV.fetch('MOO_AI_API_KEY')}"
request['Content-Type'] = 'application/json'
request.body = {
  model: 'moo-mini',
  reasoning_effort: 'standard',
  messages: [
    { role: 'user', content: 'Hello from Ruby' }
  ]
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

data = JSON.parse(response.body)

raise(data.dig('error', 'message') || 'Moo-AI request failed') unless response.is_a?(Net::HTTPSuccess)

puts data.dig('choices', 0, 'message', 'content')

C++

This example uses libcurl and nlohmann/json.

C++17
#include <curl/curl.h>
#include <nlohmann/json.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

using json = nlohmann::json;

size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    static_cast<std::string*>(userp)->append(
        static_cast<char*>(contents), size * nmemb
    );
    return size * nmemb;
}

int main() {
    const char* key = std::getenv("MOO_AI_API_KEY");
    if (!key) return 1;

    json body = {
        {"model", "moo-mini"},
        {"reasoning_effort", "standard"},
        {"messages", {{{"role", "user"}, {"content", "Hello from C++"}}}}
    };

    CURL* curl = curl_easy_init();
    std::string response;

    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: Bearer " + std::string(key)).c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");

    curl_easy_setopt(curl, CURLOPT_URL, "https://moozonian.com/moo-ai/v1/chat/completions");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.dump().c_str());
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    CURLcode result = curl_easy_perform(curl);

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);

    if (result != CURLE_OK) return 1;

    auto data = json::parse(response);
    std::cout << data["choices"][0]["message"]["content"] << "\n";
}

ASP.NET / C#

C# / ASP.NET Core
using System.Net.Http.Headers;
using System.Net.Http.Json;

var http = new HttpClient();

http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue(
        "Bearer",
        Environment.GetEnvironmentVariable("MOO_AI_API_KEY")
    );

var payload = new
{
    model = "moo-mini",
    reasoning_effort = "standard",
    messages = new[]
    {
        new { role = "user", content = "Hello from ASP.NET" }
    }
};

var response = await http.PostAsJsonAsync(
    "https://moozonian.com/moo-ai/v1/chat/completions",
    payload
);

var data = await response.Content.ReadFromJsonAsync<MooResponse>();

response.EnsureSuccessStatusCode();

Console.WriteLine(data!.choices[0].message.content);

public record MooResponse(Choice[] choices);
public record Choice(Message message);
public record Message(string role, string content);

Python

Python 3
import os
import requests

response = requests.post(
    "https://moozonian.com/moo-ai/v1/chat/completions",
    headers={
        "Authorization": f"Bearer {os.environ['MOO_AI_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "moo-mini",
        "reasoning_effort": "standard",
        "messages": [
            {"role": "user", "content": "Hello from Python"}
        ],
    },
    timeout=120,
)

response.raise_for_status()
data = response.json()

print(data["choices"][0]["message"]["content"])

Java

Java 11+
import java.net.URI;
import java.net.http.*;
import java.time.Duration;

public class MooAIExample {
    public static void main(String[] args) throws Exception {
        String key = System.getenv("MOO_AI_API_KEY");

        String json = """
        {
          "model":"moo-mini",
          "reasoning_effort":"standard",
          "messages":[
            {"role":"user","content":"Hello from Java"}
          ]
        }
        """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://moozonian.com/moo-ai/v1/chat/completions"))
            .timeout(Duration.ofSeconds(120))
            .header("Authorization", "Bearer " + key)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();

        HttpResponse<String> response =
            HttpClient.newHttpClient().send(
                request,
                HttpResponse.BodyHandlers.ofString()
            );

        System.out.println(response.body());
    }
}

Go

Go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    payload := map[string]any{
        "model": "moo-mini",
        "reasoning_effort": "standard",
        "messages": []map[string]string{
            {"role": "user", "content": "Hello from Go"},
        },
    }

    body, _ := json.Marshal(payload)

    req, _ := http.NewRequest(
        "POST",
        "https://moozonian.com/moo-ai/v1/chat/completions",
        bytes.NewReader(body),
    )

    req.Header.Set("Authorization", "Bearer "+os.Getenv("MOO_AI_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()

    data, _ := io.ReadAll(res.Body)
    fmt.Println(string(data))
}

Swift

Swift
import Foundation

let apiKey = ProcessInfo.processInfo.environment["MOO_AI_API_KEY"]!

let url = URL(string: "https://moozonian.com/moo-ai/v1/chat/completions")!

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let payload: [String: Any] = [
    "model": "moo-mini",
    "reasoning_effort": "standard",
    "messages": [
        ["role": "user", "content": "Hello from Swift"]
    ]
]

request.httpBody = try JSONSerialization.data(withJSONObject: payload)

let (data, response) = try await URLSession.shared.data(for: request)

if let http = response as? HTTPURLResponse, !(200...299).contains(http.statusCode) {
    throw URLError(.badServerResponse)
}

print(String(data: data, encoding: .utf8)!)

Kotlin

Kotlin + Java HttpClient
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

fun main() {
    val apiKey = System.getenv("MOO_AI_API_KEY")

    val body = """
    {
      "model":"moo-mini",
      "reasoning_effort":"standard",
      "messages":[
        {"role":"user","content":"Hello from Kotlin"}
      ]
    }
    """.trimIndent()

    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://moozonian.com/moo-ai/v1/chat/completions"))
        .header("Authorization", "Bearer $apiKey")
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build()

    val response = HttpClient.newHttpClient()
        .send(request, HttpResponse.BodyHandlers.ofString())

    println(response.body())
}

Rust

Rust + reqwest
use reqwest::Client;
use serde_json::json;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let response = client
        .post("https://moozonian.com/moo-ai/v1/chat/completions")
        .bearer_auth(env::var("MOO_AI_API_KEY")?)
        .json(&json!({
            "model": "moo-mini",
            "reasoning_effort": "standard",
            "messages": [
                {"role": "user", "content": "Hello from Rust"}
            ]
        }))
        .send()
        .await?
        .error_for_status()?;

    let data: serde_json::Value = response.json().await?;

    println!("{}", data["choices"][0]["message"]["content"]);

    Ok(())
}

Dart / Flutter

For production mobile apps, call Moo-AI from your own authenticated backend rather than embedding the secret API key in the shipped application.

Dart server-side example
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Future<void> main() async {
  final key = Platform.environment['MOO_AI_API_KEY']!;

  final response = await http.post(
    Uri.parse('https://moozonian.com/moo-ai/v1/chat/completions'),
    headers: {
      'Authorization': 'Bearer $key',
      'Content-Type': 'application/json',
    },
    body: jsonEncode({
      'model': 'moo-mini',
      'reasoning_effort': 'standard',
      'messages': [
        {'role': 'user', 'content': 'Hello from Dart'}
      ]
    }),
  );

  if (response.statusCode >= 400) {
    throw Exception(response.body);
  }

  final data = jsonDecode(response.body);
  print(data['choices'][0]['message']['content']);
}

Bash / cURL

Bash
export MOO_AI_API_KEY="moo_sk_YOUR_API_KEY"

curl -X POST "https://moozonian.com/moo-ai/v1/chat/completions" \
  -H "Authorization: Bearer $MOO_AI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"moo-mini",
    "reasoning_effort":"standard",
    "messages":[
      {"role":"user","content":"Hello from Bash"}
    ]
  }'

Error handling

StatusMeaningTypical cause
400Bad requestInvalid JSON or missing messages.
401Authentication errorMissing, invalid, or revoked API key.
403Access errorModel or reasoning level not included in the current plan.
404Not foundUnknown API route.
429Rate/quota limitMinute, daily, or monthly allowance exceeded.
502Backend errorThe local Moo-AI inference backend is unavailable.
503Service unavailableDatabase or service health problem.
Error JSON
{
  "error": {
    "message": "Invalid or revoked Moo-AI API key.",
    "type": "authentication_error"
  }
}

Security guidance

  • Store keys in environment variables or a secret manager.
  • Never commit moo_sk_... keys to Git.
  • Never embed a secret key in HTML, public JavaScript, jQuery, or a distributed mobile/desktop app.
  • For browser and mobile apps, use your own authenticated backend as a proxy to Moo-AI.
  • Revoke a key immediately from the dashboard if it is exposed.
  • Create separate keys for separate servers or applications so they can be revoked independently.