diff --git a/flexiapi/app/Account.php b/flexiapi/app/Account.php
index fa012e5..f1ad0e3 100644
--- a/flexiapi/app/Account.php
+++ b/flexiapi/app/Account.php
@@ -38,7 +38,7 @@ class Account extends Authenticatable
protected $with = ['passwords', 'emailChangeCode', 'types', 'actions', 'dictionaryEntries', 'carddavServers'];
protected $hidden = ['expire_time', 'pivot', 'currentProvisioningToken', 'currentRecoveryCode', 'dictionaryEntries'];
- protected $appends = ['realm', 'provisioning_token', 'provisioning_token_expire_at', 'dictionary'];
+ protected $appends = ['realm', 'provisioning_token', 'provisioning_token_expire_at', 'dictionary', 'sip_uri'];
protected $casts = [
'activated' => 'boolean',
];
@@ -87,7 +87,8 @@ class Account extends Authenticatable
return $query->where('username', $username)
->where('domain', $domain);
- };
+ }
+ ;
return $query->where('id', '<', 0);
}
@@ -188,7 +189,8 @@ class Account extends Authenticatable
public function getDictionaryAttribute()
{
- if ($this->dictionaryEntries->isEmpty()) return new stdClass;
+ if ($this->dictionaryEntries->isEmpty())
+ return new stdClass;
return $this->dictionaryEntries->keyBy('key')->map(function ($entry) {
return $entry->value;
@@ -362,11 +364,16 @@ class Account extends Authenticatable
{
return $this->space->carddavServers()->whereNotIn('id', function ($query) {
$query->select('space_carddav_server_id')
- ->from('account_carddav_credentials')
- ->where('account_id', $this->id);
+ ->from('account_carddav_credentials')
+ ->where('account_id', $this->id);
})->get();
}
+ public function getSipUriAttribute(): string
+ {
+ return 'sip:' . $this->getIdentifierAttribute();
+ }
+
public function getIdentifierAttribute(): string
{
return $this->attributes['username'] . '@' . $this->attributes['domain'];
diff --git a/flexiapi/app/CallForwarding.php b/flexiapi/app/CallForwarding.php
index fbb88bc..8e975e0 100644
--- a/flexiapi/app/CallForwarding.php
+++ b/flexiapi/app/CallForwarding.php
@@ -10,10 +10,23 @@ class CallForwarding extends Model
'enabled' => 'boolean'
];
protected $fillable = ['enabled', 'account_id', 'type', 'forward_to', 'sip_uri'];
- protected $hidden = ['account_id'];
+ protected $hidden = ['account_id', 'contact'];
+ protected $with = ['contact'];
+ protected $appends = ['contact_sip_uri'];
public function account()
{
return $this->belongsTo(Account::class);
}
+
+ public function contact()
+ {
+ return $this->hasOne(Account::class, 'id', 'contact_id');
+ }
+
+ public function getContactSipUriAttribute(): ?string
+ {
+ if ($this->contact) return $this->contact->sip_uri;
+ return null;
+ }
}
diff --git a/flexiapi/resources/views/api/documentation/accounts/call_forwarding.blade.php b/flexiapi/resources/views/api/documentation/accounts/call_forwarding.blade.php
index 450ea3c..b1733b3 100644
--- a/flexiapi/resources/views/api/documentation/accounts/call_forwarding.blade.php
+++ b/flexiapi/resources/views/api/documentation/accounts/call_forwarding.blade.php
@@ -1,5 +1,21 @@
## Account Call Forwardings
+When a `call_forwarding` object is configured to forward to a contact (`forward_to: 'contact'`) the SIP URI of the contact is returned in a `contact_sip_uri` attributes.
+
+```
+{
+ "id": 1,
+ "type": "always",
+ "forward_to": "contact",
+ "sip_uri": null,
+ "enabled": true,
+ "contact_id": 3,
+ "updated_at": "2026-03-12T14:53:22.000000Z",
+ "created_at": "2026-03-12T14:53:22.000000Z",
+ "contact_sip_uri": "sip:mcclure.kailey@sip.example.com"
+}
+```
+
### `GET /accounts/{id/me}/call_forwardings`
User
Admin
diff --git a/flexiapi/tests/Feature/ApiAccountCallForwardingTest.php b/flexiapi/tests/Feature/ApiAccountCallForwardingTest.php
index fa30e3c..13532df 100644
--- a/flexiapi/tests/Feature/ApiAccountCallForwardingTest.php
+++ b/flexiapi/tests/Feature/ApiAccountCallForwardingTest.php
@@ -95,6 +95,10 @@ class ApiAccountCallForwardingTest extends TestCase
])
->assertStatus(201);
+ $this->keyAuthenticated($account)
+ ->get($this->route)
+ ->assertJsonFragment(['contact_sip_uri' => $contactAccount->sip_uri]);
+
// SIP URI
$this->keyAuthenticated($account)
diff --git a/flexiapi/tests/Feature/ApiAccountTest.php b/flexiapi/tests/Feature/ApiAccountTest.php
index 1a45ebb..0d5368b 100644
--- a/flexiapi/tests/Feature/ApiAccountTest.php
+++ b/flexiapi/tests/Feature/ApiAccountTest.php
@@ -134,6 +134,7 @@ class ApiAccountTest extends TestCase
->json($this->method, $this->route, [
'username' => $username,
'domain' => $domain,
+ 'sip_uri' => 'sip:' . $username . '@' . $domain,
'algorithm' => 'SHA-256',
'password' => '123456',
])->assertStatus(200);