feat(authentication): enable platform merchant API Key authentication for org-level operations
Type of Change
- [ ] Bugfix
- [x] New feature
- [x] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD
Description
This PR enables authenticated access for platform merchants via their API key to perform the following operations:
Merchant Account Operations
- Create standard merchant accounts within the platform org
- List merchant accounts
- Retrieve a specific merchant account
- Update a merchant account
API Key Operations
- Create an API key for a standard merchant
- List API keys for a standard merchant
- Retrieve an API Key
- Update an API key
- Revoke an API key
Organization Operations
- Retrieve organization details
- Update organization details
Analytics (Organization level)
- Metrics
- Filters
All of the above have strict org-matching checks to ensure platform merchants can only access resources within their organization.
Introduced and integrated new auth flows to enforce this behavior:
PlatformOrgAdminAuth– For org-scoped APIs (e.g., merchant list, org update)PlatformOrgAdminAuthWithMerchantIdFromRoute– For APIs scoped by merchant path param- Enhanced
JWTAuthOrganizationFromRoute– Validates org_id in token matches path param
Each of these flows:
- Validates platform merchant identity and scope
- Ensures cross-org access is prevented
- Supports fallback to Admin API Key when
is_admin_auth_allowedis set (and also fallback merchant API key, if configured)
MerchantAccountType:
- Added
MerchantAccountTypefield inMerchantAccountResponse
Additional Changes
- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables
Motivation and Context
Platform merchants are intended to manage and orchestrate multiple standard merchant accounts under a single organization. However, until now, they couldn't interact with many core APIs using their own API key — including merchant management, organization operations, API key handling, and analytics access.
How did you test it?
Merchant Account APIs
1. Create Merchant
Request:
curl --location 'http://localhost:8080/accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_30M0S1Q1phnSUXWbRmvSScAdShlCwLrqDYby1jCuc2tHXsstIvPRo5qy7Q65RJJO' \
--data-raw '{
"merchant_id": "merchant_1748354786",
"locker_id": "m0010",
"merchant_name": "Platform API Merchant",
"merchant_details": {
"primary_contact_person": "John Test",
"primary_email": "[email protected]",
"primary_phone": "sunt laborum",
"secondary_contact_person": "John Test2",
"secondary_email": "[email protected]",
"secondary_phone": "cillum do dolor id",
"website": "https://www.example.com",
"about_business": "Online Retail with a wide selection of organic products for North America",
"address": {
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"city": "San Fransico",
"state": "California",
"zip": "94122",
"country": "US",
"first_name":"john",
"last_name":"Doe"
}
},
"organization_id": "org_CfdN8ia42BzMUrjbYNiM",
"return_url": "https://google.com/success",
"webhook_details": {
"webhook_version": "1.0.1",
"webhook_username": "ekart_retail",
"webhook_password": "password_ekart@123",
"webhook_url":"https://webhook.site",
"payment_created_enabled": true,
"payment_succeeded_enabled": true,
"payment_failed_enabled": true
},
"sub_merchants_enabled": false,
"parent_merchant_id":"merchant_123",
"metadata": {
"city": "NY",
"unit": "245"
},
"primary_business_details": [
{
"country": "US",
"business": "default"
}
]
}'
Expected Response:
{
"merchant_id": "merchant_1748339362",
"merchant_name": "Platform API Merchant",
"return_url": "https://google.com/success",
"enable_payment_response_hash": true,
"payment_response_hash_key": "ha1Rq2nQSzcCnEy3FBLKtnwPg8yc9RjMmyZboGNSEKJwKMM81K8CYXqJNWJKrp5E",
"redirect_to_merchant_with_http_post": false,
"merchant_details": {
"primary_contact_person": "John Test",
"primary_phone": "sunt laborum",
"primary_email": "[email protected]",
"secondary_contact_person": "John Test2",
"secondary_phone": "cillum do dolor id",
"secondary_email": "[email protected]",
"website": "https://www.example.com",
"about_business": "Online Retail with a wide selection of organic products for North America",
"address": {
"city": "San Fransico",
"country": "US",
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"zip": "94122",
"state": "California",
"first_name": "john",
"last_name": "Doe"
}
},
"webhook_details": {
"webhook_version": "1.0.1",
"webhook_username": "ekart_retail",
"webhook_password": "password_ekart@123",
"webhook_url": "https://webhook.site",
"payment_created_enabled": true,
"payment_succeeded_enabled": true,
"payment_failed_enabled": true
},
"payout_routing_algorithm": null,
"sub_merchants_enabled": false,
"parent_merchant_id": null,
"publishable_key": "pk_dev_d8aba9f251c44ba8bda28d7b48103125",
"metadata": {
"city": "NY",
"unit": "245",
"compatible_connector": null
},
"locker_id": "m0010",
"primary_business_details": [
{
"country": "US",
"business": "default"
}
],
"frm_routing_algorithm": null,
"organization_id": "org_CfdN8ia42BzMUrjbYNiM",
"is_recon_enabled": false,
"default_profile": "pro_iM8KYK4hLNSanTF8CFPR",
"recon_status": "not_requested",
"pm_collect_link_config": null,
"product_type": "orchestration",
"merchant_account_type": "connected"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 1.1 | Platform API Key (same org) | Merchant created |
| 1.2 | Platform API Key (different org) | Unauthorized |
| 1.3 | Admin API Key | Merchant created |
| 1.4 | Fallback API Key (config) | Merchant created |
| 1.5 | Any other case | Unauthorized |
2. List Merchants
Request:
curl --location 'http://localhost:8080/accounts/list?organization_id=org_CfdN8ia42BzMUrjbYNiM' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Merchant-Id: merchant_1748247188' \
--header 'api-key: test_admin' \
--data ''
Expected Response:
[
{
"merchant_id": "merchant_1748339023",
"merchant_name": "Hyperswitch",
"return_url": null,
"enable_payment_response_hash": true,
"payment_response_hash_key": "Y6pZAHKZCteIlcLlvPVKpj4auwVMOUyp4Gl5P3HSMCsE0W71XsqZNgjlfHInswrN",
"redirect_to_merchant_with_http_post": false,
"merchant_details": null,
"webhook_details": null,
"payout_routing_algorithm": null,
"sub_merchants_enabled": false,
"parent_merchant_id": null,
"publishable_key": "pk_dev_9a085084db3943589d04e596c790e2a2",
"metadata": null,
"locker_id": null,
"primary_business_details": [],
"frm_routing_algorithm": null,
"organization_id": "org_CfdN8ia42BzMUrjbYNiM",
"is_recon_enabled": false,
"default_profile": "pro_mky2SQ3h1hmmUDkVxlVU",
"recon_status": "not_requested",
"pm_collect_link_config": null,
"product_type": "orchestration",
"merchant_account_type": "platform"
},
{
"merchant_id": "merchant_1748339074",
"merchant_name": "Admin Merchant",
"return_url": "https://google.com/success",
"enable_payment_response_hash": true,
"payment_response_hash_key": "3LoplBmFLLUIysEIr8o4FRQF2lT2bfBpsmtNZNCat7A9SV8gEUGDTV2dznCrXNqJ",
"redirect_to_merchant_with_http_post": false,
"merchant_details": {
"primary_contact_person": "John Test",
"primary_phone": "sunt laborum",
"primary_email": "[email protected]",
"secondary_contact_person": "John Test2",
"secondary_phone": "cillum do dolor id",
"secondary_email": "[email protected]",
"website": "https://www.example.com",
"about_business": "Online Retail with a wide selection of organic products for North America",
"address": {
"city": "San Fransico",
"country": "US",
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"zip": "94122",
"state": "California",
"first_name": "john",
"last_name": "Doe"
}
},
"webhook_details": {
"webhook_version": "1.0.1",
"webhook_username": "ekart_retail",
"webhook_password": "password_ekart@123",
"webhook_url": "https://webhook.site",
"payment_created_enabled": true,
"payment_succeeded_enabled": true,
"payment_failed_enabled": true
},
"payout_routing_algorithm": null,
"sub_merchants_enabled": false,
"parent_merchant_id": null,
"publishable_key": "pk_dev_844d5c1dbe96424784c30ef393e76619",
"metadata": {
"city": "NY",
"unit": "245",
"compatible_connector": null
},
"locker_id": "m0010",
"primary_business_details": [
{
"country": "US",
"business": "default"
}
],
"frm_routing_algorithm": null,
"organization_id": "org_CfdN8ia42BzMUrjbYNiM",
"is_recon_enabled": false,
"default_profile": "pro_mwDaCNBw8LirhyMZGf1B",
"recon_status": "not_requested",
"pm_collect_link_config": null,
"product_type": "orchestration",
"merchant_account_type": "connected"
}
]
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 2.1 | Platform API Key + matching org_id in query |
Merchant list returned |
| 2.2 | Platform API Key + mismatched org_id |
Unauthorized |
| 2.3 | Admin API Key + any org_id |
Merchant list returned |
| 2.4 | Fallback API Key (config) | Merchant list returned |
| 2.5 | JWT + matching org_id in query |
Merchant list returned |
| 2.6 | JWT + mismatched org_id |
InvalidJwtToken |
| 2.7 | Any other case | Unauthorized |
3. Retrieve Merchant
Request:
curl --location 'http://localhost:8080/accounts/merchant_1748247055' \
--header 'Accept: application/json' \
--header 'api-key: test_admin'
Expected Response:
{
"merchant_id": "merchant_1748247055",
"merchant_name": "Connected JWT",
"return_url": null,
"enable_payment_response_hash": true,
"payment_response_hash_key": "R214M17EUqiZyDbkP3Slv5sB8WVLUHONaYm3Ly6YOfPPYzdiqgvCi6LOMVzNmi6p",
"redirect_to_merchant_with_http_post": false,
"merchant_details": null,
"webhook_details": null,
"payout_routing_algorithm": null,
"sub_merchants_enabled": false,
"parent_merchant_id": null,
"publishable_key": "pk_dev_7c64347723494ab1ad56df8180385bdd",
"metadata": null,
"locker_id": null,
"primary_business_details": [],
"frm_routing_algorithm": null,
"organization_id": "org_l8ol6KqrQ5eaHBPwZ2V3",
"is_recon_enabled": false,
"default_profile": "pro_rOryKpNr5QUEynTrT0TD",
"recon_status": "not_requested",
"pm_collect_link_config": null,
"product_type": "orchestration",
"merchant_account_type": "connected"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 3.1 | Platform API Key + merchant from same org | Merchant retrieved |
| 3.2 | Platform API Key + merchant from different org | Unauthorized |
| 3.3 | Admin API Key | Merchant retrieved |
| 3.4 | Fallback API Key (config) | Merchant retrieved |
| 3.5 | JWT + merchant_id in org |
Merchant retrieved |
| 3.6 | JWT + mismatched merchant_id or org |
InvalidJwtToken |
| 3.7 | Any other case | Unauthorized |
4. Update Merchant
Request:
curl --location 'http://localhost:8080/accounts/merchant_1748244954' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cW7LmHwdGurYUqCHLMkUX8AfU9uYzKJc6sT0bsAB1wQJFe6lOP01lRO30Dj0WpcH' \
--data-raw '{
"merchant_id": "merchant_1744225676",
"locker_id": "m0010",
"merchant_name": "Platform Merchant",
"merchant_details": {
"primary_contact_person": "John Test",
"primary_email": "[email protected]",
"primary_phone": "sunt laborum",
"secondary_contact_person": "John Test2",
"secondary_email": "[email protected]",
"secondary_phone": "cillum do dolor id",
"website": "https://www.example.com",
"about_business": "Online Retail with a wide selection of organic products for North America",
"address": {
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"city": "San Fransico",
"state": "California",
"zip": "94122",
"country": "US",
"first_name":"john",
"last_name":"Doe"
}
},
"return_url": "https://google.com/success",
"webhook_details": {
"webhook_version": "1.0.1",
"webhook_username": "ekart_retail",
"webhook_password": "password_ekart@123",
"webhook_url":"https://webhook.site",
"payment_created_enabled": true,
"payment_succeeded_enabled": true,
"payment_failed_enabled": true
},
"sub_merchants_enabled": false,
"parent_merchant_id":"merchant_123",
"metadata": {
"city": "NY",
"unit": "245"
},
"primary_business_details": [
{
"country": "US",
"business": "default"
}
]
}'
Expected Response:
{
"merchant_id": "merchant_1748244954",
"merchant_name": "Platform Merchant",
"return_url": "https://google.com/success",
"enable_payment_response_hash": true,
"payment_response_hash_key": "1zbZFZFo6yrsd44wwMjzaFC3GlLCxAPWhPYlGcWu7GSzDblhl4g8tRl2EdDTRpke",
"redirect_to_merchant_with_http_post": false,
"merchant_details": {
"primary_contact_person": "John Test",
"primary_phone": "sunt laborum",
"primary_email": "[email protected]",
"secondary_contact_person": "John Test2",
"secondary_phone": "cillum do dolor id",
"secondary_email": "[email protected]",
"website": "https://www.example.com",
"about_business": "Online Retail with a wide selection of organic products for North America",
"address": {
"city": "San Fransico",
"country": "US",
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"zip": "94122",
"state": "California",
"first_name": "john",
"last_name": "Doe"
}
},
"webhook_details": {
"webhook_version": "1.0.1",
"webhook_username": "ekart_retail",
"webhook_password": "password_ekart@123",
"webhook_url": "https://webhook.site",
"payment_created_enabled": true,
"payment_succeeded_enabled": true,
"payment_failed_enabled": true
},
"payout_routing_algorithm": null,
"sub_merchants_enabled": false,
"parent_merchant_id": null,
"publishable_key": "pk_dev_9a9589f79f664920bb63c5ca1a5448cd",
"metadata": {
"city": "NY",
"unit": "245"
},
"locker_id": "m0010",
"primary_business_details": [
{
"country": "US",
"business": "default"
}
],
"frm_routing_algorithm": null,
"organization_id": "org_l8ol6KqrQ5eaHBPwZ2V3",
"is_recon_enabled": false,
"default_profile": null,
"recon_status": "not_requested",
"pm_collect_link_config": null,
"product_type": "orchestration"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 4.1 | Platform API Key + merchant from same org | Merchant updated |
| 4.2 | Platform API Key + merchant from different org | Unauthorized |
| 4.3 | Admin API Key | Merchant updated |
| 4.4 | Fallback API Key (config) | Merchant updated |
| 4.5 | JWT + merchant_id in org |
Merchant updated |
| 4.6 | JWT + mismatched merchant_id or org |
InvalidJwtToken |
| 4.7 | Any other case | Unauthorized |
API Key APIs
5. Create API Key
Request:
curl --location 'http://localhost:8080/api_keys/merchant_1748339362' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_30M0S1Q1phnSUXWbRmvSScAdShlCwLrqDYby1jCuc2tHXsstIvPRo5qy7Q65RJJO' \
--data '{
"name": "Nike API Key 2",
"description": null,
"expiration": "2038-01-19T03:14:08.000Z"
}'
Expected Response:
{
"key_id": "dev_nNAgIKTXitQ6BcLVZae5",
"merchant_id": "merchant_1748339362",
"name": "Nike API Key 2",
"description": null,
"api_key": "dev_3CaIJZiLTY7lVafRs9atnxAPrHREm4yauTrvhQD8Y44KwwXCbu25fIm64QEGbCz2",
"created": "2025-05-27T09:49:50.936Z",
"expiration": "2038-01-19T03:14:08.000Z"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 5.1 | Platform API Key + merchant from same org | API Key created |
| 5.2 | Platform API Key + merchant from different org | Unauthorized |
| 5.3 | Admin API Key | API Key created |
| 5.4 | Fallback API Key (config) | API Key created |
| 5.5 | JWT + merchant_id in org |
API Key created |
| 5.6 | JWT + merchant in different org | Forbidden / InvalidJwtToken |
| 5.7 | Any other case | Unauthorized |
6. List API Keys
Request:
curl --location 'http://localhost:8080/api_keys/merchant_1748252478/list' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_1jmsnLQvYEan1qFCxMxNhMbT8xre9LvGJbiRzS90ZyBHO3d9smCbdNg0MjBWMroP'
Expected Response:
[
{
"key_id": "dev_Upyxxd2nyxZ6ptIe70zE",
"merchant_id": "merchant_1748252478",
"name": "Nike API Key 2",
"description": null,
"prefix": "dev_nRxdo8Wu",
"created": "2025-05-26T10:58:25.475Z",
"expiration": "2038-01-19T03:14:08.000Z"
},
{
"key_id": "dev_PxEjbjfyf1qykaMd7s7l",
"merchant_id": "merchant_1748252478",
"name": "Nike API Key 2",
"description": null,
"prefix": "dev_f9MG2CJf",
"created": "2025-05-26T10:58:30.545Z",
"expiration": "2038-01-19T03:14:08.000Z"
}
]
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 6.1 | Platform API Key + merchant from same org | API Keys listed |
| 6.2 | Platform API Key + merchant from different org | Unauthorized |
| 6.3 | Admin API Key | API Keys listed |
| 5.4 | Fallback API Key (config) | API Keys listed |
| 6.5 | JWT + matching merchant & permission | API Keys listed |
| 6.6 | JWT + merchant in different org | InvalidJwtToken or Forbidden |
| 6.7 | Any other case | Unauthorized |
7. Retrieve API Key
Request:
curl --location 'http://localhost:8080/api_keys/merchant_1748339362/dev_uHMMaVMYseYOLfhZrNEL' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin'
Expected Response:
{
"key_id": "dev_uHMMaVMYseYOLfhZrNEL",
"merchant_id": "merchant_1748339362",
"name": "Nike API Key 2",
"description": null,
"prefix": "dev_wKJ5D5LU",
"created": "2025-05-27T14:15:16.455Z",
"expiration": "2038-01-19T03:14:08.000Z"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 7.1 | Platform API Key + merchant from same org | API Key retrieved |
| 7.2 | Platform API Key + merchant from different org | Unauthorized |
| 7.3 | Admin API Key | API Key retrieved |
| 7.4 | Fallback API Key (config) | API Key retrieved |
| 7.5 | JWT + matching merchant & permission | API Key retrieved |
| 7.6 | JWT + merchant in different org | InvalidJwtToken or Forbidden |
| 7.7 | Any other case | Unauthorized |
8. Update API Key
Request:
curl --location 'http://localhost:8080/api_keys/merchant_1748252478/dev_b7kajJZbITKra0FdwDne' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2Y1ZTMwYjMtOTZkMi00YWJkLWJlMzMtYjhmOGFlOWRiMmZkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4MjUyNDc4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0ODQyOTg2NSwib3JnX2lkIjoib3JnX2w4b2w2S3FyUTVlYUhCUHdaMlYzIiwicHJvZmlsZV9pZCI6InByb19yM0R3VlVHUnZaVExZWEx5eHZkZSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ElVIJMr7-FPkW3N3h_cVyrOxEh4q1_u94KHVdVnJQ9g' \
--data '{
"name": "Test API Key 3",
"description": "My very awesome API key",
"expiration": null
}'
Expected Response:
{
"key_id": "dev_b7kajJZbITKra0FdwDne",
"merchant_id": "merchant_1748252478",
"name": "Test API Key 3",
"description": "My very awesome API key",
"prefix": "dev_5m97MTk0",
"created": "2025-05-26T10:59:56.935Z",
"expiration": "2038-01-19T03:14:08.000Z"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 8.1 | Platform API Key + merchant from same org | API Key updated |
| 8.2 | Platform API Key + merchant from different org | Unauthorized |
| 8.3 | Admin API Key | API Key updated |
| 8.4 | Fallback API Key (config) | API Key updated |
| 8.5 | JWT + matching merchant & permission | API Key updated |
| 8.6 | JWT + merchant in different org | InvalidJwtToken or Forbidden |
| 8.7 | Any other case | Unauthorized |
9. Revoke API Key
Request:
curl --location --request DELETE 'http://localhost:8080/api_keys/merchant_1748252478/dev_b7kajJZbITKra0FdwDne' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2Y1ZTMwYjMtOTZkMi00YWJkLWJlMzMtYjhmOGFlOWRiMmZkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4MjUyNDc4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0ODQyOTg2NSwib3JnX2lkIjoib3JnX2w4b2w2S3FyUTVlYUhCUHdaMlYzIiwicHJvZmlsZV9pZCI6InByb19yM0R3VlVHUnZaVExZWEx5eHZkZSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ElVIJMr7-FPkW3N3h_cVyrOxEh4q1_u94KHVdVnJQ9g'
Expected Response:
{
"merchant_id": "merchant_1748339362",
"key_id": "dev_uHMMaVMYseYOLfhZrNEL",
"revoked": true
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 9.1 | Platform API Key + merchant from same org | API Key revoked |
| 9.2 | Platform API Key + merchant from different org | Unauthorized |
| 9.3 | Admin API Key | API Key revoked |
| 9.4 | Fallback API Key (config) | API Key revoked |
| 9.5 | JWT + matching merchant & permission | API Key revoked |
| 9.6 | JWT + merchant in different org | InvalidJwtToken or Forbidden |
| 9.7 | Any other case | Unauthorized |
Organization APIs
10. Retrieve Org
Request:
curl --location 'http://localhost:8080/organization/org_l8ol6KqrQ5eaHBPwZ2V3' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2Y1ZTMwYjMtOTZkMi00YWJkLWJlMzMtYjhmOGFlOWRiMmZkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4MjUyNDI5Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0ODQyOTI2MCwib3JnX2lkIjoib3JnX2w4b2w2S3FyUTVlYUhCUHdaMlYzIiwicHJvZmlsZV9pZCI6InByb19GemFxMVVIdDh5RG5ZUVBOVzlhRSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.TKS85mCJxR0jqMNsYZ7YL4FrwH8K2OOTPp6O_SHdq8w'
Expected Response:
{
"organization_id": "org_l8ol6KqrQ5eaHBPwZ2V3",
"organization_name": "Platform Organization 3",
"organization_details": null,
"metadata": null,
"modified_at": "2025-05-26 10:48:43.380292",
"created_at": "2025-05-26 07:35:54.645102"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 10.1 | Platform API Key | Organization retrieved |
| 10.2 | Platform API Key + different org | Unauthorized |
| 10.3 | Admin API Key | Organization retrieved |
| 10.4 | Fallback API Key (config) | Organization retrieved |
| 10.5 | JWT + matching organization | Organization retrieved |
| 10.6 | JWT + different org | InvalidJwtToken or Forbidden |
| 10.7 | Any other case | Unauthorized |
11. Update Org
Request:
curl --location --request PUT 'http://localhost:8080/organization/org_l8ol6KqrQ5eaHBPwZ2V3' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2Y1ZTMwYjMtOTZkMi00YWJkLWJlMzMtYjhmOGFlOWRiMmZkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4MjUyNDI5Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0ODQyOTI2MCwib3JnX2lkIjoib3JnX2w4b2w2S3FyUTVlYUhCUHdaMlYzIiwicHJvZmlsZV9pZCI6InByb19GemFxMVVIdDh5RG5ZUVBOVzlhRSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.TKS85mCJxR0jqMNsYZ7YL4FrwH8K2OOTPp6O_SHdq8w' \
--data '{
"organization_name": "Platform Organization 3"
}'
Expected Response:
{
"organization_id": "org_l8ol6KqrQ5eaHBPwZ2V3",
"organization_name": "Platform Organization 3",
"organization_details": null,
"metadata": null,
"modified_at": "2025-05-26 10:48:43.380292",
"created_at": "2025-05-26 07:35:54.645102"
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 11.1 | Platform API Key | Organization updated |
| 11.2 | Platform API Key + different org | Unauthorized |
| 11.3 | Admin API Key | Organization updated |
| 11.4 | Fallback API Key (config) | Organization updated |
| 11.5 | JWT + matching organization | Organization updated |
| 11.6 | JWT + different org | InvalidJwtToken or Forbidden |
| 11.7 | Any other case | Unauthorized |
Analytics APIs
12. Payments Metrics
Request:
curl --location 'http://localhost:8080/analytics/v1/org/metrics/payments' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--header 'api-key: dev_cW7LmHwdGurYUqCHLMkUX8AfU9uYzKJc6sT0bsAB1wQJFe6lOP01lRO30Dj0WpcH' \
--data '[
{
"timeRange": {
"startTime": "2025-03-01T18:30:00Z",
"endTime": "2025-05-31T09:22:00Z"
},
"filters": {
"currency": [
"USD"
]
},
"source": "BATCH",
"metrics": [
"payment_success_rate"
],
"timeSeries": {
"granularity": "G_ONEDAY"
},
"delta": true
}
]'
Expected Response:
{
"queryData": [
{
"payment_success_rate": 100.0,
"payment_count": null,
"payment_success_count": null,
"payment_processed_amount": 0,
"payment_processed_amount_in_usd": null,
"payment_processed_count": null,
"payment_processed_amount_without_smart_retries": 0,
"payment_processed_amount_without_smart_retries_usd": null,
"payment_processed_count_without_smart_retries": null,
"avg_ticket_size": null,
"payment_error_message": null,
"retries_count": null,
"retries_amount_processed": 0,
"connector_success_rate": null,
"payments_success_rate_distribution": null,
"payments_success_rate_distribution_without_smart_retries": null,
"payments_success_rate_distribution_with_only_retries": null,
"payments_failure_rate_distribution": null,
"payments_failure_rate_distribution_without_smart_retries": null,
"payments_failure_rate_distribution_with_only_retries": null,
"failure_reason_count": 0,
"failure_reason_count_without_smart_retries": 0,
"currency": null,
"status": null,
"connector": null,
"authentication_type": null,
"payment_method": null,
"payment_method_type": null,
"client_source": null,
"client_version": null,
"profile_id": null,
"card_network": null,
"merchant_id": null,
"card_last_4": null,
"card_issuer": null,
"error_reason": null,
"time_range": {
"start_time": "2025-05-26T00:00:00.000Z",
"end_time": "2025-05-26T23:00:00.000Z"
},
"time_bucket": "2025-05-26 00:00:00"
}
],
"metaData": [
{
"total_payment_processed_amount": 0,
"total_payment_processed_amount_in_usd": null,
"total_payment_processed_amount_without_smart_retries": 0,
"total_payment_processed_amount_without_smart_retries_usd": null,
"total_payment_processed_count": 0,
"total_payment_processed_count_without_smart_retries": 0,
"total_failure_reasons_count": 0,
"total_failure_reasons_count_without_smart_retries": 0
}
]
}
| Scenario | Auth Type | Expected Behavior |
|---|---|---|
| 12.1 | Platform API Key | Access to analytics |
| 12.3 | Admin API Key | Unauthorized |
| 12.4 | Fallback API Key (config) | Unauthorized |
| 12.5 | JWT | Access to analytics |
| 12.7 | Any other case | Unauthorized |
Checklist
- [x] I formatted the code
cargo +nightly fmt --all - [x] I addressed lints thrown by
cargo clippy - [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible