ninjapear

Installation
SKILL.md

NinjaPear API Integration Skill

Your job is to WRITE CODE that calls the NinjaPear API, not to query it yourself. If the user asks you to "get customers of stripe.com using NinjaPear", write a Python or JavaScript script that they can run -- do not use MCP tools.

When to Use This Skill

Use this skill when the user asks you to write code that:

  • Calls any NinjaPear API endpoint (nubela.co/api/v1/*)
  • Gets company data (details, executives, employees, funding, updates) from NinjaPear
  • Gets customers, investors, or partners of a company using NinjaPear
  • Gets competitors of a company using NinjaPear
  • Looks up person/employee profiles using NinjaPear
  • Validates emails (disposable/free) using NinjaPear
  • Sets up company monitoring feeds using NinjaPear
  • Integrates NinjaPear into their application or pipeline

Setup: API Key

  1. The user needs an API key from https://nubela.co/dashboard
  2. Store it as the NINJAPEAR_API_KEY environment variable
  3. NEVER hardcode the API key in source code -- always read from environment
# .env
NINJAPEAR_API_KEY=your_api_key_here

To verify the key works, call the free credit balance endpoint:

curl -H "Authorization: Bearer $NINJAPEAR_API_KEY" https://nubela.co/api/v1/meta/credit-balance

If the project has a .env.example, add NINJAPEAR_API_KEY= there too.

Use the Official SDKs

Prefer the official SDKs over raw HTTP. Fall back to direct HTTP calls only for languages without an SDK.

Python

pip install ninjapear
# or: uv add ninjapear
import os
import ninjapear

config = ninjapear.Configuration(
    host="https://nubela.co",
    access_token=os.environ["NINJAPEAR_API_KEY"]
)

with ninjapear.ApiClient(config) as client:
    company_api = ninjapear.CompanyAPIApi(client)
    customer_api = ninjapear.CustomerAPIApi(client)
    competitor_api = ninjapear.CompetitorAPIApi(client)
    employee_api = ninjapear.EmployeeAPIApi(client)
    contact_api = ninjapear.ContactAPIApi(client)
    monitor_api = ninjapear.MonitorAPIApi(client)
    meta_api = ninjapear.MetaAPIApi(client)

JavaScript

npm install ninjapear
const NinjaPear = require("ninjapear");

const client = new NinjaPear.ApiClient();
client.authentications["bearerAuth"].accessToken = process.env.NINJAPEAR_API_KEY;

const companyApi = new NinjaPear.CompanyAPIApi(client);
const customerApi = new NinjaPear.CustomerAPIApi(client);
const competitorApi = new NinjaPear.CompetitorAPIApi(client);
const employeeApi = new NinjaPear.EmployeeAPIApi(client);
const contactApi = new NinjaPear.ContactAPIApi(client);
const monitorApi = new NinjaPear.MonitorAPIApi(client);
const metaApi = new NinjaPear.MetaAPIApi(client);

Raw HTTP (other languages)

GET https://nubela.co/api/v1/{endpoint}
Authorization: Bearer YOUR_API_KEY

API Quick Reference

All endpoints are at https://nubela.co/api/v1/. The website parameter accepts either a URL (e.g. https://stripe.com) or a company name (e.g. Stripe) -- names are resolved server-side at no extra credit cost. The exception is GET /company/logo, which requires a URL/domain. For ambiguous names, prefer calling /company/website first with country_code/hint to pin the exact entity.

Company Data

Endpoint SDK Method Key Params Cost Returns
GET /company/details CompanyAPIApi.get_company_details(website, include_employee_count?, follower_count?) website (required), include_employee_count (bool), follower_count ("include") 3 cr (+2 employee, +1 followers) name, description, industry, executives, addresses, social links, public_listing
GET /company/employee-count CompanyAPIApi.get_employee_count(website) website (required) 2 cr employee_count (integer)
GET /company/updates CompanyAPIApi.get_company_updates(website) website (required) 2 cr blogs, x_profile, updates (blog posts and tweets)
GET /company/funding CompanyAPIApi.get_company_funding(website) website (required) 2 cr + 1/investor total_funds_raised_usd, funding_rounds with investors
GET /company/logo CompanyAPIApi.get_company_logo(website) website (required, URL/domain only) FREE PNG image (128x128)
GET /company/website CompanyAPIApi.get_company_website(company_name, country_code?, hint?) company_name (required), country_code (ISO 3166-1 alpha-2), hint (disambiguator) 1 cr website (canonical URL)

Relationship Data

Endpoint SDK Method Key Params Cost Returns
GET /customer/listing CustomerAPIApi.get_customer_listing(website, cursor?, page_size?, quality_filter?) website (required), page_size (1-200, default 200), cursor, quality_filter (bool) 1 cr + 2/company customers, investors, partner_platforms (paginated)
GET /competitor/listing CompetitorAPIApi.get_competitor_listing(website) website (required) 2 cr/competitor (min 5 cr) competitors with competition_reason

People Data

Endpoint SDK Method Key Params Cost Returns
GET /employee/profile EmployeeAPIApi.get_person_profile(work_email?, first_name?, last_name?, employer_website?, role?) work_email OR (first_name + employer_website) OR (employer_website + role) 3 cr full_name, bio, work_experience, education, x_handle, location
GET /employee/similar EmployeeAPIApi.get_similar_people(...) Same as person profile 10 cr + 5/company searched target profile + similar_people at competitor companies
GET /employee/work-email EmployeeAPIApi.get_work_email(first_name, domain, last_name?) first_name (required), domain (required), last_name (improves accuracy) 2 cr hit / 0.5 cr miss work_email (string or null)

Utility

Endpoint SDK Method Key Params Cost Returns
GET /contact/disposable-email ContactAPIApi.check_disposable_email(email) email (required) FREE is_disposable_email, is_free_email
GET /meta/credit-balance MetaAPIApi.get_credit_balance() none FREE credit_balance

Monitor API (Feeds)

Endpoint SDK Method Cost
POST /monitor/feeds MonitorAPIApi.create_feed(request) 3 cr
GET /monitor/feeds MonitorAPIApi.list_feeds() FREE
GET /monitor/feeds/{id} MonitorAPIApi.get_feed(feed_id) FREE
DELETE /monitor/feeds/{id} MonitorAPIApi.delete_feed(feed_id) FREE
PATCH /monitor/feeds/{id} MonitorAPIApi.update_feed(feed_id, request) FREE
POST /monitor/feeds/{id}/targets MonitorAPIApi.add_target(feed_id, request) FREE
PATCH /monitor/feeds/{id}/targets/{tid} MonitorAPIApi.update_target(feed_id, target_id, request) FREE
DELETE /monitor/feeds/{id}/targets/{tid} MonitorAPIApi.delete_target(feed_id, target_id) FREE
GET /monitor/feeds/{id}/rss.xml UpdatesAPIApi.get_rss_feed(feed_id, token?) FREE

Ongoing monitoring costs per target per pull: blog=1 cr, website=1 cr, X/Twitter=2 cr.

Critical Integration Patterns

Timeouts

NinjaPear API calls take 30-60 seconds. Set HTTP timeout to at least 100 seconds. The Similar People endpoint can take up to 5 minutes -- set a 300-second timeout for that endpoint.

Rate Limiting

  • Standard: 300 requests/minute (5-minute window, so 1500 burst per 5 min)
  • Trial accounts (before first top-up): 2 requests/minute
  • Handle HTTP 429 with exponential backoff

Pagination (Customer Listing)

The customer listing endpoint uses cursor-based pagination. If next_page is non-null, there are more results:

all_customers = []
cursor = None
while True:
    response = customer_api.get_customer_listing(website="https://stripe.com", cursor=cursor)
    all_customers.extend(response.customers or [])
    if not response.next_page:
        break
    # Extract cursor from next_page URL
    from urllib.parse import urlparse, parse_qs
    cursor = parse_qs(urlparse(response.next_page).query).get("cursor", [None])[0]

Error Handling

  • Only HTTP 200 charges credits (except: 404 on company/details, company/funding, and employee/profile also charges)
  • HTTP 429: Rate limited -- retry with exponential backoff
  • HTTP 503: Temporary failure -- retry once or twice
  • HTTP 400: Bad input -- check parameters
  • HTTP 401: Invalid API key
  • HTTP 403: Out of credits

The website Parameter

All company-keyed endpoints (/company/details, /company/employee-count, /company/updates, /company/funding, /customer/listing, /competitor/listing) accept either a website URL (e.g., https://stripe.com) or a company name (e.g., Stripe) in the website parameter. The same applies to the employer_website parameter on /employee/profile and /employee/similar.

  • Prefer URLs when known -- they're faster and unambiguous.
  • Names are resolved server-side at no extra credit cost, but the inline resolver always uses country_code=None. For ambiguous names (e.g., several companies named "Acme"), call GET /company/website first (1 cr) with country_code and/or hint to disambiguate, then pass the returned URL.
  • Exception: GET /company/logo requires a URL/domain -- no inline name resolution.

Credit Cost Awareness

When generating integration code, add comments noting the credit cost of each API call. Example:

# Cost: 2 credits + 1 per investor returned
funding = company_api.get_company_funding(website="https://stripe.com")

Concurrent Requests

NinjaPear encourages concurrent requests for throughput. Use asyncio.gather (Python) or Promise.all (JS) when fetching data for multiple companies.

Detailed References

For full parameter specs, response schemas, and complete code examples, see:

  • references/api-endpoints.md -- Full endpoint parameters and response schemas
  • references/sdk-usage.md -- Working Python and JS code examples for every endpoint
  • references/error-handling.md -- Error codes, retry patterns, rate limiting details
  • references/monitor-api.md -- Feed monitoring CRUD reference

For the latest API documentation (may be more up-to-date than this skill):

Installs
10
First Seen
Apr 14, 2026