Accounts
Accounts
Section titled “Accounts”Accounts represent customer accounts in multi-tenant applications. Each account can have multiple integrations and is identified by a unique remote_id that maps to your system’s user/tenant identifier.
Overview
Section titled “Overview”The Accounts API enables:
- Multi-tenant Architecture: Manage multiple customer accounts
- Account-scoped Integrations: Each account has its own integrations
- Remote ID Mapping: Map Gateway accounts to your system’s identifiers
- Intent Token Generation: Create account-scoped authorization tokens
Account Structure
Section titled “Account Structure”{ "id": 1, "remote_id": "myapp_tenant_12345", "name": "Acme Corporation", "created_at": "2024-01-15T10:30:00.000000Z", "updated_at": "2024-01-15T10:30:00.000000Z"}Fields
Section titled “Fields”| Field | Type | Description |
|---|---|---|
id | integer | Gateway internal account ID |
remote_id | string | Your system’s unique identifier (e.g., myapp_12345) |
name | string | Account display name |
email | string | Account contact email |
created_at | timestamp | Account creation time (ISO 8601) |
updated_at | timestamp | Last update time (ISO 8601) |
List Accounts
Section titled “List Accounts”Retrieve all accounts in your application.
Endpoint
Section titled “Endpoint”GET /api/2.0/app/accountsAuthentication
Section titled “Authentication”- Required Scope:
app:account-read
Request
Section titled “Request”GET https://<GATEWAY_URL>/api/2.0/app/accountsAuthorization: Bearer YOUR_ACCESS_TOKENAccept: application/jsonQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
per_page | integer | 15 | Items per page (max: 100) |
Response
Section titled “Response”Status: 200 OK
{ "data": [ { "id": 1, "remote_id": "myapp_tenant_001", "name": "Acme Corporation", "created_at": "2024-01-15T10:30:00.000000Z", "updated_at": "2024-01-15T10:30:00.000000Z" }, { "id": 2, "remote_id": "myapp_tenant_002", "name": "Tech Solutions Inc", "created_at": "2024-01-16T14:20:00.000000Z", "updated_at": "2024-01-16T14:20:00.000000Z" } ], "meta": { "current_page": 1, "from": 1, "to": 2, "per_page": 15, "total": 2, "last_page": 1 }, "links": { "first": "https://<GATEWAY_URL>/api/2.0/app/accounts?page=1", "last": "https://<GATEWAY_URL>/api/2.0/app/accounts?page=1", "prev": null, "next": null }}Example: cURL
Section titled “Example: cURL”curl -X GET https://<GATEWAY_URL>/api/2.0/app/accounts \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json"Example: PHP
Section titled “Example: PHP”use Illuminate\Support\Facades\Http;
$response = Http::withToken($accessToken) ->get('https://<GATEWAY_URL>/api/2.0/app/accounts', [ 'per_page' => 25 ]);
$accounts = $response->json()['data'];
foreach ($accounts as $account) { echo "Account: {$account['name']} ({$account['remote_id']})\n";}Example: JavaScript
Section titled “Example: JavaScript”const axios = require('axios');
async function listAccounts(page = 1, perPage = 15) { const response = await axios.get('https://<GATEWAY_URL>/api/2.0/app/accounts', { headers: { 'Authorization': `Bearer ${accessToken}` }, params: { page, per_page: perPage } });
return response.data;}
const { data: accounts, meta } = await listAccounts();console.log(`Total accounts: ${meta.total}`);Get Account
Section titled “Get Account”Retrieve a specific account by its remote_id.
Endpoint
Section titled “Endpoint”GET /api/2.0/app/accounts/{remote_id}Authentication
Section titled “Authentication”- Required Scope:
app:account-read
Request
Section titled “Request”GET https://<GATEWAY_URL>/api/2.0/app/accounts/myapp_tenant_12345Authorization: Bearer YOUR_ACCESS_TOKENAccept: application/jsonResponse
Section titled “Response”Status: 200 OK
{ "data": { "id": 1, "remote_id": "myapp_tenant_12345", "name": "Acme Corporation", "created_at": "2024-01-15T10:30:00.000000Z", "updated_at": "2024-01-15T10:30:00.000000Z" }}Error Responses
Section titled “Error Responses”404 Not Found:
{ "message": "No query results for model [App\\Models\\Account]."}Example: cURL
Section titled “Example: cURL”curl -X GET https://<GATEWAY_URL>/api/2.0/app/accounts/myapp_tenant_12345 \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json"Create Account
Section titled “Create Account”Create a new account in the Gateway.
Endpoint
Section titled “Endpoint”POST /api/2.0/app/accountsAuthentication
Section titled “Authentication”- Required Scope:
app:account-create
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
remote_id | string | ✅ Yes | Unique identifier in your system |
name | string | ✅ Yes | Account display name |
email | string | ✅ Yes | Contact email (must be valid email format) |
[!IMPORTANT] The
remote_idmust be unique across all accounts. We recommend using a prefix likemyapp_{your_tenant_id}.
Request
Section titled “Request”POST https://<GATEWAY_URL>/api/2.0/app/accountsAuthorization: Bearer YOUR_ACCESS_TOKENContent-Type: application/json
{ "remote_id": "myapp_tenant_12345", "name": "Acme Corporation",}Response
Section titled “Response”Status: 201 Created
{ "data": { "id": 1, "remote_id": "myapp_tenant_12345", "name": "Acme Corporation", "created_at": "2024-01-15T10:30:00.000000Z", "updated_at": null }}Validation Errors
Section titled “Validation Errors”422 Unprocessable Entity:
{ "message": "The given data was invalid.", "errors": { "remote_id": ["The remote id has already been taken."], "email": ["The email must be a valid email address."], "name": ["The name field is required."] }}Example: cURL
Section titled “Example: cURL”curl -X POST https://<GATEWAY_URL>/api/2.0/app/accounts \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "remote_id": "myapp_tenant_12345", "name": "Acme Corporation", "email": "[email protected]" }'Example: PHP
Section titled “Example: PHP”use Illuminate\Support\Facades\Http;
$account = Http::withToken($accessToken) ->post('https://<GATEWAY_URL>/api/2.0/app/accounts', [ 'remote_id' => 'myapp_tenant_' . $tenantId, 'name' => $tenantName, 'email' => $tenantEmail, ]) ->json()['data'];
echo "Created account: {$account['id']}\n";Example: JavaScript
Section titled “Example: JavaScript”async function createAccount(remoteId, name, email) { const response = await axios.post( 'https://<GATEWAY_URL>/api/2.0/app/accounts', { remote_id: remoteId, name, email }, { headers: { 'Authorization': `Bearer ${accessToken}` } } );
return response.data.data;}
console.log(`Account created: ${account.id}`);Update Account
Section titled “Update Account”Update an existing account.
Endpoint
Section titled “Endpoint”PUT /api/2.0/app/accounts/{account_id}Authentication
Section titled “Authentication”- Required Scope:
app:account-update
Request Body
Section titled “Request Body”All fields are optional - only send fields you want to update:
| Field | Type | Description |
|---|---|---|
name | string | Update account name |
email | string | Update contact email |
[!NOTE] The
remote_idcannot be changed after account creation.
Request
Section titled “Request”PUT https://<GATEWAY_URL>/api/2.0/app/accounts/1Authorization: Bearer YOUR_ACCESS_TOKENContent-Type: application/json
{ "name": "Acme Corp (Updated)",}Response
Section titled “Response”Status: 200 OK
{ "data": { "id": 1, "remote_id": "myapp_tenant_12345", "name": "Acme Corp (Updated)", "created_at": "2024-01-15T10:30:00.000000Z", "updated_at": "2024-01-20T15:45:00.000000Z" }}Example: cURL
Section titled “Example: cURL”curl -X PUT https://<GATEWAY_URL>/api/2.0/app/accounts/1 \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Acme Corp (Updated)"}'Common Use Cases
Section titled “Common Use Cases”1. Sync Accounts from Your System
Section titled “1. Sync Accounts from Your System”// Sync accounts when tenants are created in your apppublic function createTenant(array $data){ // Create tenant in your database $tenant = Tenant::create($data);
// Create corresponding account in Gateway $gatewayAccount = Http::withToken($this->getGatewayToken()) ->post('https://<GATEWAY_URL>/api/2.0/app/accounts', [ 'remote_id' => 'myapp_' . $tenant->id, 'name' => $tenant->name, 'email' => $tenant->email, ]) ->json()['data'];
// Store Gateway account ID $tenant->update(['gateway_account_id' => $gatewayAccount['id']]);
return $tenant;}2. Get Account Before Creating Intent Token
Section titled “2. Get Account Before Creating Intent Token”// Verify account exists before generating intent tokenasync function getAccountIntent(remoteId) { // Get account const accountResponse = await axios.get( `https://<GATEWAY_URL>/api/2.0/app/accounts/${remoteId}`, { headers: { 'Authorization': `Bearer ${accessToken}` } } );
if (!accountResponse.data.data) { throw new Error('Account not found'); }
// Generate intent token for this account const intentResponse = await axios.post( `https://<GATEWAY_URL>/api/2.0/app/intent/${remoteId}`, { scopes: ['webcomponent:integration-read', 'webcomponent:integration-event'] }, { headers: { 'Authorization': `Bearer ${accessToken}` } } );
return intentResponse.data.data.token;}3. List Accounts with Pagination
Section titled “3. List Accounts with Pagination”def get_all_accounts(base_url: str, token: str) -> list: """Fetch all accounts across all pages.""" all_accounts = [] page = 1
while True: response = requests.get( f'{base_url}/api/2.0/app/accounts', headers={'Authorization': f'Bearer {token}'}, params={'page': page, 'per_page': 100} ) data = response.json()
all_accounts.extend(data['data'])
if page >= data['meta']['last_page']: break
page += 1
return all_accountsBest Practices
Section titled “Best Practices”1. Use Meaningful Remote IDs
Section titled “1. Use Meaningful Remote IDs”✅ Good: myapp_tenant_12345, shopify_store_abc123
❌ Avoid: 12345, user123
2. Handle Duplicate Remote IDs
Section titled “2. Handle Duplicate Remote IDs”async function createOrGetAccount(remoteId, name, email) { try { // Try to create const response = await axios.post(url, { remote_id: remoteId, name, email }); return response.data.data; } catch (error) { if (error.response?.status === 422 && error.response.data.errors?.remote_id) { // Account already exists, fetch it const getResponse = await axios.get(`${url}/${remoteId}`); return getResponse.data.data; } throw error; }}3. Validate Email Format
Section titled “3. Validate Email Format”Ensure emails are valid before creating accounts:
$validatedAccount = $request->validate([ 'remote_id' => 'required|string|max:255', 'name' => 'required|string|max:255', 'email' => 'required|email|max:255',]);4. Store Gateway Account ID
Section titled “4. Store Gateway Account ID”Map Gateway account IDs to your tenant records:
ALTER TABLE tenants ADD COLUMN gateway_account_id INT;ALTER TABLE tenants ADD COLUMN gateway_remote_id VARCHAR(255);