praniSheba API

API reference

Four calls: enroll, identify, delete and list cows. Pick a language on the right, or try a call in the sandbox without leaving the page.

Overview

Four calls, all on https://api.central.pranisheba.com.bd. Authenticate every call with your key in the X-API-Key header. Photos are limited to 20 MB, are passed to the model and are never stored by this platform.

Responses are passed through as returned by the identification model, with the same JSON and HTTP status. The platform adds headers and, for errors it raises itself, the envelope described on the errors page. The body of a live response is the model's own.

Endpoints
CallParametersToken
POST /enrollmultipart form: cow_id, file1 enroll token when the cow is enrolled
POST /identifymultipart form: file, optional top_k1 search token when the search runs
DELETE /delete/{cow_id}nonefree
GET /cowsquery: optional limit, offsetfree

Enroll a cow

POST/enroll

Register a cow with a photo of its muzzle so it can be found later.

Cost: 1 enroll token when the cow is enrolled. Any error is free.

Parameters

cow_id string form required
Your id for the cow. Must not be blank, . or ...
file file form required
The muzzle photo, up to 20 MB.

Responses

A 200 means the call worked. Check is_success and the HTTP status, and read X-Request-Id when you contact support.

Enroll a cow: errors
StatusWhen
400file is missing or cow_id is missing or invalid.
402No enroll tokens left.
413The photo is over 20 MB.
429Rate or concurrency limit reached.
502The model could not be reached. Nothing is charged.

Request

cURL

curl -X POST https://api.central.pranisheba.com.bd/enroll \
  -H "X-API-Key: YOUR_API_KEY" \
  -F cow_id=BD-0001 \
  -F file=@muzzle.jpg

Python

import requests

BASE_URL = "https://api.central.pranisheba.com.bd"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

with open("muzzle.jpg", "rb") as photo:
    response = requests.post(
        f"{BASE_URL}/enroll",
        headers=HEADERS,
        data={"cow_id": "BD-0001"},
        files={"file": ("muzzle.jpg", photo, "image/jpeg")},
        timeout=(10, 180),
    )
print(response.status_code, response.headers.get("X-Tokens-Remaining"))
print(response.text)

JavaScript

import { readFile } from "node:fs/promises";

const BASE_URL = "https://api.central.pranisheba.com.bd";
const HEADERS = { "X-API-Key": "YOUR_API_KEY" };

const form = new FormData();
form.append("cow_id", "BD-0001");
form.append("file", new Blob([await readFile("muzzle.jpg")], { type: "image/jpeg" }), "muzzle.jpg");

const response = await fetch(`${BASE_URL}/enroll`, { method: "POST", headers: HEADERS, body: form });
console.log(response.status, response.headers.get("X-Tokens-Remaining"));
console.log(await response.json());

Sample response

What the sandbox returns. A live 200 comes from the identification model.

200 OK

{
  "is_success": true,
  "message": "Cow enrolled.",
  "data": {
    "cow_id": "BD-0001"
  }
}

400

{
  "is_success": false,
  "message": "file is required.",
  "data": null
}

402

{
  "is_success": false,
  "message": "No enroll tokens left. Buy more to continue.",
  "data": null
}

429

{
  "is_success": false,
  "message": "Rate limit exceeded. Try again later.",
  "data": null
}

Identify a cow

POST/identify

Find which enrolled cow a new muzzle photo belongs to.

Cost: 1 search token when the search runs, whether or not a match is found. Any error is free.

Parameters

file file form required
The muzzle photo, up to 20 MB.
top_k integer form optional
How many candidates to return, from 1 to 5. Default 1.

Responses

A 200 means the call worked. Check is_success and the HTTP status, and read X-Request-Id when you contact support.

Identify a cow: errors
StatusWhen
400file is missing, or top_k is not a whole number from 1 to 5.
402No search tokens left.
413The photo is over 20 MB.
429Rate or concurrency limit reached.
502The model could not be reached. Nothing is charged.

Request

cURL

curl -X POST https://api.central.pranisheba.com.bd/identify \
  -H "X-API-Key: YOUR_API_KEY" \
  -F top_k=3 \
  -F file=@muzzle.jpg

Python

import requests

BASE_URL = "https://api.central.pranisheba.com.bd"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

with open("muzzle.jpg", "rb") as photo:
    response = requests.post(
        f"{BASE_URL}/identify",
        headers=HEADERS,
        data={"top_k": 3},
        files={"file": ("muzzle.jpg", photo, "image/jpeg")},
        timeout=(10, 180),
    )
print(response.status_code, response.headers.get("X-Tokens-Remaining"))
print(response.text)

JavaScript

import { readFile } from "node:fs/promises";

const BASE_URL = "https://api.central.pranisheba.com.bd";
const HEADERS = { "X-API-Key": "YOUR_API_KEY" };

const form = new FormData();
form.append("top_k", "3");
form.append("file", new Blob([await readFile("muzzle.jpg")], { type: "image/jpeg" }), "muzzle.jpg");

const response = await fetch(`${BASE_URL}/identify`, { method: "POST", headers: HEADERS, body: form });
console.log(response.status, response.headers.get("X-Tokens-Remaining"));
console.log(await response.json());

Sample response

What the sandbox returns. A live 200 comes from the identification model.

200 OK

{
  "is_success": true,
  "message": "Search complete.",
  "data": {
    "matches": [
      {
        "cow_id": "BD-0001",
        "score": 0.97
      },
      {
        "cow_id": "BD-0002",
        "score": 0.91
      },
      {
        "cow_id": "BD-0003",
        "score": 0.84
      }
    ]
  }
}

400

{
  "is_success": false,
  "message": "top_k must be an integer between 1 and 5.",
  "data": null
}

402

{
  "is_success": false,
  "message": "No search tokens left. Buy more to continue.",
  "data": null
}

429

{
  "is_success": false,
  "message": "Rate limit exceeded. Try again later.",
  "data": null
}

Delete a cow

DELETE/delete/{cow_id}

Remove a cow you enrolled.

Cost: Free.

Parameters

cow_id string path required
The id you enrolled the cow with. Must not be blank, . or ...

Responses

A 200 means the call worked. Check is_success and the HTTP status, and read X-Request-Id when you contact support.

Delete a cow: errors
StatusWhen
400cow_id is blank, . or ...
429Rate or concurrency limit reached.
502The model could not be reached.

Request

cURL

curl -X DELETE https://api.central.pranisheba.com.bd/delete/BD-0001 \
  -H "X-API-Key: YOUR_API_KEY"

Python

import requests

BASE_URL = "https://api.central.pranisheba.com.bd"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

response = requests.delete(f"{BASE_URL}/delete/BD-0001", headers=HEADERS, timeout=(10, 180))
print(response.status_code, response.text)

JavaScript

import { readFile } from "node:fs/promises";

const BASE_URL = "https://api.central.pranisheba.com.bd";
const HEADERS = { "X-API-Key": "YOUR_API_KEY" };

const response = await fetch(`${BASE_URL}/delete/BD-0001`, { method: "DELETE", headers: HEADERS });
console.log(response.status, await response.json());

Sample response

What the sandbox returns. A live 200 comes from the identification model.

200 OK

{
  "is_success": true,
  "message": "Cow deleted.",
  "data": {
    "cow_id": "BD-0001"
  }
}

400

{
  "is_success": false,
  "message": "cow_id must not be blank, '.' or '..'.",
  "data": null
}

429

{
  "is_success": false,
  "message": "Rate limit exceeded. Try again later.",
  "data": null
}

List your cows

GET/cows

Page through the cows enrolled in your account.

Cost: Free.

Parameters

limit integer query optional
How many cows to return, from 0 to 1000.
offset integer query optional
How many cows to skip, 0 or more. Default 0.

Responses

A 200 means the call worked. Check is_success and the HTTP status, and read X-Request-Id when you contact support.

List your cows: errors
StatusWhen
400limit or offset is not a whole number in range.
429Rate or concurrency limit reached.
502The model could not be reached.

Request

cURL

curl "https://api.central.pranisheba.com.bd/cows?limit=100&offset=0" \
  -H "X-API-Key: YOUR_API_KEY"

Python

import requests

BASE_URL = "https://api.central.pranisheba.com.bd"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

response = requests.get(
    f"{BASE_URL}/cows",
    headers=HEADERS,
    params={"limit": 100, "offset": 0},
    timeout=(10, 180),
)
print(response.status_code, response.text)

JavaScript

import { readFile } from "node:fs/promises";

const BASE_URL = "https://api.central.pranisheba.com.bd";
const HEADERS = { "X-API-Key": "YOUR_API_KEY" };

const response = await fetch(`${BASE_URL}/cows?limit=100&offset=0`, { headers: HEADERS });
console.log(response.status, await response.json());

Sample response

What the sandbox returns. A live 200 comes from the identification model.

200 OK

{
  "is_success": true,
  "message": "Cows listed.",
  "data": {
    "cows": [
      {
        "cow_id": "BD-0001"
      },
      {
        "cow_id": "BD-0002"
      },
      {
        "cow_id": "BD-0003"
      }
    ],
    "total": 3,
    "limit": 100,
    "offset": 0
  }
}

400

{
  "is_success": false,
  "message": "limit must be an integer between 0 and 1000.",
  "data": null
}

429

{
  "is_success": false,
  "message": "Rate limit exceeded. Try again later.",
  "data": null
}