Factuarea APIDevelopers

Connecting a client

Connect a client that implements MCP revision 2026-07-28 and authenticate with OAuth or an API key.

Use a client that implements MCP 2026-07-28, including server/discover, per-request protocol metadata and the required headers. Registering the server URL alone does not add support for this revision. Check the client’s supported revision before using Claude Code, Claude Desktop or MCP Inspector.

Connection settings

The endpoint is https://mcp.factuarea.com (/mcp remains an alias). Configure HTTP transport and either OAuth 2.1 or an Authorization: Bearer API key. The protocol guide gives an executable discovery request; resources and prompts explain the fiscal guidance.

Catalog and compatibility

Start with server/discover, then follow tools/list cursors with the same credential. The complete catalog has 457 tools; OAuth can reach 368. Legacy initialize and ping do not establish a session. The Claude Code plugin registers the server, but transport compatibility still depends on the installed client.

Authenticate

The MCP server accepts two kinds of credential on the same https://mcp.factuarea.com endpoint, for two different audiences. Both arrive as Authorization: Bearer <token>; the server tells them apart by the token's shape (fact_* → API key, anything else → OAuth access token).

Channel policy

This is the single most important rule of the MCP surface:

ChannelWhoHow scopes are chosenReachable tools
API keyThe account owner automating their own companyYou pick the scopes when you create the key — up to the super-scope *457 (everything)
OAuth 2.1A third-party app acting on a user's behalfThe user grants scopes on the consent screen, from a curated catalog368

The model mirrors GitHub: a personal access token (API key) is the owner's own credential and may hold any permission, while an OAuth app is external and is limited to a vetted set of scopes the user explicitly approves.

The 89 tools an OAuth app can never reach (only an API key can) are the most sensitive fiscal and privacy operations, plus the first-party account-management surface:

  • VeriFactu writes (verifactu:write) — 8 tools: register/retry/subsanar VeriFactu records and events, upload/activate/revoke FNMT certificates, update VeriFactu settings. These touch AEAT compliance and are owner-only.
  • GDPR erasure (delivery_notes:gdpr_forget) — 1 tool: erase signature-audit PII (Art. 17). Privileged, admin-only.
  • Payments, gateways and stores (stripe_autoinvoicing:*, payouts:read, integration_events:*, stores:*, woocommerce_store:write, shopify_store:write) — 20 tools: 13 for Stripe auto-invoicing, connected accounts, payouts and the gateway-event inbox/replay, plus 7 for store management and connection diagnostics. Fine-grained, API-key-only scopes with no OAuth consent equivalent.
  • Emails and API request logs (emails:read, developers:read) — 5 tools exposing the owner's own delivery and integration diagnostics.
  • Managed companies (companies:*, api_keys:*) — 17 tools: gestoría management of child companies and their API keys. Managing sub-accounts and credentials is first-party only, never granted by third-party consent.
  • Account writes (account:write) — 4 tools: create/rotate/revoke your own API keys and update account personalization. First-party only.
  • Privileged workforce writes/transitions — 33 tools using time_entries:write, absences:write, absences:transition or work_schedules:write; workforce reads and employees:write remain OAuth-reachable.

Everything else — all 368 read/write/transition/send tools — is available to both channels. See Scopes & permissions for the catalog.

API keys

An API key is an opaque Bearer token bound to your company, created in the developer dashboard at Settings → Developers → API Keys. The format and rules are identical to the REST API:

fact_live_<24 alphanumeric characters>   →  production company
fact_test_<24 alphanumeric characters>   →  isolated sandbox company

The prefix is the source of truth for the environment — see Test mode. The secret is shown only once at creation; the backend stores only a bcrypt hash. Pass it to your MCP client as:

Authorization: Bearer fact_test_xxxxxxxxxxxxxxxxxxxxxxxx

For the full key lifecycle — creation, scopes, rotation with grace period, revocation, IP allowlist, expires_at — see the canonical Authentication guide. Keys are shared across the REST and MCP surfaces.

OAuth 2.1

For third-party apps, Factuarea is a full OAuth 2.1 Authorization Server. It supports Dynamic Client Registration, the authorization-code flow with PKCE, and refresh-token rotation. No pre-registration or manual app approval is required — a client registers itself and the user authorizes it. (Interactive clients like Claude Code and the MCP Inspector drive this whole flow for you; the steps below are for building your own client.)

Discovery

Clients discover the server's capabilities through standard metadata endpoints (no /api prefix):

EndpointRFCPurpose
/.well-known/oauth-authorization-server8414Authorization Server Metadata — lists the authorize/token/register/introspect/revoke endpoints, supported scopes, code_challenge_methods_supported: ["S256"].
/.well-known/oauth-protected-resource9728Protected Resource Metadata — declares the MCP resource and which authorization server issues valid tokens.

When an unauthenticated request hits the endpoint, the server responds 401 with a WWW-Authenticate: Bearer ..., resource_metadata="<url>" header so RFC 9728 clients can find the authorization server without guessing.

1. Dynamic Client Registration (RFC 7591)

A client registers itself by POSTing its metadata; the server returns a client_id (and a client_secret for confidential clients):

curl -X POST https://mcp.factuarea.com/api/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My Invoicing Assistant",
    "redirect_uris": ["https://myapp.example.com/callback"],
    "token_endpoint_auth_method": "none"
  }'

Public clients (browser/native apps) register with token_endpoint_auth_method: "none" and rely on PKCE; confidential clients use client_secret_basic. Registration is rate-limited to 60 per minute per IP.

2. Authorization with PKCE

Send the user to the authorize endpoint with a PKCE challenge (code_challenge_method=S256 is the only method accepted):

GET https://mcp.factuarea.com/api/oauth/authorize
  ?response_type=code
  &client_id=<client_id>
  &redirect_uri=https://myapp.example.com/callback
  &scope=factuarea.read invoices.write
  &state=<opaque>
  &code_challenge=<base64url(sha256(verifier))>
  &code_challenge_method=S256

This renders the consent screen, where the user:

  1. Picks the company to grant access to (a user may belong to several).
  2. Picks the environmentlive (the real company) or test (an isolated sandbox), Stripe-style. Test is opt-in; absent ⇒ live.
  3. Reviews and selects the scopes to grant. Sensitive scopes are flagged and not pre-checked.

On approval the server redirects back with a single-use code (and your state). Sensitive operations are filtered out of the catalog the user can approve — see the channel policy.

3. Token exchange

Exchange the code for an access token, sending the PKCE verifier:

curl -X POST https://mcp.factuarea.com/api/oauth/token \
  -d grant_type=authorization_code \
  -d code=<code> \
  -d redirect_uri=https://myapp.example.com/callback \
  -d client_id=<client_id> \
  -d code_verifier=<verifier>
{
  "access_token": "<opaque>",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "<opaque>",
  "scope": "profile.read contacts.read invoices.read invoices.write"
}

The token persists the expanded, fine-grained scopes (macros like factuarea.read are expanded at issue time). Use the access token as the Bearer credential. The token endpoint is rate-limited to 60 per minute per (client, IP) and requires client authentication (HTTP Basic for confidential clients, client_id in the body for public ones).

4. Refresh-token rotation

Refresh tokens rotate by family: each refresh issues a new access token and a new refresh token, and invalidates the one you used.

curl -X POST https://mcp.factuarea.com/api/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=<refresh_token> \
  -d client_id=<client_id>

If a refresh token is replayed (used after rotation — the classic sign of a leak), the server detects the reuse, revokes the entire token family and raises a security alert. Always store and use the latest refresh token only.

Revocation & introspection

EndpointRFCPurpose
POST /api/oauth/revoke7009Revoke an access or refresh token.
POST /api/oauth/introspect7662Check whether a token is active and read its scopes/metadata.

Both require client authentication. Users can also review and revoke connected apps from the Factuarea dashboard, and a company admin who loses access has their tokens revoked automatically on the next call.

Test mode

The MCP server runs against the same two environments as the REST API — live (your real company) and test (an isolated sandbox) — so you can build and validate an agent integration without touching production data, the AEAT, or your clients' inboxes.

How you select test mode depends on the channel:

ChannelHow to use test mode
API keyAuthenticate with a fact_test_ key. The prefix is the source of truth — a fact_test_ token always operates on the sandbox.
OAuth 2.1On the consent screen, pick the Test environment (Stripe-style). Absent ⇒ live. The issued token is bound to that environment.

A test credential operates on a dedicated sandbox company — a technical twin of your real company, provisioned automatically and inheriting its plan, so module/plan gating behaves faithfully. Isolation is structural (test and live data live in separate companies), and external effects are switched off:

EffectIn liveIn test
VeriFactuThe Alta record is created and transmitted to the AEAT.Created locally, but never transmitted to the AEAT.
EmailDocument emails reach real recipients.Not delivered to real recipients.
WebhooksSubscribed events are delivered to your endpoints.Recorded with livemode: false, but not delivered.
FACe (FacturaE)Submissions are presented to the real FACe web service.Simulated — no SOAP call leaves Factuarea; the registry number is synthetic (FACE-SANDBOX-*).

Everything else behaves exactly as in production, and the full set of 457 tools is available in both environments (subject to your scopes and plan). When your flow works end-to-end, switch to live: create a fact_live_ key, or re-run the consent flow and select the live environment.

This is the same sandbox mechanism as the REST API. See the canonical Test mode & sandbox guide for how the sandbox company is provisioned and queried.

On this page

Need a hand?Contact support