PHPackages                             inbio/inbio - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. inbio/inbio

ActiveLibrary

inbio/inbio
===========

Official PHP SDK for the in.bio URL shortener API: short links, QR codes, analytics, folders, tags and webhooks.

0.1.0(today)00MITPHPPHP &gt;=8.1

Since Jul 23Pushed todayCompare

[ Source](https://github.com/getinbio/inbio-php)[ Packagist](https://packagist.org/packages/inbio/inbio)[ Docs](https://in.bio)[ RSS](/packages/inbio-inbio/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (2)Used By (0)

inbio/inbio — official PHP SDK for INBIO (in.bio)
=================================================

[](#inbioinbio--official-php-sdk-for-inbio-inbio)

The official PHP SDK for [INBIO](https://in.bio), the premium URL shortener with click analytics and customizable QR codes. Shorten links, generate styled QR codes, read analytics, and manage folders and tags from PHP.

- **Free to start** — `Inbio::shorten()` and the [QR API](https://docs.in.bio/api/free-qr) need **no account and no API key**
- **Zero Composer dependencies** — PHP ≥ 8.1 with `ext-curl`; readonly typed models, named arguments
- **Complete** — covers the entire [INBIO REST API](https://docs.in.bio/api): links CRUD, generator pagination, bulk create, QR codes, analytics, webhook signature verification

Install
-------

[](#install)

```
composer require inbio/inbio
```

Shorten a URL in three lines
----------------------------

[](#shorten-a-url-in-three-lines)

No account, no API key:

```
$result = \Inbio\Inbio::shorten('https://example.com/some/very/long/url');
echo $result->shortUrl; // https://in.bio/abc123
```

`shorten()` returns a `ShortenResult` with `shortUrl`, `slug`, `qrUrl`, `previewUrl`, `claimUrl` and `expires`. Keyless links are anonymous and deleted after 30 days unless claimed via `claimUrl`.

Authenticated quickstart
------------------------

[](#authenticated-quickstart)

Create a token under **Settings → API tokens** (API access is a Pro/Business feature), then:

```
use Inbio\Client;

$client = new Client(token: 'YOUR_API_TOKEN');

$link = $client->links->create('https://example.com/sale', slug: 'spring-sale');
echo $link->shortUrl; // https://in.bio/spring-sale
```

Omit the token to fall back to the `INBIO_API_TOKEN` environment variable:

```
$client = new Client(); // reads INBIO_API_TOKEN
```

Links
-----

[](#links)

### List and iterate

[](#list-and-iterate)

```
// One page at a time
$page = $client->links->list(status: 'active', perPage: 50);
foreach ($page->data as $link) {
    echo "{$link->slug}: {$link->totalClicks} clicks\n";
}
echo $page->total;       // total matching links
echo $page->currentPage; // current page number
var_dump($page->hasNext); // is there a next page?

// Or let the SDK paginate for you — iterate() is a Generator
foreach ($client->links->iterate(tag: 'marketing') as $link) {
    echo $link->shortUrl, "\n";
}
```

`listAll()` is an alias of `iterate()`. Filters: `search`, `folderId`, `tag`, `status`, `perPage`.

### Create with options

[](#create-with-options)

```
$link = $client->links->create(
    'https://example.com/sale',
    slug: 'spring-sale',          // omit for a random slug
    title: 'Spring sale',
    redirectType: 301,            // 301, 302 (default) or 307
    folderId: 3,
    tags: ['marketing', 'q3'],    // created on the fly
    expiresAt: '2026-09-01T00:00:00+00:00', // Pro+
    fallbackUrl: 'https://example.com',     // shown after expiry; Pro+
    clickLimit: 10000,            // Pro+
    password: 'hunter2',          // Pro+
    utm: ['source' => 'newsletter', 'campaign' => 'spring'],
);
```

### Update, enable, disable, delete

[](#update-enable-disable-delete)

```
$client->links->update(42, title: 'New title', tags: ['sale']);
// or with an array: $client->links->update(42, ['title' => 'New title']);

$client->links->disable(42); // active -> disabled
$client->links->enable(42);  // disabled -> active
$client->links->delete(42);  // soft-delete, stops redirecting
```

Enable/disable only toggle between `active` and `disabled`; any other status throws a `StateConflictException` carrying the `current` status.

### Bulk create (Business)

[](#bulk-create-business)

```
$result = $client->links->bulkCreate([
    ['destination_url' => 'https://example.com/1', 'slug' => 'promo-1'],
    ['destination_url' => 'https://example.com/2', 'slug' => 'promo-2'],
]);

foreach ($result->created as $link) { /* Link objects */ }
foreach ($result->failed as $row) {
    echo "row {$row['index']} failed: {$row['error']}\n";
}
```

Rows fail independently — up to 100 per call.

### QR code straight to a file

[](#qr-code-straight-to-a-file)

```
file_put_contents('spring-sale.png', $client->links->qr(42, size: 512));
file_put_contents('spring-sale.svg', $client->links->qr(42, format: 'svg'));
```

The QR encodes the short URL, so editing the destination never invalidates printed codes.

### Analytics

[](#analytics)

```
$stats = $client->links->analytics(42, from: '2026-06-01', to: '2026-07-01');

echo $stats->totals['clicks'];   // 1240
echo $stats->totals['uniques'];  // 981
foreach ($stats->series as $day) {
    echo "{$day['date']}: {$day['clicks']}\n";
}
// Also: $stats->countries, ->devices, ->browsers, ->referrers (top 10 by clicks)
```

Folders and tags
----------------

[](#folders-and-tags)

```
foreach ($client->folders->list() as $folder) {
    echo "{$folder->name} ({$folder->linksCount} links)\n";
}
foreach ($client->tags->list() as $tag) {
    echo "{$tag->name}\n";
}
```

Account usage
-------------

[](#account-usage)

```
$usage = $client->account->usage();
echo $usage->plan;                          // "pro"
echo $usage->usage['links_created'];        // 120
echo $usage->limits['links_per_month'];     // 2000
```

Webhook verification
--------------------

[](#webhook-verification)

in.bio signs every webhook delivery with `X-Inbio-Signature: t=,v1=`. Verify with the raw request body — do not decode and re-encode it first:

```
use Inbio\Exception\SignatureVerificationException;
use Inbio\Resources\Webhooks;

// In your HTTP handler (plain PHP shown; the same works in any framework):
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_INBIO_SIGNATURE'] ?? '';

try {
    $event = (new Webhooks())->verify($payload, $signature, $endpointSecret);
    // or: $client->webhooks->verify(...)
} catch (SignatureVerificationException $e) {
    http_response_code(400);
    exit;
}

match ($event->event) {
    'link.created' => handleCreated($event->data),
    'link.click_limit_reached' => notifyTeam($event->data),
    default => null,
};

http_response_code(200);
```

Verification uses `hash_hmac('sha256', ...)` with a constant-time comparison and rejects timestamps older than 5 minutes (configurable via the `tolerance` parameter) to prevent replay attacks. `constructEvent()` is an alias of `verify()`.

Error handling
--------------

[](#error-handling)

All exceptions extend `Inbio\Exception\InbioException`, which exposes `status`, `errorType` and `responseBody`:

```
use Inbio\Exception\RateLimitException;
use Inbio\Exception\ValidationException;

try {
    $client->links->create('https://example.com', slug: 'taken');
} catch (ValidationException $e) {
    print_r($e->errors); // ['slug' => ['This slug is already taken.']]
} catch (RateLimitException $e) {
    sleep($e->retryAfter ?? 60);
}
```

Exception (in `Inbio\Exception`)HTTPExtra fields`AuthenticationException`401`AccessException`403`errorType` = `plan`/`scope`/`account`, `required` scope`NotFoundException`404`StateConflictException`409`current` status`ValidationException`422`errors` map (field =&gt; messages)`EntitlementException`422 (`error.type=entitlement`)plan feature/limit`RateLimitException`429`retryAfter` seconds`ServerException`5xx`SignatureVerificationException`—webhook verification failureRetries and timeouts
--------------------

[](#retries-and-timeouts)

```
$client = new Client(
    token: 'YOUR_API_TOKEN',
    baseUrl: 'https://in.bio', // default
    timeout: 30.0,             // seconds, default 30
    maxRetries: 2,             // default 2
);
```

The client retries only idempotent `GET` requests (on network errors and 5xx) and `429` responses that carry a `Retry-After` header, with exponential backoff capped at 10 seconds. Non-idempotent requests are never retried automatically.

Environment-variable auth
-------------------------

[](#environment-variable-auth)

Set `INBIO_API_TOKEN` and construct the client without arguments — handy for CI and twelve-factor apps:

```
export INBIO_API_TOKEN=inbio_pat_...
```

```
$client = new \Inbio\Client();
```

Docs
----

[](#docs)

Full API reference:

About INBIO
-----------

[](#about-inbio)

[INBIO](https://in.bio) (`in.bio`) is a URL shortener and link-management platform: short links with custom slugs, real-time click analytics (countries, devices, browsers, referrers — bots filtered out), a QR code studio with dot styles, marker shapes and colors, folders, tags, UTM tools, and a REST API with webhooks. Free plan included.

- Website:
- Documentation:
- Free shorten API (no key):
- Free QR code API (no key):
- MCP server for AI agents:
- All SDKs (JavaScript, Python, PHP, Ruby, Go):

License
-------

[](#license)

MIT © [InBio, Inc.](https://in.bio)

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1533426?v=4)[Instituto Nacional de Biodiversidad, Costa Rica](/maintainers/inbio)[@INBio](https://github.com/INBio)

---

Top Contributors

[![www-in-bio](https://avatars.githubusercontent.com/u/308400026?v=4)](https://github.com/www-in-bio "www-in-bio (1 commits)")

---

Tags

analyticsinbioqr-codesdkshort-linksurl-shorteneranalyticsurl shortenerqr codesshort-linksin.bio

### Embed Badge

![Health badge](/badges/inbio-inbio/health.svg)

```
[![Health](https://phpackages.com/badges/inbio-inbio/health.svg)](https://phpackages.com/packages/inbio-inbio)
```

###  Alternatives

[spatie/laravel-analytics

A Laravel package to retrieve Google Analytics data.

3.3k6.1M68](/packages/spatie-laravel-analytics)[segmentio/analytics-php

Segment Analytics PHP Library

26622.7M32](/packages/segmentio-analytics-php)[matomo/matomo-php-tracker

PHP Client for Matomo Analytics Tracking API

2213.7M42](/packages/matomo-matomo-php-tracker)[zumba/amplitude-php

PHP SDK for Amplitude

4110.3M5](/packages/zumba-amplitude-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
