Skip to content

User Access

Choose Your Approach

ApproachBest ForSetup
Entity API Key AccessSimple white-label, no user managementCreate entity → Create API key → Generate server-side launch flow
User-Based AccessRole-based permissions, team collaborationCreate entity → Add users → Generate tokens

Entity API Key Access

The simplest way to give your customers dashboard access when you do not want to manage Space Invoices user records.

How It Works

API key access structure
┌───────────────────────────────────────────────┐
│              Your Application                 │
├───────────────────────────────────────────────┤
│  API Key (entity-scoped)                      │
│  ─────────────────────────                    │
│  Access: Single entity only                   │
│  Use: Backend integrations                    │
├───────────────────────────────────────────────┤
│  Invoices  │  Customers  │  Items             │
└────────────┴─────────────┴────────────────────┘

Setup

1. Create an entity for your customer:

Create entitytypescript
// title: Create an entity
const _entity = await sdk.entities.create({
  name: "My Company",
  address: "123 Business Street",
  city: "Ljubljana",
  post_code: "1000",
  country: "Slovenia",
  country_code: "SI",
  tax_number: "SI12345678",
  is_tax_subject: true,
});

2. Create an entity API key:

Create api keytypescript
// title: Create API key for entity
const _apiKey = await sdk.entityApiKeys.create({
  name: "Production API Key",
}, { entity_id: entity.id });

3. Redirect to dashboard:

Redirect api keytypescript
// title: Use API key in requests
import { SpaceInvoices } from "@spaceinvoices/js-sdk/sdk";

// Initialize SDK with entity API key
const sdk = new SpaceInvoices({
  accessToken: process.env.ENTITY_API_KEY,
});

// All requests are automatically scoped to the entity
const _invoices = await sdk.invoices.list();

Key Points

  • No user records — You don’t manage Space Invoices users
  • Full entity access — API key grants complete access to the entity
  • Environment-specific — Key inherits entity’s environment (live/sandbox)
  • One key per entity — Create additional keys if needed for different purposes
  • Server-side only — Keep the key private and use your backend to initiate access

Integration Flow

API key authentication flow
┌──────────────┐     ┌─────────────────┐     ┌──────────────┐
│   Your       │     │   Your Server   │     │    Space     │
│   System     │────▶│   (Backend)     │────▶│   Invoices   │
└──────────────┘     └─────────────────┘     └──────────────┘
                            │                       │
                            │  Authorization:       │
                            │  Bearer <api_key>     │
                            │─────────────────────▶│
                            │                       │
                            │  API Response         │
                            │◀─────────────────────│
                            │                       │

User-Based Access

For platforms that need role-based permissions or team collaboration within entities.

Email inputs for signup, login, password reset, verification resend, email availability checks, and passkey authentication are normalized to lowercase. For example, signing up with User@Example.com stores user@example.com; either casing can then be used to log in. This does not change white-label account isolation.

How It Works

User-based access structure
┌───────────────────────────────────────────────┐
│                    Entity                     │
├───────────────────────┬───────────────────────┤
│   User A (admin)      │   User B (member)     │
│   Full access         │   Limited access      │
├───────────────────────┴───────────────────────┤
│  Invoices  │  Customers  │  Settings          │
└────────────┴─────────────┴────────────────────┘

User Roles

RolePermissions
viewerRead-only access to invoices, customers, etc.
editorCreate and edit invoices, customers, items
adminFull access including settings, users, API keys

Setup

1. Create an entity for your customer:

Create entitytypescript
// title: Create an entity
const _entity = await sdk.entities.create({
  name: "My Company",
  address: "123 Business Street",
  city: "Ljubljana",
  post_code: "1000",
  country: "Slovenia",
  country_code: "SI",
  tax_number: "SI12345678",
  is_tax_subject: true,
});

2. Add users to the entity:

Add userstypescript
// title: Add users to entity
// Add an admin user
await sdk.entityUsers.addEntityUser({
  email: "admin@company.com",
  role: "admin",
}, { entity_id: entity.id });

// Add a team member
await sdk.entityUsers.addEntityUser({
  email: "team@company.com",
  role: "editor",
}, { entity_id: entity.id });

3. Generate SSO token and redirect:

Generate tokentypescript
// title: Generate user access token
const token = await sdk.entityUsers.generateEntityUserToken(user.id, {}, { entity_id: entity.id });

// Use token to access embedded dashboard
const _dashboardUrl = `https://app.spaceinvoices.com/embed?token=${token.id}`;

Provision Users Silently

For white-label platforms that already authenticate users themselves, you can create Space Invoices users without sending any email. A silent user has no password and no email is sent. Their email counts as verified when the provisioning credential is an account API key or a user with a verified email; otherwise the user must verify their email before sending documents by email.

Silent provisioning requires an account API key or an account owner/admin signed in directly (an interactive session). Delegated (SSO) tokens, including those minted by Generate Token, can’t provision users silently.

1. Create the user with silent: true:

Silent create usertypescript
// title: Provision a user silently
// No email is sent and the user has no password
const user = await sdk.entityUsers.addEntityUser({
  email: "jane@company.com",
  role: "editor",
  silent: true,
  metadata: { external_id: "u_123" },
}, { entity_id: entity.id });

metadata is optional, accepted only together with silent, and holds string key-value data for your own use, such as your internal user ID. silent takes precedence over send_invite: when silent is true no invitation is sent, whatever send_invite says. The response is the new user; use its user_id in the steps below.

2. Look the user up by your own ID:

Find user by metadatatypescript
// title: Find a user by your own ID
const users = await sdk.entityUsers.list({
  entity_id: entity.id,
  query: JSON.stringify({ metadata: { external_id: "u_123" } }),
});

The query parameter filters on email and metadata.

3. Set or clear metadata:

Update user metadatatypescript
// title: Update user metadata
await sdk.entityUsers.update(user.user_id, {
  metadata: { external_id: "u_123", plan: "pro" },
}, { entity_id: entity.id });

// Send null to clear the metadata
await sdk.entityUsers.update(user.user_id, { metadata: null }, { entity_id: entity.id });

The same update call changes the role, the metadata, or both. Metadata is replaced as a whole, not merged, and sending metadata: null clears it. It is available for your account’s white-label users.

4. Issue a short-lived embed token on every page load:

Generate embed tokentypescript
// title: Issue a short-lived embed token
// Call this from your backend on every page load; ttl is in seconds (300-86400)
const embedToken = await sdk.entityUsers.generateEntityUserToken(user.user_id, { ttl: 900 }, { entity_id: entity.id });

Pass ttl to the same token endpoint to get a short-lived embed token that lasts ttl seconds (300 to 86400). Without ttl the endpoint returns the one-year SSO token. The embed token cannot create other credentials, manage passkeys, two-factor authentication or till operator PINs, or delete the account, and it cannot be extended: issue a new one when it expires. To use it in the embedded UI, see Per-user tokens.

Key Points

  • Role-based access — Control what each user can do
  • Team collaboration — Multiple users per entity with different roles
  • User management — Users have Space Invoices accounts
  • Cross-entity access — One user can access multiple entities

Integration Flow

User authentication flow
┌──────────────┐     ┌─────────────────┐     ┌──────────────┐
│   User       │     │   Your App      │     │    Space     │
│   Logs In    │────▶│   Backend       │────▶│   Invoices   │
└──────────────┘     └─────────────────┘     └──────────────┘
                            │                       │
                            │  1. Generate token    │
                            │─────────────────────▶│
                            │                       │
                            │  2. Redirect to embed │
                            │◀─────────────────────│
                            │                       │
                            │  3. User accesses UI  │
                            │─────────────────────▶│
                            │                       │

Choosing the Right Approach

ScenarioRecommended
Simple white-label dashboard with server-brokered accessEntity API Key Access
Multiple team members need accessUser-Based Access
Different permission levels neededUser-Based Access
Minimal setup, fast integrationEntity API Key Access
Users need to access multiple entitiesUser-Based Access
Automated systems (no UI)Entity API Keys for API calls

Next Steps