Skip to content

Integrate partner compliance

Connect your sales middleware to Ovee: find a partner or supplier, establish the relationship, provide evidence, and fetch current compliance after webhook notifications. This workflow covers organisation-level compliance. Individual staff qualifications and people-sharing permissions are outside its scope.

An organisation administrator follows the API Keys guide. Keep the key in your middleware’s secret store. Set your application origin and identifiers:

Terminal window
export OVEE_BASE_URL="https://app.ovee.com.au"
export CUSTOMER_ORG_ID="your-organisation-id"
# Load OVEE_API_KEY privately from your secret store.

Use the environment that issued your key; the configured application is https://app.ovee.com.au. CUSTOMER_ORG_ID is the requesting customer. Later, PARTNER_ORG_ID identifies the subject partner in compliance paths. PARTNERSHIP_ID identifies this customer’s relationship with that partner. These are different identifiers.

All requests use Authorization: Bearer $OVEE_API_KEY, except direct storage uploads and downloads. API keys retain their bound organisation and user permissions.

Terminal window
curl --fail-with-body --get \
--header "Authorization: Bearer $OVEE_API_KEY" \
--data-urlencode "abn=51 824 753 556" \
"$OVEE_BASE_URL/api/org/$CUSTOMER_ORG_ID/partners/lookup"

Example identity response (IDs are illustrative):

{
"abn": "51824753556",
"state": "LINKED_MANUAL",
"partnerOrgId": "000000000000000000000002",
"partnershipId": "000000000000000000000010",
"organisationName": "Supplier Trading",
"legalEntityName": "Supplier Legal Pty Ltd",
"onboardingRequestId": null
}
StateMiddleware action
LINKED_MANUAL / LINKED_OVEEReuse partnerOrgId and partnershipId; preserve existing data.
EXISTING_OVEEStart onboarding; wait for the registered organisation’s administrator to accept. Only limited identity is disclosed at lookup.
NOT_FOUNDStart onboarding to create a customer-managed manual partner.
PENDINGKeep onboardingRequestId; fetch its status and wait.
ACCEPTEDFetch the request or repeat lookup to obtain the relationship identifiers.
DECLINED / EXPIREDStop automatic onboarding and arrange administrator follow-up. Repeating the request does not resend invitations.

ABNs are normalised and checksum-validated. A linked relationship takes priority over an unlinked organisation with the same ABN. Ambiguous matches return 409; resolve them in Ovee instead of merging records. Another customer’s manual records are never returned. Onboarding your own organisation’s ABN is rejected.

Before the first import, configure applicable compliance profiles in Ovee and map your source services and staffing rules to their stable IDs. For example, choose Workcover when the business employs staff and Professional Indemnity when allied health or nursing services require it. Ovee does not infer these facts from an ABN.

Terminal window
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/data/domains"
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org/organisation-services"
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org-compliance/assignable-profiles"
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org-compliance/known-requirements"

Select profiles belonging to your customer organisation with ASSIGNED applicability. Their requirements expose IDs and, where configured, knownRequirementId. Use the returned compliance steps[].stepKey for evidence calls; evidenceStepKeys identifies related legacy keys. Never match requirements by display title.

For signed business agreements, configure Evidence specific to each partnership (partnershipScoped: true) on the applicable profile requirement and enable attachment evidence. This prevents an agreement supplied for one customer from satisfying another customer’s agreement requirement. The same option is available for other customer-specific evidence. Inspect profile requirements through GET /api/org-compliance/profiles.

Minimum creation data is name (business/trading display name), a valid abn, domainId, and non-empty assignedComplianceProfileIds. Include the contact details supplied by your sales process; do not manufacture missing data. Addresses and services can be included when known. This is a two-stage exchange: onboarding first, then agreement upload and bank evidence against an applicable compliance step.

Save a JSON request as onboarding.json, replacing profile, domain and service IDs with discovery results:

{
"name": "Supplier Trading",
"abn": "51824753556",
"domainId": "000000000000000000000020",
"assignedComplianceProfileIds": ["000000000000000000000030"],
"organisationServiceIds": ["000000000000000000000040"],
"contactPoints": [
{ "type": "Key Contact", "value": "Alex Example" },
{ "type": "Email", "value": "alex@supplier.example" },
{ "type": "Mobile", "value": "+61400000000" },
{ "type": "Remittance Email", "value": "accounts@supplier.example" }
]
}
Terminal window
curl --fail-with-body --request POST \
--header "Authorization: Bearer $OVEE_API_KEY" \
--header "Content-Type: application/json" \
--data-binary @onboarding.json \
"$OVEE_BASE_URL/api/org/$CUSTOMER_ORG_ID/partners/onboarding"
HTTP statusOutcome
200Existing identifiers returned without overwriting names, contacts, evidence or profile assignments; can also return a terminal invitation state.
201New manual partner and relationship created transactionally.
202Registered organisation invitation is pending, including an existing pending invitation.
409Ambiguous identity or concurrent change. Retry a concurrent conflict using the same ABN; resolve ambiguous records manually.
412Invalid selections or unmet business rules. Correct the request.
422 / 503ABN missing from the register / registry temporarily unavailable. No manual partner is created.

Repeated and concurrent calls use a unique customer/ABN identity reservation. Preserve returned IDs rather than creating a second record on a timeout. The server verifies legal-name and nullable GST data through its existing ABN registry lookup; client-supplied registry claims are not trusted for new manual records.

A 201 response looks like:

{
"state": "LINKED_MANUAL",
"partnerOrgId": "000000000000000000000002",
"partnershipId": "000000000000000000000010",
"onboardingRequestId": null,
"created": true
}

Store both IDs. The customer manages this record and can provide evidence immediately. Existing manual relationships are returned unchanged with 200 and created: false; use Ovee to review or change existing profile assignments. The existing partner-token/takeover workflow remains available through POST /api/org/{orgId}/partners/{partnershipId}/takeover-invitation with an email body. It is separate from registered-organisation acceptance.

A 202 response looks like:

{
"state": "PENDING",
"partnerOrgId": "000000000000000000000002",
"partnershipId": null,
"onboardingRequestId": "000000000000000000000050",
"created": true
}

The target organisation receives an invitation for its administrators. They sign in to Partner Organisations using the invitation’s onboardingRequestId link, select the invited organisation, and accept or decline. The screen identifies the customer and compliance profiles. Acceptance enables the relationship and assigned profiles; it does not enable people sharing or replace the registered organisation’s contacts or bank record.

Terminal window
export ONBOARDING_REQUEST_ID="returned-request-id"
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org/$CUSTOMER_ORG_ID/partners/onboarding-requests/$ONBOARDING_REQUEST_ID"

Wait for status: "ACCEPTED" and a non-null partnershipId before submitting evidence. The invitation expires after 14 days; expiry reconciliation can take a short interval. Status retrieval is available to either participant’s administrator. Only the target organisation’s administrator can call POST .../accept or POST .../decline; the customer’s key cannot accept on the supplier’s behalf. A repeated decision returns the recorded terminal state.

Fetch compliance first to find the applicable bank requirement’s canonical stepKey and responseType: "BANK_ACCOUNT_DETAILS". Then propose bank details for this relationship:

Terminal window
export PARTNER_ORG_ID="returned-partner-org-id"
export PARTNERSHIP_ID="returned-partnership-id"
export BANK_STEP_KEY="canonical-bank-step-key"
curl --fail-with-body --request PUT \
--header "Authorization: Bearer $OVEE_API_KEY" \
--header "Content-Type: application/json" \
--data '{"accountName":"Supplier Legal Pty Ltd","bsb":"123-456","accountNumber":"123456789"}' \
"$OVEE_BASE_URL/api/org-compliance/org/$PARTNER_ORG_ID/partnerships/$PARTNERSHIP_ID/steps/$BANK_STEP_KEY/bank-account-proposal"

These are proposed, private evidence for this customer’s relationship, requiring review. They do not update the registered organisation’s shared bank record. Changes invalidate the evidence’s previous verification. Fetch the step status and verification before treating the bank details as approved.

Use the canonical agreement step key from the assigned profile. This private upload flow also works for other document requirements:

Terminal window
export AGREEMENT_STEP_KEY="canonical-agreement-step-key"
curl --fail-with-body --request POST \
--header "Authorization: Bearer $OVEE_API_KEY" \
--header "Content-Type: application/json" \
--data '{"fileName":"signed-business-agreement.pdf","mimeType":"application/pdf"}' \
"$OVEE_BASE_URL/api/org-compliance/org/$PARTNER_ORG_ID/partnerships/$PARTNERSHIP_ID/steps/$AGREEMENT_STEP_KEY/attachments/upload"

The response contains attachmentId, uploadUrl, and expiresAt (30-minute upload slot). Set ATTACHMENT_ID and UPLOAD_URL to the returned values. PUT the bytes to uploadUrl, without an Ovee API key:

Terminal window
curl --fail-with-body --request PUT \
--header "Content-Type: application/pdf" \
--upload-file signed-business-agreement.pdf "$UPLOAD_URL"

Then associate the uploaded attachment with its server-bound partnership, subject and step:

Terminal window
curl --fail-with-body --request POST \
--header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org-compliance/org/$PARTNER_ORG_ID/partnerships/$PARTNERSHIP_ID/attachments/$ATTACHMENT_ID/complete"

The object must exist and contain 1 byte to 80 MiB before completion succeeds. Store attachmentId; repeated completion is idempotent. Providing evidence is separate from verification, submission and approval. For text requirements use PUT /api/org-compliance/org/{partnerOrgId}/steps/{stepKey}/text-evidence?partnershipId=... with {"text":"..."}.

Evidence providers submit through POST /api/org-compliance/org/{partnerOrgId}/requests/{partnershipId}/submit; customer reviewers verify individual steps and record the request decision. The API reference documents these role-protected operations. Registered suppliers normally submit their own request; the customer’s key cannot impersonate them.

Follow the Webhooks guide for subscription setup, raw-body signature verification, test delivery, retries and replay. Subscribe before starting onboarding to avoid missing invitation transitions.

PurposeEvents to select
Registered organisation onboardingpartner.onboarding.requested, partner.onboarding.accepted, partner.onboarding.declined, partner.onboarding.expired
Relationship and organisation changespartner.created, partner.updated, partner.removed
Evidence, bank and document changespartner.compliance.evidence_updated
Submission and decisionspartner.compliance.submitted, partner.compliance.approved, partner.compliance.conditionally_approved, partner.compliance.rejected
Current compliance and expirypartner.compliance.status_changed
Agreed completion statepartner.compliance.completion_changed

Save a subscription body as subscription.json:

{
"name": "Partner compliance integration",
"url": "https://middleware.example/ovee-events",
"enabled": true,
"eventTypes": [
"partner.onboarding.requested", "partner.onboarding.accepted",
"partner.onboarding.declined", "partner.onboarding.expired",
"partner.created", "partner.updated", "partner.removed",
"partner.compliance.evidence_updated", "partner.compliance.submitted",
"partner.compliance.approved", "partner.compliance.conditionally_approved",
"partner.compliance.rejected", "partner.compliance.status_changed",
"partner.compliance.completion_changed"
]
}
Terminal window
curl --fail-with-body --request POST \
--header "Authorization: Bearer $OVEE_API_KEY" \
--header "Content-Type: application/json" --data-binary @subscription.json \
"$OVEE_BASE_URL/api/webhooks/subscriptions"

Securely store the returned one-time signingSecret separately from your API key. Test the receiver with POST /api/webhooks/subscriptions/{id}/test. Verify each request’s signature over its raw bytes, acknowledge only after durable queuing, and deduplicate by the stable event ID. Deliveries may be duplicated or arrive out of order. See the Webhooks guide for signature timestamp tolerance and retry timing.

Payloads contain identifiers and state transitions, never bank details, document contents or signed storage URLs. After each relevant event, fetch the current authorised resource. Use onboarding events to resume waiting work and compliance events to refresh the affected partnership. Reconcile stored relationships periodically as well; do not rely on receiving an event as proof of current state. partner.removed can be followed by a 404 when you try to fetch the old relationship.

5. Retrieve current partner and compliance information

Section titled “5. Retrieve current partner and compliance information”
Terminal window
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org/$CUSTOMER_ORG_ID/partners/$PARTNER_ORG_ID/preview"
curl --fail-with-body --get --header "Authorization: Bearer $OVEE_API_KEY" \
--data-urlencode "partnershipId=$PARTNERSHIP_ID" \
"$OVEE_BASE_URL/api/org-compliance/org/$PARTNER_ORG_ID"

Both require an existing authorised relationship. Preview is an additive DTO, subject to existing visibility rules. legalEntityName/abnName is the registry legal name; tradingName/name is the display name. They are not interchangeable. gstRegistered is nullable: null means unknown, not false. Missing customer-supplied contacts or addresses remain missing.

A shortened compliance response illustrates the fields to store (step keys and IDs depend on your configuration):

{
"orgId": "000000000000000000000002",
"partnershipId": "000000000000000000000010",
"status": "COMPLIANT",
"completion": {
"completed": true,
"lastCompletedAt": "2026-11-02T02:30:00Z",
"approvalUrl": "https://app.ovee.com.au/partner-organisations?reviewPartnershipId=000000000000000000000010"
},
"steps": [
{
"stepKey": "agreement-requirement-id",
"partnershipScoped": true,
"status": "COMPLIANT",
"evidenceText": null,
"bankAccountDetails": null,
"verification": { "verified": true, "conditional": false },
"attachments": [
{ "id": "000000000000000000000060", "fileName": "signed-business-agreement.pdf", "mimeType": "application/pdf" }
]
}
]
}

completion.completed is true only when the request is fully APPROVED, requirements are applicable, no conditional step exists, and the current assessment is COMPLIANT or EXPIRING_SOON. Submission, conditional approval and an empty requirement set do not qualify. Existing UI progress/completed fields retain their original meanings; use the nested completion object for this integration.

lastCompletedAt records each observed false-to-true transition for this customer and partnership. It remains available after expiry or another change makes completion false. It can be null for historical records whose exact completion time cannot be established; do not invent a timestamp from a webhook delivery time. Expiry is reconciled periodically. Renewal can produce a new completion time once full approval and the required assessment hold again.

approvalUrl opens Ovee’s existing partner-compliance review route. It preserves sign-in return navigation and requires the reviewer’s usual permissions. It is a page link, not a public approval token. Use the returned environment-specific URL.

Customer dataAuthoritative response / setup
Legal entity namePreview legalEntityName / abnName from ABN registry data.
Trading or business display namePreview tradingName / name.
ABN and GST statusPreview abn, nullable gstRegistered.
Business address and locationsPreview address, locations.
Key contact, emails, phone/mobilePreview contactPoints (type, value).
Remittance emailPreview remittanceEmail, derived when there is one unambiguous Remittance Email contact; otherwise null.
ServicesPreview organisationServiceNames and customer-specific partnerServiceNames; discover stable service IDs before onboarding.
Bank account name, BSB and numberApplicable compliance step bankAccountDetails.accountName, .bsb, .accountNumber, with step status and verification; proposed data needs review.
Public LiabilityYour configured requirement key, its status, verification/expiry and attachments.
WorkcoverApplicable assigned profile when the business employs staff; configured requirement key and evidence.
Professional IndemnityApplicable profile for relevant allied health/nursing services; configured requirement key and evidence.
Police Check / Statutory DeclarationOrganisation-level configured requirement keys and evidence; individual staff qualification workflows are excluded.
Licences / registrations (such as AHPRA)Applicable organisation-level configured requirement keys and evidence.
Signed Business AgreementPartnership-scoped agreement requirement’s attachments and verification.
Compliance completed and timecompletion.completed, completion.lastCompletedAt.
Page to review or approvecompletion.approvalUrl.

Use stable requirement IDs/keys in your integration configuration. There is no universal title-based mapping for insurance, declarations or registrations. Confirm your customer’s profiles and required evidence with their administrator before importing suppliers.

Take an attachment ID from the current visible steps[].attachments. Ask Ovee for a fresh URL:

Terminal window
curl --fail-with-body --header "Authorization: Bearer $OVEE_API_KEY" \
"$OVEE_BASE_URL/api/org-compliance/org/$PARTNER_ORG_ID/partnerships/$PARTNERSHIP_ID/attachments/$ATTACHMENT_ID/download-url"
{
"url": "https://storage.example/private-object?short-lived-signature=...",
"expiresAt": "2026-11-02T02:45:00Z",
"fileName": "signed-business-agreement.pdf",
"mimeType": "application/pdf"
}

The API checks this partnership, subject and currently applicable requirement before returning Cache-Control: no-store and a 15-minute signed download URL. Set DOWNLOAD_URL to the returned url. Storage serves the bytes directly:

Terminal window
curl --fail-with-body --output signed-business-agreement.pdf "$DOWNLOAD_URL"

Do not send your Ovee API key to storage. Treat the URL as a temporary bearer capability: keep it out of logs, webhook payloads and permanent records. Store the attachment ID and request a fresh URL whenever needed, including after expiry. Access changes prevent new URLs from being issued; a previously issued URL can remain usable until it expires. Missing, inapplicable or inaccessible evidence returns 404 (or the relevant permission error).

In SIT, exercise both manual and registered-organisation branches, repeated onboarding, a declined/expired invitation, incomplete and conditionally approved evidence, full approval, expiry/renewal, changed bank details, agreement replacement, signature failures, duplicate/out-of-order webhooks, and expired download URLs. Confirm another customer’s key cannot see your invitations or relationship-specific evidence.

Deploy the corresponding backend before publishing documentation for these operations. The public developer site can remain statically hosted on SIT while OVEE_BASE_URL points to the production application for production integrations.