Sandbox Testing

Test the full incorporation flow without real payments or admin actions

The sandbox environment allows you to test the complete entity incorporation flow without processing real payments or waiting for admin actions. Use test API keys (sk_test_*) to access sandbox features.

Isolated Environment

Test data is separate from production

Simulate Payments

Mark entities as paid without real charges

Control Status

Transition through any status for testing

Test vs Live API Keys

Key TypePrefixUse Case
Test Keysk_test_Development, testing, sandbox endpoints
Live Keysk_live_Production, real entities, actual payments

Sandbox endpoints require test keys

The /sandbox/* endpoints will return a 403 error if called with a live API key. This prevents accidental use in production.

Complete Test Flow

Here's how to test the full incorporation lifecycle using sandbox endpoints:

1

Create entity

Use the standard POST /entities endpoint with a test key — returns a draft with no invoice yet

2

Add required data

Add parties, documents, and any required information

3

Issue invoice

Call POST /entities/{id}/invoice to create the incorporation invoice and get an invoiceId

4

Simulate payment

Call POST /sandbox/invoices/{invoiceId}/pay using the invoiceId from the invoice step

5

Submit for review

Call POST /entities/{id}/submit (or it auto-submits on payment if pending_submission was set)

6

Simulate admin actions

Use POST /entities/{id}/sandbox/set-status to transition through statuses

7

Test feedback loop

Set status to returned_for_changes, respond to feedback, resubmit

8

Complete incorporation

Set status to incorporated with company number and date

Sandbox Endpoints

Allowed Status Values

StatusDescriptionAdditional Fields
submitted_for_reviewEntity submitted and awaiting review-
in_reviewAdmin is reviewing the entity-
submitted_to_cspSubmitted to Corporate Service Provider-
returned_for_changesReturned with feedback requiring responsefeedback_message (optional)
incorporatedSuccessfully incorporatedcompany_number, incorp_date

Example: Full Test Flow

Complete test flow example
const API_KEY = 'sk_test_your_test_key';
const BASE_URL = 'https://app.entityengine.io/api/v1';

async function testIncorporationFlow() {
  // 1. Create entity
  const entity = await fetch(`${BASE_URL}/entities`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      jurisdiction_product_id: 'jp_abc123',
      name: 'Test Company Ltd'
    })
  }).then(r => r.json());
  
  const entityId = entity.data.id;
  console.log('Created entity:', entityId, '— status:', entity.data.status); // "draft"

  // 2. Add a director (simplified - add all required data in real tests)
  await fetch(`${BASE_URL}/entities/${entityId}/parties`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      party_type: 'person',
      first_name: 'John',
      last_name: 'Smith',
      roles: ['director', 'shareholder', 'ubo'],
      date_of_birth: '1985-03-15',
      nationality: 'US',
      address: {
        street1: '123 Test Street',
        city: 'New York',
        country: 'US',
        postcode: '10001'
      }
    })
  });

  // 3. Issue the incorporation invoice (draft entities have no invoice until this call)
  const invoiceResp = await fetch(`${BASE_URL}/entities/${entityId}/invoice`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({}) // omit payment_method — sandbox doesn't support hosted checkout
  }).then(r => r.json());

  const invoiceId = invoiceResp.data.invoice.id;
  console.log('Invoice created:', invoiceId);

  // 4. Simulate payment
  const payment = await fetch(`${BASE_URL}/sandbox/invoices/${invoiceId}/pay`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }).then(r => r.json());
  
  console.log('Payment simulated:', payment.data.payment_status);

  // 5. Submit for review
  const submission = await fetch(`${BASE_URL}/entities/${entityId}/submit`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }).then(r => r.json());
  
  console.log('Submitted:', submission.data.status);

  // 6. Simulate admin returning for changes
  await fetch(`${BASE_URL}/entities/${entityId}/sandbox/set-status`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      status: 'returned_for_changes',
      feedback_message: 'Please provide proof of address for the director.'
    })
  });

  // 7. Get feedback and respond
  const feedback = await fetch(`${BASE_URL}/entities/${entityId}/feedback`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }).then(r => r.json());

  const feedbackId = feedback.data.feedback_items[0].id;
  
  await fetch(`${BASE_URL}/entities/${entityId}/feedback/${feedbackId}/responses`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      message: 'I have uploaded the proof of address document.'
    })
  });

  // 8. Resubmit
  await fetch(`${BASE_URL}/entities/${entityId}/submit`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  // 9. Simulate incorporation
  const incorporated = await fetch(`${BASE_URL}/entities/${entityId}/sandbox/set-status`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      status: 'incorporated',
      company_number: 'TEST-12345678',
      incorp_date: '2024-01-20'
    })
  }).then(r => r.json());

  console.log('Incorporated!', incorporated.data);
}

testIncorporationFlow();

Webhooks in Sandbox

Sandbox actions fire real webhooks to your registered endpoints. This allows you to test your webhook handlers with realistic payloads. Sandbox webhooks include a sandbox_simulated: true flag in the payload.

Test webhooks separately

Create separate webhook endpoints for test and live environments, or filter by the sandbox_simulated flag in your handler.