Skip to main content

CRM API accounts

A CRM that delivers listings for many agencies can hold one client ID and secret for all of them. Each listing's agentID decides which FeedSync feed it lands in, so onboarding a new agency adds an entry to an allow-list instead of issuing another credential.

The CRM OpenAPI reference is the machine-readable contract for endpoints, request formats, response fields, and HTTP status codes.

How it differs from a feed credential

A feed credential (see REAXML API feeds) is bound to one feed, and every listing it uploads goes to that feed. A CRM credential is bound to a provider and carries a list of the feeds it may upload for.

Feed credentialCRM credential
Upload path/api/v1/listing/v1/upload/api/v1/crm/upload
Scopelisting:listings:writecrm:listings:write
Target feedFixed by the credentialResolved from each listing's agentID
Adding an agencyIssue another credentialAdd the feed to the allow-list

Everything else is the same contract: one REAXML listing per request, a 10 MiB body limit, application/xml or text/xml, a 202 with an upload ID, and the same asynchronous processing report.

Operations

MethodFeedSync pathBehavior
POST/api/v1/crm/uploadAccept one REAXML listing, route it by agentID, and return 202 plus uploadId.
GET/api/v1/crm/upload/{uploadId}Return the processing report.
GET/api/v1/crm/upload?agencyId=…&externalListingId=…Search reports by REAXML agentID and uniqueID.

Get credentials

FeedSync creates the account from the provider's record and sends the client ID and secret to the CRM's team email. The email lists every agency the credential is authorised for alongside the agentID to send for each one.

Store the secret in a secret manager or encrypted server configuration. Never place it in frontend JavaScript, mobile code, URLs, source control, screenshots, or normal request logs.

Request a bearer token

Identical to a feed credential, with the CRM scope:

curl --request POST "https://feedsync.com.au/api/v1/oauth/token" \
--user "CLIENT_ID:CLIENT_SECRET" \
--header "Accept: application/json" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials"
{
"access_token": "opaque-access-token",
"token_type": "bearer",
"expires_in": 3600,
"scope": "crm:listings:write",
"consumer_id": "7ebfcd36-b5b0-46e6-a3fb-d88b18f04c37"
}

FeedSync revokes the client's earlier live tokens when it issues a new one, so all of a CRM's workers should share one cached token.

Upload one listing

curl --request POST "https://feedsync.com.au/api/v1/crm/upload" \
--header "Authorization: Bearer ACCESS_TOKEN" \
--header "Accept: application/json" \
--header "Content-Type: application/xml" \
--data-binary @listing.xml

The agentID in the document is what routes it:

<?xml version="1.0" encoding="UTF-8"?>
<propertyList>
<residential status="current" modTime="2026-09-11-10:00:00">
<agentID>OFFICE42</agentID>
<uniqueID>CRM-10001</uniqueID>
<category name="House" />
<address display="yes">
<suburb display="yes">Fremantle</suburb>
<state>WA</state>
<postcode>6160</postcode>
</address>
</residential>
</propertyList>

An agentID the credential is not authorised for is rejected with 403 and the detail names the code that was rejected:

{
"errors": [
{
"status": "403",
"title": "Forbidden",
"detail": "This credential is not authorised to upload for agentID OFFICE42",
"meta": {
"transactionId": "36028179-ff20-46fe-b17a-3f50e10f175f"
}
}
]
}

Nothing is stored and the listing is not queued, so this is safe to treat as a configuration fault: the agency has not been onboarded yet, or the CRM is sending a different code from the one FeedSync has registered. Ask FeedSync support to check the account's allow-list rather than retrying.

Reports

GET /api/v1/crm/upload/{uploadId} and the agencyId search behave exactly as they do for a feed credential, scoped to the feeds this credential is authorised for. An upload ID belonging to any other feed returns 404, whether or not it exists. See Retrieve a report for the report shape and polling guidance.

Errors and status codes

The envelope and status codes match the Uploads API — see Errors and status codes — with two differences on 403:

StatusMeaning
403The listing's agentID matches no authorised feed, the token lacks crm:listings:write, or a feed credential was used on /crm.

Rate limiting is per credential, so a CRM's whole push shares one 300-requests-per-minute budget. Spread large batches out and honour Retry-After on a 429.

Production checklist

  • Send the agentID FeedSync registered for each agency, exactly as it appears in the credentials email.
  • Treat 403 as a configuration fault and stop retrying that listing.
  • Share the cached token between workers.
  • Persist uploadId, agentID, uniqueID, timestamps, status, and safe error metadata.
  • Reconcile periodically so a missed delivery cannot leave an agency's data stale indefinitely.