Skip to main content

AI / Jarvis Block

AI Block

Machine learning features for modern applications

The AI Block brings powerful machine learning capabilities to your application without the complexity of building ML infrastructure. Leverage pre-built AI features for text analysis, image recognition, recommendations, content moderation, and more—all through a simple REST API.

Features

  • Text Analysis - Sentiment, entities, key phrases, and language detection
  • Image Recognition - Classification, object detection, and OCR
  • Smart Recommendations - Personalized suggestions based on user behavior
  • Content Moderation - Detect inappropriate content and spam
  • Embeddings - Vector representations for semantic search and similarity
  • Language Translation - Translate text between 100+ languages
  • Summarization - Generate concise summaries of long text
  • Classification - Custom text and image classification

Quick Start

npm install @23blocks/sdk

API Endpoint

ServiceURL
AI (Jarvis)https://jarvis.api.us.23blocks.com

Environment Routing: Use the same URL for all environments. Your API key determines the environment:

  • pk_test_* / sk_test_* → Routes to Staging
  • pk_live_* / sk_live_* → Routes to Production
import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { ai: 'https://jarvis.api.us.23blocks.com' },
apiKey: 'your-api-key', // Use pk_test_* for staging, pk_live_* for production
});

// Analyze sentiment
const sentiment = await client.ai.analyzeSentiment({
text: 'This product is amazing!'
});
// { score: 0.92, label: 'positive' }

// Get recommendations
const recs = await client.ai.recommend({
userId: 'user_123',
context: 'product-page',
limit: 5
});

// Moderate content
const moderation = await client.ai.moderate({
text: 'Some user-generated content...'
});

Authentication

All API requests require authentication using your API credentials.

Required Headers

X-App-Id: your-app-id
X-Api-Key: your-api-key
Content-Type: application/json

Text Analysis API

Analyze text for sentiment, entities, and more.

Analyze Sentiment

Determine the emotional tone of text.

POST /ai/v1/text/sentiment

Request Body:

{
"data": {
"type": "sentiment_requests",
"attributes": {
"text": "I absolutely love this product! It exceeded all my expectations.",
"language": "en"
}
}
}

Response:

{
"data": {
"type": "sentiment_results",
"id": "sent_abc123",
"attributes": {
"score": 0.92,
"label": "positive",
"confidence": 0.97,
"scores": {
"positive": 0.92,
"neutral": 0.06,
"negative": 0.02
}
}
}
}

Extract Entities

Identify named entities in text.

POST /ai/v1/text/entities

Request Body:

{
"data": {
"type": "entity_requests",
"attributes": {
"text": "Apple CEO Tim Cook announced new products at the event in Cupertino, California.",
"types": ["PERSON", "ORG", "LOCATION"]
}
}
}

Response:

{
"data": {
"type": "entity_results",
"id": "ent_xyz789",
"attributes": {
"entities": [
{
"text": "Apple",
"type": "ORG",
"start": 0,
"end": 5,
"confidence": 0.98
},
{
"text": "Tim Cook",
"type": "PERSON",
"start": 10,
"end": 18,
"confidence": 0.99
},
{
"text": "Cupertino",
"type": "LOCATION",
"start": 62,
"end": 71,
"confidence": 0.96
},
{
"text": "California",
"type": "LOCATION",
"start": 73,
"end": 83,
"confidence": 0.99
}
]
}
}
}

Entity Types:

TypeDescription
PERSONPeople, including fictional
ORGCompanies, agencies, institutions
LOCATIONCountries, cities, addresses
DATEDates and times
MONEYMonetary values
PRODUCTProducts and vehicles
EVENTNamed events
WORK_OF_ARTTitles of books, songs, etc.

Extract Key Phrases

Identify important phrases in text.

POST /ai/v1/text/key-phrases

Request Body:

{
"data": {
"type": "key_phrase_requests",
"attributes": {
"text": "The new machine learning algorithm significantly improves prediction accuracy while reducing computational costs.",
"max_phrases": 5
}
}
}

Response:

{
"data": {
"type": "key_phrase_results",
"attributes": {
"key_phrases": [
{ "phrase": "machine learning algorithm", "score": 0.95 },
{ "phrase": "prediction accuracy", "score": 0.89 },
{ "phrase": "computational costs", "score": 0.85 }
]
}
}
}

Detect Language

Identify the language of text.

POST /ai/v1/text/language

Request Body:

{
"data": {
"type": "language_requests",
"attributes": {
"text": "Bonjour, comment allez-vous?"
}
}
}

Response:

{
"data": {
"type": "language_results",
"attributes": {
"language": "fr",
"language_name": "French",
"confidence": 0.99,
"alternatives": [
{ "language": "it", "language_name": "Italian", "confidence": 0.01 }
]
}
}
}

Summarize Text

Generate a concise summary of long text.

POST /ai/v1/text/summarize

Request Body:

{
"data": {
"type": "summarize_requests",
"attributes": {
"text": "Your long article text here...",
"max_length": 100,
"style": "extractive"
}
}
}

Response:

{
"data": {
"type": "summarize_results",
"attributes": {
"summary": "A concise summary of the input text...",
"length": 85,
"compression_ratio": 0.15
}
}
}

Image Analysis API

Analyze images for classification, objects, and text.

Classify Image

Categorize an image.

POST /ai/v1/image/classify

Request Body:

{
"data": {
"type": "image_classify_requests",
"attributes": {
"image_url": "https://example.com/photo.jpg",
"max_labels": 5
}
}
}

Response:

{
"data": {
"type": "image_classify_results",
"attributes": {
"labels": [
{ "label": "dog", "confidence": 0.97 },
{ "label": "golden retriever", "confidence": 0.94 },
{ "label": "pet", "confidence": 0.92 },
{ "label": "animal", "confidence": 0.99 },
{ "label": "outdoor", "confidence": 0.78 }
]
}
}
}

Detect Objects

Identify and locate objects in an image.

POST /ai/v1/image/detect

Request Body:

{
"data": {
"type": "object_detect_requests",
"attributes": {
"image_url": "https://example.com/street.jpg",
"min_confidence": 0.7
}
}
}

Response:

{
"data": {
"type": "object_detect_results",
"attributes": {
"objects": [
{
"label": "car",
"confidence": 0.95,
"bounding_box": {
"x": 120,
"y": 200,
"width": 350,
"height": 180
}
},
{
"label": "person",
"confidence": 0.88,
"bounding_box": {
"x": 50,
"y": 100,
"width": 80,
"height": 250
}
}
]
}
}
}

Extract Text (OCR)

Extract text from images.

POST /ai/v1/image/ocr

Request Body:

{
"data": {
"type": "ocr_requests",
"attributes": {
"image_url": "https://example.com/document.jpg",
"detect_orientation": true
}
}
}

Response:

{
"data": {
"type": "ocr_results",
"attributes": {
"text": "Extracted text from the image...",
"blocks": [
{
"text": "INVOICE",
"confidence": 0.99,
"bounding_box": { "x": 50, "y": 20, "width": 150, "height": 30 }
},
{
"text": "Order #12345",
"confidence": 0.97,
"bounding_box": { "x": 50, "y": 60, "width": 200, "height": 25 }
}
],
"language": "en",
"orientation": 0
}
}
}

Recommendations API

Generate personalized recommendations.

Get Recommendations

POST /ai/v1/recommendations

Request Body:

{
"data": {
"type": "recommendation_requests",
"attributes": {
"user_id": "user_abc123",
"context": "product-page",
"item_id": "prod_xyz789",
"limit": 5,
"filters": {
"category": "electronics",
"price_max": 500
}
}
}
}

Response:

{
"data": {
"type": "recommendation_results",
"attributes": {
"recommendations": [
{
"item_id": "prod_001",
"score": 0.95,
"reason": "Users who viewed this also viewed"
},
{
"item_id": "prod_002",
"score": 0.87,
"reason": "Similar products"
},
{
"item_id": "prod_003",
"score": 0.82,
"reason": "Based on your history"
}
],
"model_version": "v2.3"
}
}
}

Track User Event

Record user interactions for better recommendations.

POST /ai/v1/recommendations/events

Request Body:

{
"data": {
"type": "recommendation_events",
"attributes": {
"user_id": "user_abc123",
"event_type": "purchase",
"item_id": "prod_xyz789",
"timestamp": "2025-01-15T10:30:00Z",
"metadata": {
"quantity": 1,
"price": 299.99
}
}
}
}

Event Types:

EventDescription
viewUser viewed an item
clickUser clicked on an item
add_to_cartItem added to cart
purchaseItem purchased
ratingUser rated an item
likeUser liked an item

Content Moderation API

Detect inappropriate content.

Moderate Text

POST /ai/v1/moderation/text

Request Body:

{
"data": {
"type": "moderation_requests",
"attributes": {
"text": "User-generated content to check...",
"categories": ["hate", "violence", "sexual", "spam"]
}
}
}

Response:

{
"data": {
"type": "moderation_results",
"attributes": {
"flagged": false,
"categories": {
"hate": { "flagged": false, "score": 0.02 },
"violence": { "flagged": false, "score": 0.01 },
"sexual": { "flagged": false, "score": 0.00 },
"spam": { "flagged": false, "score": 0.05 }
},
"action": "allow"
}
}
}

Moderate Image

POST /ai/v1/moderation/image

Request Body:

{
"data": {
"type": "image_moderation_requests",
"attributes": {
"image_url": "https://example.com/user-upload.jpg",
"categories": ["adult", "violence", "hate"]
}
}
}

Response:

{
"data": {
"type": "image_moderation_results",
"attributes": {
"flagged": false,
"categories": {
"adult": { "flagged": false, "score": 0.03 },
"violence": { "flagged": false, "score": 0.01 },
"hate": { "flagged": false, "score": 0.00 }
},
"action": "allow"
}
}
}

Embeddings API

Generate vector embeddings for semantic operations.

Generate Embeddings

POST /ai/v1/embeddings

Request Body:

{
"data": {
"type": "embedding_requests",
"attributes": {
"inputs": [
"Machine learning is transforming technology",
"AI is revolutionizing software development"
],
"model": "text-embedding-3"
}
}
}

Response:

{
"data": {
"type": "embedding_results",
"attributes": {
"embeddings": [
{
"index": 0,
"embedding": [0.023, -0.045, 0.089, ...],
"dimensions": 1536
},
{
"index": 1,
"embedding": [0.031, -0.052, 0.076, ...],
"dimensions": 1536
}
],
"model": "text-embedding-3",
"usage": {
"tokens": 18
}
}
}
}

Compute Similarity

Compare text similarity.

POST /ai/v1/embeddings/similarity

Request Body:

{
"data": {
"type": "similarity_requests",
"attributes": {
"source": "How do I reset my password?",
"targets": [
"I forgot my login credentials",
"Change my account password",
"What's the weather today?"
]
}
}
}

Response:

{
"data": {
"type": "similarity_results",
"attributes": {
"similarities": [
{ "index": 0, "score": 0.89 },
{ "index": 1, "score": 0.94 },
{ "index": 2, "score": 0.12 }
]
}
}
}

Translation API

Translate text between languages.

Translate Text

POST /ai/v1/translate

Request Body:

{
"data": {
"type": "translation_requests",
"attributes": {
"text": "Hello, how are you today?",
"source_language": "en",
"target_language": "es"
}
}
}

Response:

{
"data": {
"type": "translation_results",
"attributes": {
"translated_text": "Hola, como estas hoy?",
"source_language": "en",
"target_language": "es",
"confidence": 0.98
}
}
}

Supported Languages

Get list of supported languages.

GET /ai/v1/translate/languages

Classification API

Create custom classifiers.

Create Classifier

POST /ai/v1/classifiers

Request Body:

{
"data": {
"type": "classifiers",
"attributes": {
"name": "support-ticket-classifier",
"description": "Classify customer support tickets",
"labels": ["billing", "technical", "general", "urgent"]
}
}
}

Train Classifier

POST /ai/v1/classifiers/:classifier_id/train

Request Body:

{
"data": {
"type": "training_data",
"attributes": {
"examples": [
{ "text": "I was charged twice", "label": "billing" },
{ "text": "App keeps crashing", "label": "technical" },
{ "text": "How do I change settings?", "label": "general" },
{ "text": "URGENT: Service is down!", "label": "urgent" }
]
}
}
}

Classify Text

POST /ai/v1/classifiers/:classifier_id/classify

Request Body:

{
"data": {
"type": "classification_requests",
"attributes": {
"text": "My payment didn't go through"
}
}
}

Response:

{
"data": {
"type": "classification_results",
"attributes": {
"predictions": [
{ "label": "billing", "confidence": 0.92 },
{ "label": "technical", "confidence": 0.05 },
{ "label": "general", "confidence": 0.02 },
{ "label": "urgent", "confidence": 0.01 }
]
}
}
}

Prompt Rendering API

Render dynamic prompts with variable substitution and array transformations.

Render Prompt

Render a prompt template with placeholder values.

POST /ai/v1/prompts/:unique_id/render

Request Body:

{
"placeholders": {
"simple_string": "Hello",
"string_array": ["url1", "url2", "url3"],
"nested_object": {
"title": "My Title",
"metadata": { "author": "John" }
},
"object_array": [
{ "claim": "Fact 1", "priority": "high" },
{ "claim": "Fact 2", "priority": "low" }
]
}
}

Response:

{
"data": {
"type": "rendered_prompts",
"id": 12345,
"attributes": {
"prompt_unique_id": "prompt_abc123",
"rendered_content": "The rendered prompt text with substituted values...",
"placeholders_used": ["simple_string", "string_array", "nested_object"]
}
}
}
Breaking Change

The response id field is now an integer (previously UUID). Use prompt_unique_id for the UUID identifier.

Placeholder Syntax

PatternExampleDescription
Simple{{name}}Basic variable substitution
Nested object{{user.email}}Access nested object fields
Array index{{items[0]}}Access array element by index
Combined{{steps[0].title}}Index access + field access

Pipe Transforms for Arrays

Transform array values using pipe syntax: {{placeholder\|transform}}

TransformSyntaxInputOutput
Default{{urls}}["a", "b"]a\nb (newline-joined)
Bullets{{urls|bullets}}["a", "b"]- a\n- b
Numbered{{urls|numbered}}["a", "b"]1. a\n2. b
Join{{urls|join:, }}["a", "b"]a, b
Length{{urls|length}}["a", "b"]2
First{{urls|first}}["a", "b"]a
Last{{urls|last}}["a", "b"]b
Field{{users|field:name}}[{name: "John"}, {name: "Jane"}]John\nJane

Examples

Simple variable substitution:

Prompt template: "Hello {{name}}, welcome to {{company}}!"
Placeholders: { "name": "Alice", "company": "Acme Corp" }
Result: "Hello Alice, welcome to Acme Corp!"

Array with bullets:

Prompt template: "Sources:\n{{urls|bullets}}"
Placeholders: { "urls": ["https://example.com", "https://test.com"] }
Result: "Sources:\n- https://example.com\n- https://test.com"

Nested object access:

Prompt template: "Author: {{metadata.author}}, Published: {{metadata.date}}"
Placeholders: { "metadata": { "author": "John Doe", "date": "2026-01-15" } }
Result: "Author: John Doe, Published: 2026-01-15"

Object array with field extraction:

Prompt template: "Claims to verify:\n{{claims|field:text|numbered}}"
Placeholders: { "claims": [{ "text": "Fact 1" }, { "text": "Fact 2" }] }
Result: "Claims to verify:\n1. Fact 1\n2. Fact 2"

Webhooks

Configure webhooks for AI events.

Register Webhook

POST /ai/v1/webhooks

Request Body:

{
"data": {
"type": "webhooks",
"attributes": {
"url": "https://your-app.com/webhooks/ai",
"events": [
"moderation.flagged",
"classifier.trained",
"batch.completed"
],
"secret": "your-webhook-secret"
}
}
}

Webhook Events

EventDescription
moderation.flaggedContent was flagged by moderation
classifier.trainedCustom classifier finished training
batch.completedBatch processing job completed

Error Handling

Error Response Format

{
"errors": [
{
"status": "400",
"code": "invalid_image_format",
"title": "Invalid Image Format",
"detail": "The image format 'bmp' is not supported. Supported formats: jpg, png, gif, webp.",
"source": {
"parameter": "image_url"
}
}
]
}

Common Error Codes

CodeStatusDescription
text_too_long400Input text exceeds maximum length
invalid_image_format400Unsupported image format
invalid_language400Language code not supported
classifier_not_found404Custom classifier does not exist
model_unavailable503AI model temporarily unavailable
rate_limit_exceeded429Too many requests

SDK Examples

React Sentiment Component

import { useState } from 'react';
import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { ai: 'https://jarvis.api.us.23blocks.com' },
appId: 'your-app-id',
});

function SentimentAnalyzer() {
const [text, setText] = useState('');
const [sentiment, setSentiment] = useState(null);
const [loading, setLoading] = useState(false);

const analyzeSentiment = async () => {
if (!text.trim()) return;

setLoading(true);
try {
const result = await client.ai.analyzeSentiment({ text });
setSentiment(result);
} finally {
setLoading(false);
}
};

const getSentimentColor = (label) => {
switch (label) {
case 'positive': return 'text-green-500';
case 'negative': return 'text-red-500';
default: return 'text-gray-500';
}
};

return (
<div className="sentiment-analyzer">
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Enter text to analyze..."
rows={4}
/>
<button onClick={analyzeSentiment} disabled={loading}>
{loading ? 'Analyzing...' : 'Analyze Sentiment'}
</button>

{sentiment && (
<div className="result">
<p className={getSentimentColor(sentiment.label)}>
{sentiment.label.toUpperCase()} ({(sentiment.score * 100).toFixed(1)}%)
</p>
<div className="confidence-bar">
<div
style={{ width: `${sentiment.confidence * 100}%` }}
className="confidence-fill"
/>
</div>
</div>
)}
</div>
);
}

Content Moderation Hook

import { useState, useCallback } from 'react';
import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { ai: 'https://jarvis.api.us.23blocks.com' },
appId: 'your-app-id',
});

function useContentModeration() {
const [isChecking, setIsChecking] = useState(false);

const moderateContent = useCallback(async (content: string) => {
setIsChecking(true);
try {
const result = await client.ai.moderate({
text: content,
categories: ['hate', 'violence', 'sexual', 'spam']
});

return {
isApproved: !result.flagged,
flags: Object.entries(result.categories)
.filter(([_, data]) => data.flagged)
.map(([category]) => category),
action: result.action
};
} finally {
setIsChecking(false);
}
}, []);

return { moderateContent, isChecking };
}

// Usage in a form
function CommentForm() {
const { moderateContent, isChecking } = useContentModeration();
const [comment, setComment] = useState('');
const [error, setError] = useState('');

const handleSubmit = async (e) => {
e.preventDefault();
setError('');

const moderation = await moderateContent(comment);
if (!moderation.isApproved) {
setError(`Comment flagged for: ${moderation.flags.join(', ')}`);
return;
}

// Submit the comment...
};

return (
<form onSubmit={handleSubmit}>
<textarea
value={comment}
onChange={(e) => setComment(e.target.value)}
placeholder="Write a comment..."
/>
{error && <p className="error">{error}</p>}
<button type="submit" disabled={isChecking}>
{isChecking ? 'Checking...' : 'Post Comment'}
</button>
</form>
);
}

Rate Limits

PlanRequests/minuteText chars/requestImages/minute
Free605,00010
Starter30025,00060
Growth1,000100,000200
EnterpriseCustomCustomCustom

Best Practices

Text Analysis

  1. Batch when possible - Send multiple texts in a single request
  2. Specify language - Improves accuracy when you know the language
  3. Clean input - Remove irrelevant formatting or markup

Image Analysis

  1. Optimize images - Resize large images before sending
  2. Use URLs - Prefer image URLs over base64 for large images
  3. Set confidence thresholds - Filter low-confidence results

Recommendations

  1. Track events - The more user events, the better recommendations
  2. Use context - Provide page/section context for relevance
  3. Apply filters - Filter by availability, category, etc.

Content Moderation

  1. Moderate early - Check content before displaying to others
  2. Use appropriate categories - Only check relevant categories
  3. Handle flags gracefully - Provide helpful feedback to users