Before you start
Filed registers each partner by hand. Contact Filed to receive:
You supply your redirect URI during registration. Filed matches it exactly,
so a trailing slash or an extra query parameter is rejected. Register every
environment you need (production, staging) as a separate URI.
Your customers must already be Filed customers. Filed does not offer self-serve
signup, so a workspace is created under contract by the Filed team. Signing a
customer up in your product does not create a Filed account for them.
Endpoints
Filed publishes
RFC 8414 metadata, so most OAuth
libraries can configure themselves:
cURL
Scopes
Request only what you use. Your customer sees this list on the consent screen in the wording below, so an unnecessary scope is a reason for them to decline.
Omit the
scope parameter to request everything you are registered for.
Scopes are recorded on the grant and shown to the customer, but Filed does not
yet enforce them field by field. Today a token’s real limit is the workspace it
belongs to, and whether the grant included any write scope at all. Treat scopes
as a contract you keep, not a boundary Filed enforces for you.
Connect a customer
1. Send the customer to Filed
Generate a PKCE verifier and challenge, store the verifier against the user’s session, and redirect their browser to the authorization endpoint.string
required
The identifier Filed issued you.
string
required
Must match one of your registered URIs exactly.
string
required
Always
code.string
required
Base64url SHA-256 of your verifier.
string
required
Always
S256. Filed rejects plain.string
Space-delimited. Omit to request every scope you are registered for.
string
Returned to you unchanged. Use it to defend against CSRF.
2. The customer approves
Filed asks them to sign in, choose which of their workspaces to connect, and review what you are asking for. The grant covers that one workspace: your token cannot reach the customer’s other workspaces. Only an opaque handle for the request travels in the browser. Yourclient_id
and the requested scopes stay on Filed’s server, so nothing the customer can
edit in the URL bar changes what the grant permits.
3. Receive the code
Filed redirects back to yourredirect_uri:
state matches what you stored. The code is single use and expires after
60 seconds, so exchange it immediately.
4. Exchange the code for tokens
Call the token endpoint from your backend. Authenticate with HTTP Basic, sending yourclient_id as the username and your client_secret as the
password. This is the client_secret_basic method.
cURL
string
A Filed workspace token. Send it as a bearer token to the Filed API.
string
Always
Bearer.number
Seconds until the access token expires. Always
180.string
Store this against the customer. It is valid for 90 days and is the credential
that represents the grant.
string
Space-delimited scopes the customer approved. Returned on this exchange only.
string
The workspace the grant is pinned to. Returned on this exchange only, because it
never changes for the life of the grant.
string
Display name of that workspace, so you can show the customer what they connected.
Returned on this exchange only.
5. Call the Filed API
cURL
Pushing documents
Documents go in the same way as any other integration — stage the files, then calladdClientDocuments — with one extra
step the first time you push for a client.
Link the client to your connection first. addClientDocuments takes a Filed
clientId, and the push is refused with FAILED_PRECONDITION until a link
exists between your connection and that client:
externalId is your identifier for the client. Filed cannot create the link
for you because only you know that value, and it is what lets you find the same
client again later.
The link is also how Filed attributes what you push. A document filed under your
connection’s link is traceable back to your product; without one it would be
indistinguishable from a document the customer uploaded in Filed themselves —
the access token identifies the customer who approved your grant, not whoever
acted in your product.
Only
addClientDocuments carries this attribution today. Documents attached
through createClient, initiateTaxReview, or initiateTaxAdvisor are recorded
as ordinary uploads.Refreshing
Access tokens last three minutes. This is deliberate: the long-lived credential is the refresh token you hold, and what reaches the API is not. Exchange the refresh token whenever you need a fresh access token rather than caching one.cURL
scope, workspace_id, and
workspace_name. Filed returns the same refresh token rather than rotating
it, so there is nothing to store after a refresh.
The refresh token is valid for 90 days. When it expires, send the customer
through the flow again.
When a customer disconnects
Customers manage the connection in Filed under Plugins, where your integration appears by name alongside their others. Disconnecting revokes the grant. Because access tokens are short lived, a disconnect takes effect within three minutes at the outside. Your next refresh fails withinvalid_grant. The same
happens if the customer who approved the grant leaves the workspace, or if the
90 days elapse.
Treat invalid_grant on refresh as “this connection is over”: stop retrying,
clear the stored token, and prompt the customer to reconnect if they want to
continue.
Handling failures
Some failures happen before Filed can trust yourredirect_uri: an unknown
client_id, or a URI that is not registered. Filed renders an error page in the
customer’s browser rather than redirecting, because bouncing a browser to an
unverified URI is how an open redirect is built. Check your registration if a
customer reports seeing this page.
Once the redirect URI is verified, everything comes back to you as query
parameters, per
RFC 6749:
access_denied covers three distinct situations, and the description tells you
which:
The last two are ordinary outcomes, not rare edge cases, because Filed accounts
are provisioned under contract. Filed hands the browser back to you rather than
stopping on a Filed page, so your product is the one that explains what to do
next.
The token endpoint returns JSON errors:
Current limits
Worth knowing before you build:- Scopes are not enforced field by field yet, as described above.
- There is no token revocation endpoint. The discovery document omits it rather than advertising one that does not work. Customers revoke by disconnecting.
- Refresh tokens are not rotated. Refreshing returns the same token, so its 90-day life is both how long a leaked copy stays usable and how often a customer reconnects.
- Authorization requests expire after 10 minutes, so a customer who leaves the consent screen open and comes back has to start again.