Adobe Sign for Laravelconceptlz/adobe-sign-laravel GitHub

Reference

Facade, events, routes & commands

Everything the Laravel bridge adds, in one place: class names, signatures, properties, routes, columns and error messages, exactly as they are in the code. The guides explain when to use each piece.

Classes at a glance

ClassRole
Conceptlz\AdobeSign\Laravel\AdobeSignServiceProviderRegisters config, bindings, routes, publishable files and the command. Auto-discovered.
Conceptlz\AdobeSign\Laravel\AdobeSignManagerBuilds configured clients; forwards unknown calls to the default client.
Conceptlz\AdobeSign\Laravel\Facades\AdobeSignFacade over the manager, alias AdobeSign.
Conceptlz\AdobeSign\Laravel\EloquentTokenStoreCore TokenStore backed by the token table.
Conceptlz\AdobeSign\Laravel\Models\AdobeSignTokenEloquent model for one stored token pair.
Conceptlz\AdobeSign\Laravel\Events\OAuthConnectedA user finished connecting their account.
Conceptlz\AdobeSign\Laravel\Events\WebhookReceivedA new webhook notification arrived.
Conceptlz\AdobeSign\Laravel\Http\Controllers\OAuthControllerThe redirect and callback routes.
Conceptlz\AdobeSign\Laravel\Http\Controllers\WebhookControllerThe webhook route (invokable).
Conceptlz\AdobeSign\Laravel\Console\VerifyCommandadobe-sign:verify.
Conceptlz\AdobeSign\Laravel\MisconfiguredExceptionConfig is missing something a feature needs.

Facade methods

The facade's docblock declares these methods. The first group is defined on AdobeSignManager; the second is forwarded through __call to the default client (client()).

Manager methods

MethodReturnsNotes
client()Conceptlz\AdobeSign\AdobeSignDefault client per adobe-sign.auth
forUser(Authenticatable|string|int $user)Conceptlz\AdobeSign\AdobeSignOAuth client for one user; cached per key
isConnected(Authenticatable|string|int $user)boolA token is stored; no API call
oauth()Conceptlz\AdobeSign\Auth\OAuthClientAuthorization-code flow client
tokens()Conceptlz\AdobeSign\Auth\TokenStoreThe bound token store
userKey(Authenticatable|string|int $user)stringToken store key for a user
webhookHandler()Conceptlz\AdobeSign\Webhook\WebhookHandlerAllow-lists the configured client ids
resolveUserKeyUsing(?callable $resolver)voidStatic; process-wide; null resets
signatureLevel()Conceptlz\AdobeSign\Enum\SignatureLevelFrom adobe-sign.signature_level
qualifiedIssuers()list<string>From adobe-sign.qualified_issuers
signatureShortfalls(string $agreementId, ?SignatureLevel $required = null)list<string>Empty when every signer met the level

Forwarded to the default client

MethodReturnsCore docs
asUser(string $user)Conceptlz\AdobeSign\AdobeSignAuthentication
agreements()Conceptlz\AdobeSign\Resource\AgreementsCreating agreements, Managing agreements
transientDocuments()Conceptlz\AdobeSign\Resource\TransientDocumentsUploading documents
libraryDocuments()Conceptlz\AdobeSign\Resource\LibraryDocumentsOther resources
webhooks()Conceptlz\AdobeSign\Resource\WebhooksWebhooks
users()Conceptlz\AdobeSign\Resource\UsersOther resources
widgets()Conceptlz\AdobeSign\Resource\WidgetsOther resources
megaSigns()Conceptlz\AdobeSign\Resource\MegaSignsOther resources

Container bindings

AbstractConcreteLifetime
AdobeSignManagernew AdobeSignManager($app, config('adobe-sign'))scoped
Conceptlz\AdobeSign\AdobeSignAdobeSignManager::client()bind (the manager caches the client)
Conceptlz\AdobeSign\Auth\TokenStoreEloquentTokenStoresingleton, via bindIf

The manager also uses a bound Psr\Http\Client\ClientInterface when one exists, the cache store from cache_store, and the log channel from log_channel.

Events

OAuthConnected

Conceptlz\AdobeSign\Laravel\Events\OAuthConnected, final, uses Dispatchable. Dispatched by the OAuth callback after the token is stored.

PropertyTypeDescription
$userIlluminate\Contracts\Auth\AuthenticatableThe signed-in user who connected
$keystringThe token store key, from AdobeSignManager::userKey()
$apiAccessPoint?stringThe account's API host, e.g. https://api.eu1.adobesign.com/

WebhookReceived

Conceptlz\AdobeSign\Laravel\Events\WebhookReceived, final, uses Dispatchable. Dispatched by the webhook route once per new notification; duplicates are already dropped. Listeners doing real work should implement ShouldQueue.

PropertyTypeDescription
$eventConceptlz\AdobeSign\Webhook\WebhookEventThe parsed notification: AgreementEvent, MegaSignEvent, WidgetEvent, LibraryDocumentEvent or UnknownEvent. Fields are listed on the Webhooks page.

Routes

NameMethodURI (default)Middleware (default)ActionEnabled by
adobe-sign.oauth.redirectGETadobe-sign/oauth/redirectweb, authOAuthController@redirectoauth.routes
adobe-sign.oauth.callbackGETadobe-sign/oauth/callbackweb, authOAuthController@callbackoauth.routes
adobe-sign.webhookGET, POSTadobe-sign/webhooknoneWebhookControllerwebhooks.enabled

Prefix, path and middleware come from oauth.route_prefix, oauth.route_middleware, webhooks.path and webhooks.middleware. Run php artisan route:list --name=adobe-sign to see them in your app.

Responses

RouteStatusWhen
redirect302Always, to Adobe's consent page; state stored in session key adobe_sign_oauth_state
callback302Success; to oauth.redirect_after
callback400State mismatch (STATE_MISMATCH), no code (MISSING_CODE), or an untrusted api_access_point
callback403Any other OAuthException: user denied access, Adobe rejected the code
callback502TransportException: Acrobat Sign unreachable
callback401No signed-in user
webhook200Accepted, with X-AdobeSign-ClientId header and {"xAdobeSignClientId": "…"} body
webhook403Missing or unknown client id
webhook400POST body unreadable

The adobe-sign:verify command

adobe-sign:verify {--user= : Check this user's OAuth connection instead of the default client}

Calls GET /users/me with the default client, or with forUser($user) when --user is given (a token key, e.g. 42 or team:7). On success it prints "Connected to Acrobat Sign." with the user's email, whether they are an account admin, and the account id, and exits 0. On any SDK exception, including MisconfiguredException, it prints the message and exits 1.

php artisan adobe-sign:verify
php artisan adobe-sign:verify --user=42

Publishable files

TagPublishesCommand
adobe-sign-configconfig/adobe-sign.phpphp artisan vendor:publish --tag=adobe-sign-config
adobe-sign-migrationsThe token table migration, into database/migrationsphp artisan vendor:publish --tag=adobe-sign-migrations

Every config key is described on the Configuration page.

AdobeSignToken model

Conceptlz\AdobeSign\Laravel\Models\AdobeSignToken extends Illuminate\Database\Eloquent\Model.

AspectValue
TablegetTable() returns config('adobe-sign.oauth.table', 'adobe_sign_tokens')
Castsaccess_token and refresh_token: encrypted; expires_at: datetime
Hiddenaccess_token, refresh_token
Guardednothing ($guarded = [])
Propertiesstring $key, string $access_token, ?string $refresh_token, ?Carbon $expires_at, ?string $api_access_point

Useful for admin screens and housekeeping, e.g. listing connections that will lapse:

use Conceptlz\AdobeSign\Laravel\Models\AdobeSignToken;

$stale = AdobeSignToken::where('updated_at', '<', now()->subDays(50))->pluck('key');

EloquentTokenStore

get(string $key): ?Conceptlz\AdobeSign\Auth\AccessToken

The stored token for a key, or null.

put(string $key, Conceptlz\AdobeSign\Auth\AccessToken $token): void

Insert or update the row for the key (updateOrCreate).

forget(string $key): void

Delete the row. Not part of the TokenStore interface, and it doesn't revoke the token at Adobe; call AdobeSign::oauth()->revoke($token) first if that matters.

Migration columns

Table name from adobe-sign.oauth.table (default adobe_sign_tokens):

ColumnDefinition
id$table->id()
keystring, unique
access_tokentext (encrypted)
refresh_tokentext, nullable (encrypted)
expires_attimestamp, nullable
api_access_pointstring, nullable
created_at, updated_at$table->timestamps()

MisconfiguredException

Conceptlz\AdobeSign\Laravel\MisconfiguredException extends RuntimeException and implements the core's Conceptlz\AdobeSign\Exception\AdobeSignException, so a catch (AdobeSignException $e) covers it too. These are the messages it carries:

MessageThrown byFix
Set ADOBE_SIGN_INTEGRATION_KEY, or ADOBE_SIGN_AUTH=oauth.client()Add the key
adobe-sign.auth is "oauth" but no user is signed in; use AdobeSign::forUser($user).client()Use forUser() in jobs, commands and listeners
Set ADOBE_SIGN_CLIENT_ID and ADOBE_SIGN_CLIENT_SECRET to use OAuth.oauth(), forUser(), the OAuth routesAdd the OAuth app credentials
Set ADOBE_SIGN_WEBHOOK_CLIENT_IDS (or ADOBE_SIGN_CLIENT_ID) to receive webhooks.webhookHandler(), the webhook routeAdd the allow-list
ADOBE_SIGN_SIGNATURE_LEVEL must be ses, aes or qes; got "…".signatureLevel(), and so every client creationFix the value

All other exceptions come from the core; see its errors page.

Common questions

Will my IDE autocomplete AdobeSign::agreements()?

Yes. The facade's docblock declares every method with its return type, so PhpStorm, Intelephense and PHPStan/Larastan resolve AdobeSign::agreements()->create() to the core Agreements resource.

Does the package fire events for individual signers or statuses?

It fires one event type for all webhooks, WebhookReceived, and leaves interpretation to you. Check $received->event->event or use is(EventType::…) and isWorkflowCompleted(). The only other event is OAuthConnected.

Can I extend AdobeSignManager?

It isn't final, so you can subclass it and rebind it as scoped in your own service provider. Prefer composition where you can: most needs are covered by binding a ClientInterface or TokenStore, or by building a core client directly.

Can I rename the package's routes?

The names (adobe-sign.oauth.redirect, adobe-sign.oauth.callback, adobe-sign.webhook) are fixed; the URIs and middleware are configurable. The manager relies on the callback's name to build the default redirect URI.