PHPackages                             touchestate/php-sdk - 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. [HTTP &amp; Networking](/categories/http)
4. /
5. touchestate/php-sdk

ActiveLibrary[HTTP &amp; Networking](/categories/http)

touchestate/php-sdk
===================

Official PHP SDK for TouchEstate API - works with Laravel and standalone PHP

v1.0.0(4mo ago)02MITPHPPHP ^8.1

Since Feb 18Pushed 4mo agoCompare

[ Source](https://github.com/innovayse/touchestate-php-sdk)[ Packagist](https://packagist.org/packages/touchestate/php-sdk)[ Docs](https://touchestate.am)[ RSS](/packages/touchestate-php-sdk/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (4)Versions (2)Used By (0)

TouchEstate PHP SDK
===================

[](#touchestate-php-sdk)

Official PHP SDK for the TouchEstate API with TE-SigV4 authentication.

[![PHP Version](https://camo.githubusercontent.com/cc9cdea9aa96b40a822425e981b0a030e3371202973c7d57b74e8e99834f81dc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e312d626c7565)](https://php.net)[![Laravel](https://camo.githubusercontent.com/3020a5644b41b0a6e42c716ae0486d76e1af9fdfb5ccbce77edf26d8c4e0554e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d25354531302e3025323025374325323025354531312e302d726564)](https://laravel.com)[![Tests](https://camo.githubusercontent.com/210d4aa043a6823f18d79933282de5c673dde3e64c96d3e2ed03171f8b548fac/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d353725323070617373696e672d73756363657373)](https://phpunit.de)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

About
-----

[](#about)

TouchEstate SDK is a PHP library that provides seamless integration with the TouchEstate CRM API. It handles all the complexity of cryptographic request signing, authentication, and API communication, allowing you to focus on building your real estate application.

### Key Features

[](#key-features)

- ✅ **TE-SigV4 Authentication** - Cryptographic request signing using HMAC-SHA256 for maximum security
- ✅ **Laravel Integration** - First-class support with service provider, facade, and dependency injection
- ✅ **Standalone Usage** - Works with any PHP project, not just Laravel
- ✅ **Type-Safe** - Full PHP 8.1+ type hints and strict types for better IDE support
- ✅ **Clean API** - Stripe-inspired fluent interface for intuitive usage
- ✅ **Comprehensive Error Handling** - Specific exceptions for different error scenarios
- ✅ **Retry Logic Ready** - Built-in support for retry patterns and circuit breakers
- ✅ **Production Ready** - Thoroughly tested with 57+ unit and integration tests
- ✅ **Well Documented** - Extensive inline documentation and usage examples

What is TE-SigV4?
-----------------

[](#what-is-te-sigv4)

TE-SigV4 (TouchEstate Signature Version 4) is a cryptographic authentication protocol used by TouchEstate API to ensure maximum security for all API requests.

### Why TE-SigV4?

[](#why-te-sigv4)

Traditional API authentication methods (API tokens, basic auth) have significant security weaknesses:

- **Tokens can be intercepted** during transmission
- **No protection against tampering** - attackers can modify request data
- **No replay protection** - captured requests can be re-sent
- **Single point of failure** - one leaked token compromises everything

TE-SigV4 solves all these problems through cryptographic request signing.

### How It Works

[](#how-it-works)

Every API request is cryptographically signed using HMAC-SHA256:

```
1. Client calculates SHA-256 hash of request body
2. Client builds canonical request (method, path, headers, body hash)
3. Client signs the canonical request with secret key
4. Client sends request with signature in Authorization header
5. Server independently calculates signature using same algorithm
6. Server compares signatures - if they match, request is authentic

```

Your **secret key never leaves your server** - only the signature is transmitted.

### Security Guarantees

[](#security-guarantees)

- **Request Authenticity** - Cryptographically proves the request came from you (only you have the secret key)
- **Request Integrity** - Any modification to the request (headers, body, URL) invalidates the signature
- **Replay Protection** - 5-minute timestamp window prevents captured requests from being re-sent
- **Credential Scoping** - Signatures are scoped to date/service, limiting damage if compromised
- **Zero Credential Exposure** - Secret keys are never transmitted over the network

### Algorithm Details

[](#algorithm-details)

TE-SigV4 uses industry-standard HMAC-SHA256 cryptography with key derivation:

- **Algorithm:** TE-HMAC-SHA256
- **Scope:** `{date}/global/touchestate/te_request`
- **Header:** `TE-HMAC-SHA256 Credential=..., SignedHeaders=..., Signature=...`
- **Region:** `global` (single worldwide region)
- **Service:** `touchestate` (TouchEstate CRM only)

### Why This Matters for Developers

[](#why-this-matters-for-developers)

✅ **Automatic signing** - The SDK handles all signature calculation for you ✅ **Maximum security** - Bank-grade cryptographic authentication for your real estate data ✅ **Simple usage** - Just provide your TouchEstate keys and make requests ✅ **Zero complexity** - No manual cryptography or signature logic needed

```
// All signature calculation happens automatically
$properties = TouchEstate::properties()->list();

// Behind the scenes:
// 1. SDK calculates body hash
// 2. SDK builds canonical request
// 3. SDK signs with your secret key
// 4. SDK adds Authorization header
// 5. SDK sends signed request
// You don't see any of this complexity!
```

Installation
------------

[](#installation)

Install via Composer:

```
composer require touchestate/php-sdk
```

### Requirements

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.x or 11.x (for Laravel integration)
- GuzzleHTTP 7.x

Quick Start
-----------

[](#quick-start)

### 1. Get Your API Keys

[](#1-get-your-api-keys)

1. Log in to [TouchEstate Dashboard](https://app.touchestate.am)
2. Navigate to **Settings** → **Access Keys**
3. Click **Create Access Key**
4. Copy both keys (secret key shown only once!)

### 2. Configure Environment

[](#2-configure-environment)

Add your credentials to `.env`:

```
TOUCHESTATE_PUBLIC_KEY=pk_live_your_public_key_here
TOUCHESTATE_SECRET_KEY=sk_live_your_secret_key_here
TOUCHESTATE_BASE_URL=https://api.touchestate.am

# Disable SSL verification only for local development on Windows
# Never set to false in production
TOUCHESTATE_VERIFY_SSL=true
```

### 3. Start Using

[](#3-start-using)

```
use TouchEstate\Sdk\Facades\TouchEstate;

// List properties
$properties = TouchEstate::properties()->list([
    'page' => 1,
    'pageSize' => 20,
]);

foreach ($properties['items'] as $property) {
    echo $property['title'] . ' - $' . number_format($property['price']) . "\n";
}

// Get single property
$property = TouchEstate::properties()->retrieve('property-id');
echo $property['title'];
```

Laravel Integration
-------------------

[](#laravel-integration)

### Service Provider (Auto-registered)

[](#service-provider-auto-registered)

The package automatically registers its service provider in Laravel 10+.

### Publish Configuration

[](#publish-configuration)

```
php artisan vendor:publish --tag=touchestate-config
```

This creates `config/touchestate.php`:

```
return [
    'public_key'      => env('TOUCHESTATE_PUBLIC_KEY'),
    'secret_key'      => env('TOUCHESTATE_SECRET_KEY'),
    'base_url'        => env('TOUCHESTATE_BASE_URL', 'https://api.touchestate.am'),
    'timeout'         => env('TOUCHESTATE_TIMEOUT', 30),
    'connect_timeout' => env('TOUCHESTATE_CONNECT_TIMEOUT', 10),
    'verify_ssl'      => env('TOUCHESTATE_VERIFY_SSL', true),
];
```

### Usage Methods

[](#usage-methods)

#### 1. Facade (Recommended)

[](#1-facade-recommended)

```
use TouchEstate\Sdk\Facades\TouchEstate;

$properties = TouchEstate::properties()->list();
$contacts = TouchEstate::contacts()->list();
```

#### 2. Dependency Injection

[](#2-dependency-injection)

```
use TouchEstate\Sdk\TouchEstateClient;

class PropertyController extends Controller
{
    public function __construct(
        private TouchEstateClient $client
    ) {}

    public function index()
    {
        $properties = $this->client->properties()->list([
            'page' => 1,
            'pageSize' => 20,
        ]);

        return view('properties.index', compact('properties'));
    }
}
```

#### 3. Service Container

[](#3-service-container)

```
$client = app('touchestate');
$properties = $client->properties()->list();
```

Standalone Usage (Without Laravel)
----------------------------------

[](#standalone-usage-without-laravel)

```
use TouchEstate\Sdk\TouchEstateClient;

$client = new TouchEstateClient([
    'public_key' => 'pk_live_xxx',
    'secret_key' => 'sk_live_xxx',
    'base_url' => 'https://api.touchestate.am',
]);

$properties = $client->properties()->list();
```

API Reference
-------------

[](#api-reference)

### Properties Service

[](#properties-service)

#### List Properties

[](#list-properties)

```
$properties = $client->properties()->list([
    'page' => 1,          // Page number (default: 1)
    'pageSize' => 20,     // Items per page (max: 100)
]);
```

**Response:**

```
[
    'items' => [
        [
            'id' => 'uuid',
            'title' => 'Luxury Apartment in Yerevan',
            'price' => 500000,
            'propertyType' => 'Apartment',
            'listingType' => 'Sale',
            'bedrooms' => 3,
            'bathrooms' => 2,
            'area' => 120.5,
            'address' => [...],
            // ... more fields
        ],
    ],
    'pageNumber' => 1,
    'pageSize' => 20,
    'totalCount' => 150,
    'totalPages' => 8,
    'hasNextPage' => true,
    'hasPreviousPage' => false,
]
```

#### Retrieve Single Property

[](#retrieve-single-property)

```
$property = $client->properties()->retrieve('property-id');
```

### Contacts Service

[](#contacts-service)

#### List Contacts

[](#list-contacts)

```
$contacts = $client->contacts()->list([
    'page' => 1,
    'pageSize' => 50,
]);
```

**Response:**

```
[
    'items' => [
        [
            'id' => 'uuid',
            'firstName' => 'John',
            'lastName' => 'Doe',
            'email' => 'john@example.com',
            'phone' => '+1234567890',
            'type' => 'Lead',
            // ... more fields
        ],
    ],
    'pageNumber' => 1,
    'pageSize' => 50,
    'totalCount' => 500,
    'totalPages' => 10,
]
```

#### Retrieve Single Contact

[](#retrieve-single-contact)

```
$contact = $client->contacts()->retrieve('contact-id');
```

### Workspace Service

[](#workspace-service)

#### Get Workspace Information

[](#get-workspace-information)

Get information about your workspace (determined from your API key):

```
$workspace = $client->workspace()->retrieve();

// Or use the alias method
$workspace = $client->workspace()->info();
```

**Response:**

```
[
    'id' => 'uuid',
    'name' => 'My Real Estate Agency',
    'slug' => 'my-agency',
    'logoUrl' => 'https://cdn.touchestate.am/logos/...',
    'description' => 'Leading real estate agency in Yerevan',
    'timezone' => 'Asia/Yerevan',
    'defaultCommissionPercent' => 5.0,
    'isActive' => true,
    'createdAt' => '2024-01-01T00:00:00Z',
]
```

**Use Cases:**

- Display workspace branding in external applications
- Sync workspace settings and configuration
- Validate workspace status and permissions
- Show workspace details in CRM integrations

Error Handling
--------------

[](#error-handling)

The SDK provides specific exception types for different error scenarios:

### Exception Hierarchy

[](#exception-hierarchy)

```
TouchEstateException (base)
├── AuthenticationException (401)
└── ApiException (API errors)
    ├── InvalidRequestException (4xx)
    ├── RateLimitException (429)
    └── ServerException (5xx)

```

### Basic Error Handling

[](#basic-error-handling)

```
use TouchEstate\Sdk\Exception\AuthenticationException;
use TouchEstate\Sdk\Exception\InvalidRequestException;
use TouchEstate\Sdk\Exception\RateLimitException;
use TouchEstate\Sdk\Exception\ServerException;

try {
    $properties = $client->properties()->list();
} catch (AuthenticationException $e) {
    // Invalid credentials - check your keys
    Log::error('Authentication failed: ' . $e->getMessage());
} catch (InvalidRequestException $e) {
    // Bad request, not found, validation error
    Log::warning('Invalid request: ' . $e->getMessage());
    $details = $e->getResponseData(); // Get API error details
} catch (RateLimitException $e) {
    // Too many requests - implement backoff
    Log::warning('Rate limited, retrying later');
} catch (ServerException $e) {
    // Server error - retry with backoff
    Log::error('Server error: ' . $e->getMessage());
}
```

### Retry Logic Example

[](#retry-logic-example)

```
function retryableRequest(callable $request, int $maxRetries = 3): mixed
{
    for ($attempt = 1; $attempt properties()->list(['page' => 1]);
});
```

### Getting Error Details

[](#getting-error-details)

```
try {
    $property = $client->properties()->retrieve('invalid-id');
} catch (InvalidRequestException $e) {
    // HTTP status code
    echo $e->getCode(); // 404

    // Error message (auto-extracted from API response)
    echo $e->getMessage(); // "Resource not found"

    // Full response body
    echo $e->getResponseBody();

    // Decoded response data
    $data = $e->getResponseData();
    if ($data) {
        print_r($data);
    }
}
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom HTTP Client

[](#custom-http-client)

```
use TouchEstate\Sdk\HttpClient\GuzzleClient;

$httpClient = new GuzzleClient([
    'timeout' => 60,
    'connect_timeout' => 30,
    'verify' => true,
]);

$client = new TouchEstateClient([
    'public_key' => 'pk_live_xxx',
    'secret_key' => 'sk_live_xxx',
    'http_client' => $httpClient,
]);
```

### Custom Headers

[](#custom-headers)

```
use TouchEstate\Sdk\Util\RequestOptions;

$options = new RequestOptions([
    'X-Request-ID' => 'unique-request-id',
]);

$properties = $client->properties()->list(['page' => 1], $options);
```

### Environment-Specific Configuration

[](#environment-specific-configuration)

```
// config/touchestate.php
return [
    'public_key' => env('TOUCHESTATE_PUBLIC_KEY'),
    'secret_key' => env('TOUCHESTATE_SECRET_KEY'),
    'base_url' => env('APP_ENV') === 'production'
        ? 'https://api.touchestate.am'
        : 'http://localhost:5100',
    'timeout' => 30,
];
```

Logging
-------

[](#logging)

The SDK integrates with Laravel's logging system (PSR-3 compatible) to provide detailed insights into API requests, responses, and errors.

### Automatic Logging

[](#automatic-logging)

When using Laravel, the SDK automatically logs to your configured logger:

```
use TouchEstate\Sdk\Facades\TouchEstate;

// SDK automatically logs:
// [INFO] TouchEstate API request { method, path, params_count }
// [INFO] TouchEstate API response { method, path, status, duration_ms }
$properties = TouchEstate::properties()->list(['page' => 1]);
```

### Log Levels

[](#log-levels)

- **INFO**: API requests and successful responses
- **WARNING**: Rate limiting (429)
- **ERROR**: Authentication failures (401), client errors (4xx), server errors (5xx)

### Basic Error Handling with Logging

[](#basic-error-handling-with-logging)

```
use TouchEstate\Sdk\Facades\TouchEstate;
use TouchEstate\Sdk\Exception\AuthenticationException;
use TouchEstate\Sdk\Exception\RateLimitException;
use TouchEstate\Sdk\Exception\ServerException;
use Illuminate\Support\Facades\Log;

try {
    // INFO: TouchEstate API request
    $properties = TouchEstate::properties()->list(['page' => 1]);

    // INFO: TouchEstate API response { status: 200, duration_ms: 125 }
    Log::info('Properties fetched successfully', [
        'count' => $properties['totalCount'],
    ]);

} catch (AuthenticationException $e) {
    // ERROR: TouchEstate API authentication failed (already logged by SDK)
    Log::critical('API authentication broken - check keys', [
        'user_id' => auth()->id(),
    ]);

    return response()->json(['error' => 'Service unavailable'], 503);

} catch (RateLimitException $e) {
    // WARNING: TouchEstate API rate limit exceeded (already logged by SDK)
    Log::warning('Rate limit hit - implementing backoff', [
        'user_id' => auth()->id(),
    ]);

    return response()->json(['error' => 'Too many requests'], 429);

} catch (ServerException $e) {
    // ERROR: TouchEstate API server error (already logged by SDK)
    Log::error('API server error - will retry', [
        'error' => $e->getMessage(),
    ]);

    return response()->json(['error' => 'Service temporarily unavailable'], 503);
}
```

### Advanced: Retry Logic with Logging

[](#advanced-retry-logic-with-logging)

```
use TouchEstate\Sdk\Exception\RateLimitException;
use TouchEstate\Sdk\Exception\ServerException;
use Illuminate\Support\Facades\Log;

function fetchPropertiesWithRetry($client, $params, $maxRetries = 3): array
{
    $attempt = 0;

    while ($attempt < $maxRetries) {
        $attempt++;

        try {
            Log::info('Fetching properties', [
                'attempt' => $attempt,
                'max_attempts' => $maxRetries,
            ]);

            $properties = $client->properties()->list($params);

            // SUCCESS
            Log::info('Properties fetched successfully', [
                'attempt' => $attempt,
                'count' => $properties['totalCount'],
            ]);

            return $properties;

        } catch (RateLimitException | ServerException $e) {
            // WARNING/ERROR already logged by SDK

            if ($attempt === $maxRetries) {
                Log::error('All retry attempts exhausted', [
                    'attempts' => $maxRetries,
                    'last_error' => $e->getMessage(),
                ]);

                throw $e;
            }

            // Exponential backoff: 1s, 2s, 4s
            $delay = pow(2, $attempt - 1);

            Log::warning('Retrying after delay', [
                'attempt' => $attempt,
                'delay_seconds' => $delay,
                'error' => $e->getMessage(),
            ]);

            sleep($delay);
        }
    }
}

// Usage
try {
    $properties = fetchPropertiesWithRetry($client, ['page' => 1]);
} catch (Exception $e) {
    return response()->json(['error' => 'Failed to fetch properties'], 500);
}
```

### Custom Log Channel

[](#custom-log-channel)

Create a dedicated channel for TouchEstate logs:

```
// config/logging.php
'channels' => [
    'touchestate' => [
        'driver' => 'daily',
        'path' => storage_path('logs/touchestate.log'),
        'level' => env('APP_ENV') === 'production' ? 'warning' : 'debug',
        'days' => 14,
    ],
],
```

Use the custom channel:

```
use Illuminate\Support\Facades\Log;

$client = new TouchEstateClient([
    'public_key' => config('touchestate.public_key'),
    'secret_key' => config('touchestate.secret_key'),
    'logger' => Log::channel('touchestate'),
]);
```

### Example Log Output

[](#example-log-output)

```
[2026-02-15 15:30:00] production.INFO: TouchEstate API request {"method":"GET","path":"/api/external/properties","params_count":2}
[2026-02-15 15:30:00] production.INFO: TouchEstate API response {"method":"GET","path":"/api/external/properties","status":200,"duration_ms":125.43}
[2026-02-15 15:30:00] production.INFO: Properties fetched successfully {"count":62}

```

Testing
-------

[](#testing)

The SDK includes comprehensive tests:

```
# Run all tests
vendor/bin/phpunit

# Run with coverage
vendor/bin/phpunit --coverage-html coverage

# Run specific test suite
vendor/bin/phpunit tests/Unit
vendor/bin/phpunit tests/Integration

# Pretty output
vendor/bin/phpunit --testdox
```

**Test Coverage:** 57 tests, 89 assertions, 100% coverage of core functionality.

Security Best Practices
-----------------------

[](#security-best-practices)

### 1. Never Commit Secrets

[](#1-never-commit-secrets)

**CRITICAL:** Never commit actual API keys to version control.

```
# ❌ NEVER commit files with actual secrets
git add .env
git add .env.production
git add .env.local

# ✅ ALWAYS keep .env files in .gitignore
# .env files should never be tracked by Git
```

**Proper Setup:**

```
# .env (NEVER committed - contains actual secrets)
TOUCHESTATE_PUBLIC_KEY=pk_live_abc123...
TOUCHESTATE_SECRET_KEY=sk_live_xyz789...
TOUCHESTATE_BASE_URL=https://api.touchestate.am
```

```
// config/touchestate.php (committed - contains env() references only)
return [
    'public_key' => env('TOUCHESTATE_PUBLIC_KEY'),  // ✅ Safe to commit
    'secret_key' => env('TOUCHESTATE_SECRET_KEY'),  // ✅ Safe to commit
    'base_url' => env('TOUCHESTATE_BASE_URL', 'https://api.touchestate.am'),
];
```

### 2. Use Environment Variables

[](#2-use-environment-variables)

Never hardcode credentials in your code:

```
// ❌ NEVER hardcode keys
$client = new TouchEstateClient([
    'public_key' => 'pk_live_abc123',
    'secret_key' => 'sk_live_xyz789',
]);

// ✅ ALWAYS use environment variables
$client = new TouchEstateClient([
    'public_key' => env('TOUCHESTATE_PUBLIC_KEY'),
    'secret_key' => env('TOUCHESTATE_SECRET_KEY'),
]);

// ✅ Or use Laravel config (recommended)
$client = new TouchEstateClient([
    'public_key' => config('touchestate.public_key'),
    'secret_key' => config('touchestate.secret_key'),
]);
```

### 3. Use Different Keys Per Environment

[](#3-use-different-keys-per-environment)

Each environment should have its own keys:

```
# .env.production (production server only)
TOUCHESTATE_PUBLIC_KEY=pk_live_production_key
TOUCHESTATE_SECRET_KEY=sk_live_production_key

# .env.staging (staging server only)
TOUCHESTATE_PUBLIC_KEY=pk_test_staging_key
TOUCHESTATE_SECRET_KEY=sk_test_staging_key

# .env (local development only)
TOUCHESTATE_PUBLIC_KEY=pk_test_dev_key
TOUCHESTATE_SECRET_KEY=sk_test_dev_key
```

### 4. Rotate Keys Regularly

[](#4-rotate-keys-regularly)

Generate new keys periodically and revoke old ones:

1. Create new keys in [TouchEstate Dashboard](https://app.touchestate.am/settings/access-keys)
2. Update environment variables on all servers
3. Test the new keys work correctly
4. Revoke old keys in the dashboard

### 5. Monitor Key Usage

[](#5-monitor-key-usage)

Regularly check key usage in the TouchEstate dashboard:

- Last used timestamp
- Request volume
- Any suspicious activity

### 6. Revoke Compromised Keys Immediately

[](#6-revoke-compromised-keys-immediately)

If a key is leaked or compromised:

1. **Revoke immediately** in the dashboard
2. Generate new replacement keys
3. Update environment variables on all servers
4. Review recent activity for unauthorized access
5. Investigate how the leak occurred

Troubleshooting
---------------

[](#troubleshooting)

### Authentication Fails (401)

[](#authentication-fails-401)

**Possible causes:**

- Invalid public/secret key
- Key has expired
- Signature mismatch (clock skew)

**Solutions:**

- Verify keys are correct in `.env`
- Check key status in dashboard
- Ensure server time is synchronized (`ntpdate` or NTP service)

### Rate Limit Exceeded (429)

[](#rate-limit-exceeded-429)

**Solutions:**

- Implement exponential backoff
- Cache frequently accessed data
- Reduce request frequency
- Consider upgrading plan if needed

### Connection Timeout

[](#connection-timeout)

**Solutions:**

- Increase timeout in config
- Check network connectivity
- Verify API endpoint URL

### Invalid Response Format

[](#invalid-response-format)

**Solutions:**

- Update SDK to latest version
- Check API compatibility
- Verify base URL is correct

Support
-------

[](#support)

- **Documentation:**
- **Dashboard:**
- **Issues:**
- **Source Code:**
- **Email:**

Changelog
---------

[](#changelog)

### 1.0.0 (2026-02-15)

[](#100-2026-02-15)

- Initial release
- TE-SigV4 authentication
- Properties API support
- Contacts API support
- Laravel integration
- Comprehensive error handling
- 100% test coverage

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

Credits
-------

[](#credits)

Developed by [TouchEstate](https://touchestate.am) Team.

---

**Ready to build amazing real estate applications?** [Get your API keys now!](https://app.touchestate.am/settings/access-keys)

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance76

Regular maintenance activity

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 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

136d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a60c6cb4f65978c46f524af9839ca20ec1475bf91d0ca008206fda818d736d5b?d=identicon)[innovayse](/maintainers/innovayse)

---

Top Contributors

[![edgar2031](https://avatars.githubusercontent.com/u/197250615?v=4)](https://github.com/edgar2031 "edgar2031 (5 commits)")

---

Tags

laravelGuzzlesignatureAuthenticationlaravel-packagecalendarcrmREST APIapi clientphp-sdkpropertiesApi Wrappercontactshmacreal-estateappointmentsdealsinnovaysetouchestateproperty-managementsigv4

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/touchestate-php-sdk/health.svg)

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

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[illuminate/http

The Illuminate Http package.

11937.9M6.9k](/packages/illuminate-http)[venturedrake/laravel-crm

A free open source CRM built as a package for laravel projects

43311.2k](/packages/venturedrake-laravel-crm)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5021.9k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

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