Skip to content

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.

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
{
"id": 1,
"remote_id": "myapp_tenant_12345",
"name": "Acme Corporation",
"email": "[email protected]",
"created_at": "2024-01-15T10:30:00.000000Z",
"updated_at": "2024-01-15T10:30:00.000000Z"
}
FieldTypeDescription
idintegerGateway internal account ID
remote_idstringYour system’s unique identifier (e.g., myapp_12345)
namestringAccount display name
emailstringAccount contact email
created_attimestampAccount creation time (ISO 8601)
updated_attimestampLast update time (ISO 8601)

Retrieve all accounts in your application.

GET /api/2.0/app/accounts
  • Required Scope: app:account-read
GET https://<GATEWAY_URL>/api/2.0/app/accounts
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
ParameterTypeDefaultDescription
pageinteger1Page number
per_pageinteger15Items per page (max: 100)

Status: 200 OK

{
"data": [
{
"id": 1,
"remote_id": "myapp_tenant_001",
"name": "Acme Corporation",
"email": "[email protected]",
"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",
"email": "[email protected]",
"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
}
}
Terminal window
curl -X GET https://<GATEWAY_URL>/api/2.0/app/accounts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
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";
}
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}`);

Retrieve a specific account by its remote_id.

GET /api/2.0/app/accounts/{remote_id}
  • Required Scope: app:account-read
GET https://<GATEWAY_URL>/api/2.0/app/accounts/myapp_tenant_12345
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json

Status: 200 OK

{
"data": {
"id": 1,
"remote_id": "myapp_tenant_12345",
"name": "Acme Corporation",
"email": "[email protected]",
"created_at": "2024-01-15T10:30:00.000000Z",
"updated_at": "2024-01-15T10:30:00.000000Z"
}
}

404 Not Found:

{
"message": "No query results for model [App\\Models\\Account]."
}
Terminal window
curl -X GET https://<GATEWAY_URL>/api/2.0/app/accounts/myapp_tenant_12345 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"

Create a new account in the Gateway.

POST /api/2.0/app/accounts
  • Required Scope: app:account-create
FieldTypeRequiredDescription
remote_idstring✅ YesUnique identifier in your system
namestring✅ YesAccount display name
emailstring✅ YesContact email (must be valid email format)

[!IMPORTANT] The remote_id must be unique across all accounts. We recommend using a prefix like myapp_{your_tenant_id}.

POST https://<GATEWAY_URL>/api/2.0/app/accounts
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"remote_id": "myapp_tenant_12345",
"name": "Acme Corporation",
"email": "[email protected]"
}

Status: 201 Created

{
"data": {
"id": 1,
"remote_id": "myapp_tenant_12345",
"name": "Acme Corporation",
"email": "[email protected]",
"created_at": "2024-01-15T10:30:00.000000Z",
"updated_at": null
}
}

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."]
}
}
Terminal window
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]"
}'
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";
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;
}
const account = await createAccount('myapp_tenant_12345', 'Acme Corporation', '[email protected]');
console.log(`Account created: ${account.id}`);

Update an existing account.

PUT /api/2.0/app/accounts/{account_id}
  • Required Scope: app:account-update

All fields are optional - only send fields you want to update:

FieldTypeDescription
namestringUpdate account name
emailstringUpdate contact email

[!NOTE] The remote_id cannot be changed after account creation.

PUT https://<GATEWAY_URL>/api/2.0/app/accounts/1
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"name": "Acme Corp (Updated)",
"email": "[email protected]"
}

Status: 200 OK

{
"data": {
"id": 1,
"remote_id": "myapp_tenant_12345",
"name": "Acme Corp (Updated)",
"email": "[email protected]",
"created_at": "2024-01-15T10:30:00.000000Z",
"updated_at": "2024-01-20T15:45:00.000000Z"
}
}
Terminal window
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)"}'

// Sync accounts when tenants are created in your app
public 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 token
async 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;
}
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_accounts

Good: myapp_tenant_12345, shopify_store_abc123

Avoid: 12345, user123

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;
}
}

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',
]);

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);