Tareef
Operational v1.0 REST · JSON

API reference

Build with the face recognition API

A focused REST surface. Multipart in, JSON out. The same verb every endpoint speaks.

marketing.docs.sections
All systems operational v1.0 REST · JSON

API reference

The face recognition API is organized around REST. It accepts multipart form bodies for image uploads, returns JSON, and uses standard HTTP response codes. All requests must be made over HTTPS in production.

Base URL
https://tareef.g4t.io/api/v1
Auth
Bearer token
Content type
multipart/form-data

01 · Get started

Quickstart

Make your first verified call in under two minutes.

  1. Sign up (free) and create an API key.
  2. Enroll one or more people with reference photos.
  3. Verify a new photo against your library — done.

Every code sample on this page is runnable as written. The shell snippet below is the same shape every other endpoint uses.

POST /api/v1/verify
curl -X POST https://tareef.g4t.io/api/v1/verify \
  -H "Authorization: Bearer frs_live_XXXXXX" \
  -F "file=@photo.jpg"
const form = new FormData();
form.append('file', file);

const res = await fetch('https://tareef.g4t.io/api/v1/verify', {
  method: 'POST',
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
  body: form,
});
$res = Http::withToken('frs_live_XXXXXX')
    ->attach('file', file_get_contents($path), 'photo.jpg')
    ->post('https://tareef.g4t.io/api/v1/verify');
import requests

with open('photo.jpg','rb') as f:
    res = requests.post(
        'https://tareef.g4t.io/api/v1/verify',
        headers={'Authorization': 'Bearer frs_live_XXXXXX'},
        files={'file': f},
    )

Official SDK · Laravel

Laravel SDK

Skip the raw HTTP plumbing. The first-party tareef/laravel package wraps every endpoint in a typed facade with typed exceptions and streamed multipart uploads.

The package is the recommended way to talk to Tareef from any Laravel app — PHP 8.2+, Laravel 10 / 11 / 12 / 13. Source on GitHub.

Install

composer require tareef/laravel

Configure

Set your key in .env — the service provider auto-discovers the rest.

TAREEF_API_KEY=frs_live_XXXXXX

Optional config keys: TAREEF_BASE_URL (defaults to https://tareef.g4t.io/api/v1), TAREEF_TIMEOUT, TAREEF_RETRIES, TAREEF_THROW_ON_QUOTA.

Image inputs

Any method that takes an image accepts:

  • Illuminate\Http\UploadedFile — straight from $request->file()
  • SplFileInfo / Illuminate\Http\File — pre-moved files on disk
  • string — an absolute path

Uploads are streamed, never buffered into memory.

Typed exceptions

All errors inherit from TareefException. Catch the specific subclass when you care:

  • FaceAlreadyExistsException — duplicate face for this account
  • NoFaceDetectedException — no detectable face in the supplied image
  • QuotaExceededException — monthly verify quota hit (suppress with TAREEF_THROW_ON_QUOTA=false)
  • AuthenticationException — bad / revoked API key
  • ServiceUnavailableException — Tareef is down or unreachable
PHP use Tareef\Laravel\Facades\Tareef
composer require tareef/laravel

# then in .env:
TAREEF_API_KEY=frs_live_XXXXXX
// The SDK is Laravel-only — see the JS tab on the rest of this page
// for fetch-based examples.
use Tareef\Laravel\Facades\Tareef;
use Tareef\Laravel\Exceptions\{NoFaceDetectedException, QuotaExceededException};

// Enroll someone from an uploaded file
$person = Tareef::register(
    name:   'Jane Doe',
    images: [$request->file('photo')],
    phone:  '+15555555555',
);

// Identify a face
try {
    $result = Tareef::verify($request->file('selfie'));

    if ($result->matched) {
        return ['uuid' => $result->person->uuid, 'score' => $result->score];
    }
} catch (NoFaceDetectedException) {
    abort(422, 'No face in the photo.');
} catch (QuotaExceededException) {
    abort(429, 'Monthly verify quota hit.');
}
# The SDK is Laravel-only — install the package on Packagist:
# https://packagist.org/packages/tareef/laravel
# For Python, use the raw REST examples on the rest of this page.

02 · Security

Authentication

Bearer your API key. We also accept x-api-key for legacy clients.

All authenticated endpoints require an Authorization header with a bearer token issued from your dashboard. Each key is bound to one account; revoking it disables access immediately.

  • Format: frs_live_ followed by 32+ random characters.
  • Rotation: revoke keys you no longer use — they are shown once at creation.
  • Failures return 401 unauthorized with no further details.
GET /api/v1/people
# Pass the header on every request
Authorization: Bearer frs_live_XXXXXX
fetch('https://tareef.g4t.io/api/v1/people', {
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
})
Http::withToken('frs_live_XXXXXX')
    ->get('https://tareef.g4t.io/api/v1/people')
requests.get(
    'https://tareef.g4t.io/api/v1/people',
    headers={'Authorization': 'Bearer frs_live_XXXXXX'},
)

03 · Resources

Enroll a person

Create a new person in your library from one or more reference photos.

POST /api/v1/people multipart

Body parameters

name required string
Display name for the person.
phone optional string
Free-form identifier — phone, email, employee ID.
file one of file
A single image (jpg, png, webp), up to 8 MB.
files[] one of file[]
Multiple images. Repeat the form key once per file. More samples means higher accuracy on future verifies.

Responses

  • 200 success: true with the new uuid and images_registered.
  • 422 face_exists — the face is already enrolled for you. Existing UUID returned.
  • 422 no_face — no detectable face in any supplied image.
POST /api/v1/people
curl -X POST https://tareef.g4t.io/api/v1/people \
  -H "Authorization: Bearer frs_live_XXXXXX" \
  -F "name=Jane Doe" \
  -F "phone=+15555555555" \
  -F "file=@photo.jpg"
const form = new FormData();
form.append('name', 'Jane Doe');
form.append('phone', '+15555555555');
form.append('file', file);

await fetch('https://tareef.g4t.io/api/v1/people', {
  method: 'POST',
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
  body: form,
});
// Official SDK: composer require tareef/laravel
use Tareef\Laravel\Facades\Tareef;

$person = Tareef::register(
    name:   'Jane Doe',
    images: [$request->file('photo')],
    phone:  '+15555555555',
);
with open('photo.jpg','rb') as f:
    requests.post(
        'https://tareef.g4t.io/api/v1/people',
        headers={'Authorization': 'Bearer frs_live_XXXXXX'},
        data={'name':'Jane Doe','phone':'+15555555555'},
        files={'file': f},
    )

Resources

Add reference photos

Attach more photos to a person you’ve already enrolled.

POST /api/v1/people/{uuid}/images multipart

Same body shape as enroll — just omit name / phone. Accuracy improves with every additional sample.

Path parameters

uuid required
The person UUID returned from enroll.
POST /api/v1/people/{uuid}/images
curl -X POST https://tareef.g4t.io/api/v1/people/UUID/images \
  -H "Authorization: Bearer frs_live_XXXXXX" \
  -F "files=@a.jpg" -F "files=@b.jpg"
const form = new FormData();
[a, b].forEach(f => form.append('files', f));

await fetch('https://tareef.g4t.io/api/v1/people/UUID/images', {
  method: 'POST',
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
  body: form,
});
Http::withToken('frs_live_XXXXXX')
    ->attach('files', file_get_contents($a), 'a.jpg')
    ->attach('files', file_get_contents($b), 'b.jpg')
    ->post('https://tareef.g4t.io/api/v1/people/UUID/images');
with open('a.jpg','rb') as a, open('b.jpg','rb') as b:
    requests.post(
        'https://tareef.g4t.io/api/v1/people/UUID/images',
        headers={'Authorization': 'Bearer frs_live_XXXXXX'},
        files=[('files', a), ('files', b)],
    )

Resources

Identify a face

Search every photo of every person in your library. Counts against your monthly quota.

POST /api/v1/verify multipart billable

Body parameters

file required file
The query image. We extract one embedding and return the best matching person.

Reading the score

The response includes a cosine scorelower is closer.

  • ≤ 0.30 very confident match
  • ≤ 0.38 accepted match
  • ≤ 0.55 uncertain
  • > 0.55 different person

Responses

  • 200 match — returns uuid, name, score, samples.
  • 200 not_found — below threshold or not in your library.
  • 200 no_face — no detectable face in the query image.
  • 429 quota_exceeded — monthly verification limit reached.
POST /api/v1/verify
curl -X POST https://tareef.g4t.io/api/v1/verify \
  -H "Authorization: Bearer frs_live_XXXXXX" \
  -F "file=@photo.jpg"
const form = new FormData();
form.append('file', file);

const res = await fetch('https://tareef.g4t.io/api/v1/verify', {
  method: 'POST',
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
  body: form,
});
const data = await res.json();
// Official SDK: composer require tareef/laravel
use Tareef\Laravel\Facades\Tareef;

$result = Tareef::verify($request->file('selfie'));

if ($result->matched) {
    return [
        'uuid'  => $result->person->uuid,
        'name'  => $result->person->name,
        'score' => $result->score,
    ];
}
import requests

with open('photo.jpg', 'rb') as f:
    res = requests.post(
        'https://tareef.g4t.io/api/v1/verify',
        headers={'Authorization': 'Bearer frs_live_XXXXXX'},
        files={'file': f},
    )

print(res.json())

Resources

List people

Page through everyone you’ve enrolled, newest first.

GET /api/v1/people

Query parameters

limit optional integer
Maximum rows to return. Defaults to 100.
GET /api/v1/people
curl https://tareef.g4t.io/api/v1/people \
  -H "Authorization: Bearer frs_live_XXXXXX"
const { people } = await fetch('https://tareef.g4t.io/api/v1/people', {
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
}).then(r => r.json());
// Official SDK: composer require tareef/laravel
use Tareef\Laravel\Facades\Tareef;

$people = Tareef::list(limit: 100);
people = requests.get(
    'https://tareef.g4t.io/api/v1/people',
    headers={'Authorization': 'Bearer frs_live_XXXXXX'},
).json()['people']

Resources

Read & delete a person

Fetch a person record or remove them — and their embeddings — permanently.

Endpoints

  • GET/api/v1/people/{uuid}Returns the person record plus reference image paths.
  • DELETE/api/v1/people/{uuid}Removes embeddings and stored photos. Irreversible.
GET /api/v1/people/{uuid}
# Read
curl https://tareef.g4t.io/api/v1/people/UUID \
  -H "Authorization: Bearer frs_live_XXXXXX"

# Delete
curl -X DELETE https://tareef.g4t.io/api/v1/people/UUID \
  -H "Authorization: Bearer frs_live_XXXXXX"
// Read
const person = await fetch('https://tareef.g4t.io/api/v1/people/UUID', {
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
}).then(r => r.json());

// Delete
await fetch('https://tareef.g4t.io/api/v1/people/UUID', {
  method: 'DELETE',
  headers: { Authorization: 'Bearer frs_live_XXXXXX' },
});
$person = Http::withToken('frs_live_XXXXXX')
    ->get('https://tareef.g4t.io/api/v1/people/UUID')
    ->json();

Http::withToken('frs_live_XXXXXX')
    ->delete('https://tareef.g4t.io/api/v1/people/UUID');
person = requests.get(
    'https://tareef.g4t.io/api/v1/people/UUID',
    headers={'Authorization': 'Bearer frs_live_XXXXXX'},
).json()

requests.delete(
    'https://tareef.g4t.io/api/v1/people/UUID',
    headers={'Authorization': 'Bearer frs_live_XXXXXX'},
)

04 · Limits

Rate limits & quotas

Verifications bill against your monthly quota. Enrollment, reads, and deletes are free. Quotas reset on the 1st of every calendar month at 00:00 UTC.

Plan Price Verifications People
Free$0100 / mo50
Pro$2910,000 / mo5,000
Business$99100,000 / moUnlimited

Exceeding the quota returns 429 quota_exceeded with the current used and limit in the response body.


05 · Reference

Error codes

Every response includes a stable status string. Branch on that, not on HTTP codes alone.

Status HTTP Meaning
ok 200 Successful response.
not_found 200 / 404 No matching person; or person UUID isn’t in your library.
no_face 200 We couldn’t detect a face in the supplied image.
face_exists 422 The face is already enrolled — existing UUID returned.
invalid 422 Request body is malformed or missing required fields.
unauthorized 401 Missing or revoked API key.
quota_exceeded 429 Plan limit reached for the calendar month.
upstream_error 502 The face recognition service was unreachable.