AppDirect Tenant Marketplace Provisioning API
Tenant-owner M2M APIs for marketplace partners (org create, subscription lifecycle, balance top-up, member seats). Requires a tenant-scoped API key from the tenant-owner org.
Tenant-owner M2M APIs for marketplace partners (org create, subscription lifecycle, balance top-up, member seats). Requires a tenant-scoped API key from the tenant-owner org.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/appdirect-tenant-marketplace-provisioning-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
openapi: 3.2.0
info:
description: The Companies API allows developers to manage marketplace companies and their user memberships.
title: Companies AI Embed Tenant Marketplace Provisioning API
license:
name: Apache License, Version 2.0
url: http://www.apache.org/licenses/LICENSE-2.0
version: v296.0-SNAPSHOT
servers:
- url: https://marketplace.appdirect.com/api
- url: https://virtserver.swaggerhub.com
tags:
- name: Tenant Marketplace Provisioning
description: Tenant-owner M2M APIs for marketplace partners (org create, subscription lifecycle, balance top-up, member seats). Requires a tenant-scoped API key from the tenant-owner org.
paths:
/api/v1/tenant/organizations/create:
post:
tags:
- Tenant Marketplace Provisioning
summary: Create tenant organization
description: Creates a child organization under the tenant and returns the org ID and resolved admin user ID. When the tenant has subscription billing management enabled, the org is created without an automatic paid subscription (FREE bootstrap) so step 2 is POST .../subscription. Requires ORG_SETTINGS WRITE with a tenant-scoped API key from the tenant-owner org.
operationId: createTenantOrganization
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTenantOrganizationRequestDto'
responses:
'201':
description: Organization created.
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTenantOrganizationResponseDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/subscription:
get:
tags:
- Tenant Marketplace Provisioning
summary: Get organization subscription
description: Returns the active subscription for the target org. Poll after async create/patch/cancel operations. Reconcile cancellation on cancelledAt (status may remain ACTIVE until period close). Requires ORG_SUBSCRIPTIONS READ.
operationId: getTenantOrgSubscription
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
responses:
'200':
description: Active subscription.
content:
application/json:
schema:
$ref: '#/components/schemas/OrgSubscriptionDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
post:
tags:
- Tenant Marketplace Provisioning
summary: Create organization subscription
description: Starts the subscription-created workflow (202 Accepted, empty body). Requires X-Idempotency-Key. Returns 403 when subscriptionBillingManagementEnabled is false on the tenant. Returns 409 when the org already has an active non-FREE subscription. Replay with the same idempotency key returns 202 again. Requires ORG_SUBSCRIPTIONS WRITE.
operationId: createTenantOrgSubscription
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- $ref: '#/components/parameters/XIdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTenantOrgSubscriptionRequestDto'
responses:
'202':
description: Subscription creation accepted (async workflow).
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
patch:
tags:
- Tenant Marketplace Provisioning
summary: Update organization subscription
description: Updates plan, seats, or external identifiers. Entitlement changes run via async workflow (202, empty body). Trivial field-only edits may return 200 with OrgSubscriptionDto. Requires X-Idempotency-Key and ORG_SUBSCRIPTIONS WRITE. Returns 403 when subscriptionBillingManagementEnabled is false.
operationId: patchTenantOrgSubscription
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- $ref: '#/components/parameters/XIdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchTenantOrgSubscriptionRequestDto'
responses:
'200':
description: Subscription updated synchronously.
content:
application/json:
schema:
$ref: '#/components/schemas/OrgSubscriptionDto'
'202':
description: Subscription change accepted (async workflow).
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
delete:
tags:
- Tenant Marketplace Provisioning
summary: Cancel organization subscription
description: Starts the cancel lifecycle workflow (202 Accepted, empty body). Sets cancelledAt while status may remain ACTIVE until period close. Requires X-Idempotency-Key. Optional request body for provenance metadata. Requires ORG_SUBSCRIPTIONS WRITE. Returns 403 when subscriptionBillingManagementEnabled is false.
operationId: cancelTenantOrgSubscription
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- $ref: '#/components/parameters/XIdempotencyKey'
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CancelTenantOrgSubscriptionRequestDto'
responses:
'202':
description: Cancellation accepted (async workflow).
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/billing/balances:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization balances
description: Returns current included and extra balances per balance type. Requires BILLING_BALANCES READ.
operationId: getTenantOrgBalances
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
responses:
'200':
description: Organization balances.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OrgBalanceDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
post:
tags:
- Tenant Marketplace Provisioning
summary: Top up organization balance
description: 'Credits the org balance (positive amounts only). Requires X-Idempotency-Key mapped to the ledger referenceId; replays return alreadyRecorded: true. Partner convention: balanceType CHAT and targetColumn EXTRA for purchased credits. Requires BILLING_BALANCES WRITE. Returns 403 when subscriptionBillingManagementEnabled is false.'
operationId: topUpTenantOrgBalance
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- $ref: '#/components/parameters/XIdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TenantAdjustBalanceRequestDto'
responses:
'201':
description: Balance credited (or idempotent replay).
content:
application/json:
schema:
$ref: '#/components/schemas/AdjustBalanceResponseDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/billing/balances/ledger:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization balance ledger
description: Paginated ledger entries for reconciliation. Requires BILLING_BALANCES READ.
operationId: getTenantOrgBalanceLedger
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: balanceType
in: query
schema:
$ref: '#/components/schemas/BalanceTypeDto'
- name: since
in: query
schema:
type: string
format: date-time
- name: until
in: query
schema:
type: string
format: date-time
- name: entryType
in: query
schema:
$ref: '#/components/schemas/LedgerEntryTypeDto'
- name: cursor
in: query
schema:
type: string
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 50
responses:
'200':
description: Ledger page.
content:
application/json:
schema:
$ref: '#/components/schemas/BalanceLedgerPageDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/billing/invoices:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization invoices
description: Paginated invoices for the org subscription. Requires BILLING_INVOICES READ.
operationId: listTenantOrgInvoices
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: cursor
in: query
schema:
type: string
minLength: 1
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: Invoice page.
content:
application/json:
schema:
$ref: '#/components/schemas/InvoicePageDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/billing/allocations:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization allocation limits
description: Returns org-level monthly/daily allocation limits per balance type. Requires BILLING_ALLOCATIONS READ.
operationId: getTenantOrgAllocations
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
responses:
'200':
description: Allocation limits.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OrgAllocationDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/members:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization members
description: Paginated member list for seat reconciliation. Requires ORG_SETTINGS READ.
operationId: listTenantOrgMembers
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 10
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: Member page.
content:
application/json:
schema:
$ref: '#/components/schemas/TenantOrganizationMembersPageDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/invitations:
get:
tags:
- Tenant Marketplace Provisioning
summary: List organization invitations
description: Paginated invitation list for reconciliation. Requires ORG_SETTINGS READ.
operationId: listTenantOrgInvitations
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: status
in: query
schema:
type: string
enum:
- pending
- accepted
- revoked
default: pending
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 50
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: Invitation page.
content:
application/json:
schema:
$ref: '#/components/schemas/TenantOrganizationInvitationsPageDto'
'400':
description: Bad request.
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
post:
tags:
- Tenant Marketplace Provisioning
summary: Invite organization member
description: Sends an invitation email to add a member by email. Seat caps enforced. Requires ORG_SETTINGS WRITE.
operationId: inviteTenantOrgMember
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTenantOrganizationInvitationRequestDto'
responses:
'201':
description: Invitation sent.
content:
application/json:
schema:
$ref: '#/components/schemas/TenantOrganizationInvitationSuccessDto'
'400':
description: Bad request.
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
'409':
description: Conflict — seat cap exceeded.
'429':
description: Rate limit exceeded.
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
/api/v1/tenant/organizations/{orgId}/members/{userId}:
put:
tags:
- Tenant Marketplace Provisioning
summary: Update organization member
description: Updates role and/or membership type. At least one field required. Requires ORG_SETTINGS WRITE.
operationId: updateTenantOrgMember
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: userId
in: path
required: true
description: Target user ID.
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateTenantOrganizationMemberRequestDto'
responses:
'200':
description: Member updated.
content:
application/json:
schema:
$ref: '#/components/schemas/TenantMemberUpdateSuccessDto'
'400':
description: Bad request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
delete:
tags:
- Tenant Marketplace Provisioning
summary: Unassign organization member
description: 'Removes membership and cancels seat assignment. Idempotent: returns 204 even if the member was already removed. Requires ORG_SETTINGS WRITE. Uses a Redis-backed lock; returns 503 when Redis is unavailable. Returns 400 when another deletion is already in progress for the org.'
operationId: unassignTenantOrgMember
parameters:
- name: orgId
in: path
required: true
description: Target organization ID (must belong to the tenant).
schema:
type: string
- name: userId
in: path
required: true
description: Target user ID.
schema:
type: string
responses:
'204':
description: Member unassigned (or already absent).
'400':
description: Bad request — e.g. another member deletion is already in progress for this organization.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized — missing or invalid authentication.
'403':
description: Forbidden — caller is not the tenant owner or cannot access this organization.
'404':
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Service unavailable — member deletion requires Redis for the concurrency lock.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error.
security:
- ApiKeyAuth: []
components:
schemas:
CreateTenantOrganizationResponseDto:
type: object
required:
- orgId
- adminUserId
- name
- tenantPublicId
- tenantName
- seededOrgName
properties:
orgId:
type: string
adminUserId:
type: string
description: Resolved admin user ID (supplied admin or API caller).
name:
type: string
tenantPublicId:
type: string
tenantName:
type: string
seededOrgName:
type: boolean
description: False when seedOrgName was requested but the brand-name write failed (org still created).
PatchTenantOrgSubscriptionRequestDto:
type: object
properties:
pricingPlan:
type: string
enum:
- FREE
- FREE_MULTI_USER
- PERSONAL
- BUSINESS
description: Pricing plan allowed on tenant marketplace subscription create/patch.
maxUsers:
type:
- integer
- 'null'
minimum: 1
allowsFreeUsers:
type: boolean
maxFreeUsers:
type:
- integer
- 'null'
minimum: 1
externalSubscriptionId:
type:
- string
- 'null'
externalCustomerId:
type:
- string
- 'null'
metadata:
$ref: '#/components/schemas/TenantSubscriptionMetadataRequestDto'
additionalProperties: false
description: Partial update. Status/lifecycle fields are not settable — use DELETE to cancel.
SubscriptionMetadataDto:
type: object
additionalProperties: true
properties:
trialEndDate:
type: string
format: date-time
promo:
type: string
OrgMembershipTypeDto:
type: string
enum:
- FULL
- RESTRICTED
TenantOrganizationInvitationSuccessDto:
type: object
required:
- success
properties:
success:
type: boolean
enum:
- true
CreateTenantOrganizationAdminDto:
type: object
required:
- email
properties:
email:
type: string
format: email
description: Admin email address.
firstName:
type: string
minLength: 1
maxLength: 255
lastName:
type: string
minLength: 1
maxLength: 255
externalId:
type: string
minLength: 1
maxLength: 255
description: Partner external user identifier.
membershipType:
$ref: '#/components/schemas/OrgMembershipTypeDto'
description: Admin seat type. Defaults to FULL.
additionalProperties: false
CreateTenantOrganizationRequestDto:
type: object
required:
- name
properties:
name:
type: string
minLength: 1
maxLength: 255
description: Organization display name.
seedOrgName:
type: boolean
default: true
description: When true (default), seeds the org brand name from name. When false, inherits tenant branding for the name.
admin:
$ref: '#/components/schemas/CreateTenantOrganizationAdminDto'
externalId:
type: string
minLength: 1
maxLength: 255
description: Partner external organization identifier for reconciliation.
additionalProperties: false
CreateTenantOrganizationInvitationRequestDto:
type: object
required:
- emailAddress
- role
properties:
emailAddress:
type: string
format: email
role:
type: string
enum:
- ADMIN
- MEMBER
membershipType:
$ref: '#/components/schemas/OrgMembershipTypeDto'
description: Defaults to FULL.
additionalProperties: false
OrgSubscriptionPricingPlanDto:
type: string
enum:
- FREE
- FREE_MULTI_USER
- PERSONAL
- BUSINESS
- ENTERPRISE
TenantAdjustBalanceRequestDto:
type: object
required:
- balanceType
- targetColumn
- amount
- reason
properties:
balanceType:
$ref: '#/components/schemas/BalanceTypeDto'
targetColumn:
$ref: '#/components/schemas/BalanceColumnDto'
amount:
type: string
pattern: ^\d{1,8}(\.\d{1,12})?$
description: Positive non-zero dollar amount as a decimal string (up to 8 integer and 12 fractional digits). Must be greater than zero; floats are not accepted.
reason:
type: string
minLength: 10
maxLength: 500
description: Audit reason (trimmed; must be at least 10 characters after trim).
additionalProperties: false
OrgSubscriptionStatusDto:
type: string
enum:
- ACTIVE
- CANCELLED
- SUSPENDED
- FREE_TRIAL
TenantMemberUpdateSuccessDto:
ty
# --- truncated at 32 KB (46 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/appdirect/refs/heads/main/openapi/appdirect-tenant-marketplace-provisioning-api-openapi.yml