Pangram Ruby SDK
Ruby client for the Pangram Labs API, with support for AI detection, asynchronous bulk jobs, file uploads, and plagiarism checks.
Requirements
- Ruby 3.1 or newer
- A Pangram API key
Installation
Add the gem to your application:
gem 'pangram'Then run bundle install, or install it directly:
gem install pangramClient setup
Set your API key in the environment:
export PANGRAM_API_KEY='your-api-key'require 'pangram'
client = Pangram.newYou can also pass the key directly. A constructor argument takes precedence
over PANGRAM_API_KEY.
client = Pangram.new(api_key: 'your-api-key')
# Equivalent: Pangram::Client.new(api_key: 'your-api-key')All API responses are ordinary Ruby Hash and Array values. Response keys
remain strings and match Pangram's JSON schema.
Discover models
Model access depends on the API key and current service availability. Discover selectors instead of hard-coding a model catalog:
models = client.list_models
# => ["default", "pangram-4"]Pass model: "default" to track Pangram's default, or pass another selector
returned by list_models. Omitting model is temporarily supported but emits
a deprecation warning; Pangram plans to require it after September 30, 2026.
AI detection
predict submits an asynchronous task, polls until it succeeds, and returns
the completed result:
result = client.predict(
'Text to analyze',
model: 'pangram-4',
timeout: 300,
poll_interval: 0.5
)
puts result['prediction_short']
puts result['fraction_ai']
result['windows'].each do |window|
puts "#{window['label']}: #{window['ai_assistance_score']}"
endRequest a public dashboard link either directly or with the convenience method:
result = client.predict(
'Text to analyze',
model: 'pangram-4',
public_dashboard_link: true
)
result = client.predict_with_dashboard_link(
'Text to analyze',
model: 'pangram-4'
)Polling intervals below 0.1 seconds are clamped to 0.1. timeout is a total
deadline covering task submission and polling.
Bulk jobs
Submit either a plain text list or an items list with optional customer
IDs. Do not pass both.
bulk = client.submit_bulk(
items: [
{ id: 'row-001', text: 'First text' },
{ id: 'row-002', text: 'Second text' }
],
model: 'pangram-4'
)
bulk_id = bulk['bulk_id']
status = client.wait_for_bulk(bulk_id, timeout: 3600, poll_interval: 1)
results = client.get_bulk_results(bulk_id)
results['items'].each do |item|
prediction = item['result']
puts "#{item['id']}: #{prediction['prediction_short']}" if prediction
end
results['failed_items'].each do |item|
warn "#{item['id']}: #{item['error']}"
endUse the lower-level methods to inspect a job without materializing all result pages:
client.get_bulk_status(bulk_id)
client.get_bulk_items(bulk_id, offset: 0, limit: 100)
client.get_bulk_results_page(bulk_id, offset: 0, limit: 100)get_bulk_results requests all pages and stores them in memory. For very large
jobs, process get_bulk_results_page one page at a time. The API accepts at
most 1,000 submitted item slots per results page.
File uploads
File prediction uses Pangram's default model and does not accept model.
result = client.predict_file(
'document.pdf',
public_dashboard_link: true,
timeout: 300
)
results = client.predict_files(
['first.docx', 'second.pdf'],
public_dashboard_link: true
)The SDK sends one multipart field named files for each path and closes every
opened file after the request, including when the request fails.
Plagiarism detection
result = client.check_plagiarism('Text to check')
puts result['plagiarism_detected']
puts result['percent_plagiarized']Errors
All SDK errors inherit from Pangram::Error:
| Error | Meaning |
|---|---|
Pangram::AuthenticationError |
No API key was configured |
Pangram::ValidationError |
A local argument is invalid |
Pangram::APIError |
Pangram rejected the request or a task failed |
Pangram::InvalidResponseError |
Pangram returned invalid JSON or an unexpected schema |
Pangram::NetworkError |
The HTTP connection failed or a request timed out |
Pangram::TimeoutError |
An async prediction or bulk job exceeded its total deadline |
begin
client.predict('Text', model: 'default')
rescue Pangram::TimeoutError => e
warn e.message
rescue Pangram::Error => e
warn "Pangram request failed: #{e.message}"
endTransient network failures and responses with status 408, 429, 500, 502, 503,
or 504 are retried until the total deadline while polling a prediction or bulk
job and while paginating bulk results. Other API errors are raised immediately
with the HTTP status and response body attached.
Deprecated compatibility methods
The current Python SDK still includes these methods, so Ruby provides matching compatibility helpers:
-
predict_short(text, model:)forwards to the current prediction flow. -
batch_predict(texts, model:)calls the prediction flow sequentially.
Prefer predict for one input and submit_bulk for many inputs.
Development
Extended documentation is available in docs/, including
the API reference, development guide,
and release checklist.
mise install
bundle install
make verifyThe test suite uses WebMock and never needs a live Pangram API key.