> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formabledocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PHP

> Install and use formable/formable-sdk, the official PHP SDK for the Formable API.

[`formable/formable-sdk`](https://packagist.org/packages/formable/formable-sdk) is the official PHP SDK for the Formable API (v1). It covers templates, signature requests, redlining, and billing.

* Guzzle HTTP client (injectable)
* PHP 8.1+

Source code is on [GitHub](https://github.com/FormableDocs/formable-php).

## Installation

```bash theme={null}
composer require formable/formable-sdk
```

## Initialize the client

Pass your API key from [Settings](https://app.formabledocs.com/settings). It's sent as a bearer token on every request.

```php theme={null}
use Formable\Formable;

$formable = new Formable(getenv('FORMABLE_API_KEY'));
```

## Templates

Upload a document to create a reusable template, then mint edit URLs to place fields in the embedded editor. See the [embedded templates walkthrough](/walkthroughs/embedded-templates). `file` accepts a path, raw contents, or a PSR-7 stream.

```php theme={null}
$result = $formable->templates->create(
    file: './nda.docx',
    filename: 'nda.docx',
    signerRoles: [
        ['name' => 'Client', 'order' => 0],
        ['name' => 'Witness', 'order' => 1],
    ],
);

$templateId = $result['templateId'];

// Mint a fresh edit URL later (expires after 1 day)
$edit = $formable->templates->createEditUrl($templateId);
```

## Signature requests

Send a template for signing by email, or embed the signing experience in your product. See the [embedded signing walkthrough](/walkthroughs/embedded-signing).

```php theme={null}
// Formable emails each signer a signing link
$request = $formable->signatureRequests->create(
    templateId: $templateId,
    signers: [
        ['email' => 'jane@example.com', 'name' => 'Jane Doe', 'role' => 'Client'],
        ['email' => 'bob@example.com', 'name' => 'Bob Smith', 'role' => 'Witness'],
    ],
);

// Embedded flow: mint signing URLs to embed in an iframe yourself
$embedded = $formable->signatureRequests->createEmbedded(
    templateId: $templateId,
    signers: [['email' => 'jane@example.com', 'name' => 'Jane Doe', 'role' => 'Client']],
    testMode: true,
);

$signer = $embedded['signers'][0];
$signing = $formable->signatureRequests->createSigningUrl(
    $signer['recipientSignatureId']
);

// Track progress
$current = $formable->signatureRequests->get($embedded['signatureRequestId']);
$all = $formable->signatureRequests->list(
    updatedSince: new DateTimeImmutable('2026-01-01T00:00:00Z')
);
$events = $formable->signatureRequests->getEvents($embedded['signatureRequestId']);

// Download the signed document once completed
$envelope = $formable->signatureRequests->getSignedEnvelope(
    $embedded['signatureRequestId']
);
```

<Note>
  `getSignedEnvelope` throws a `409` until the document is complete. Wait for the [`document_completed`](/webhooks/events#document_completed) webhook, or poll `get` until `status` is `Completed`.
</Note>

## Redline requests

Run turn-based contract negotiation before signing. See the [redlining walkthrough](/walkthroughs/redlining).

```php theme={null}
$created = $formable->redlineRequests->create(
    templateId: $templateId,
    members: [
        ['email' => 'us@example.com', 'displayName' => 'John Doe', 'role' => 'DisclosingParty'],
        ['email' => 'them@example.com', 'displayName' => 'Jane Smith', 'role' => 'ReceivingParty'],
    ],
    metadata: ['subject' => 'Mutual NDA'],
);

$redlineRequestId = $created['redlineRequestId'];

// Mint a redline URL for a member (embed in an iframe)
$url = $formable->redlineRequests->createUrl($redlineRequestId, 'them@example.com');

// Manage members and track progress
$formable->redlineRequests->updateMembers($redlineRequestId, [
    ['email' => 'counsel@example.com', 'displayName' => 'Counsel', 'role' => 'ReceivingCounsel'],
]);
$redline = $formable->redlineRequests->get($redlineRequestId);
$events = $formable->redlineRequests->getEvents($redlineRequestId);
```

## Billing and health

```php theme={null}
$billing = $formable->billing();
$health = $formable->health();
```

## Error handling

All non-2xx responses throw a `FormableError` with the server's error message, HTTP status, and parsed response body.

```php theme={null}
use Formable\FormableError;

try {
    $formable->signatureRequests->get('missing-id');
} catch (FormableError $error) {
    error_log($error->status.' '.$error->getMessage());
}
```

## Configuration

The client constructor takes an API key, then optional `baseUrl` and Guzzle `client` arguments.

```php theme={null}
use Formable\Formable;
use GuzzleHttp\Client;

$formable = new Formable(
    apiKey: getenv('FORMABLE_API_KEY'),
    baseUrl: 'https://api.formabledocs.com/v1',
    client: new Client(['timeout' => 60]),
);
```

| Option    | Description                                               | Default                           |
| --------- | --------------------------------------------------------- | --------------------------------- |
| `apiKey`  | Your Formable API key (sent as a bearer token). Required. | -                                 |
| `baseUrl` | Override the API base URL.                                | `https://api.formabledocs.com/v1` |
| `client`  | Custom `GuzzleHttp\ClientInterface`.                      | Built-in client with 60s timeout  |

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Go from a plain document to a signed PDF in 4 calls.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/introduction">
    Every endpoint the SDK wraps, with a live playground.
  </Card>
</CardGroup>
