Partner Agent Feed
Expose your agent network to Safiri so your shops, supermarkets, petrol stations and other outlets can become parcel collection and drop-off locations. You host the endpoint; Safiri calls it. Each response contains your complete agent list, with enough information to recreate the businesses, their offices and their associated account holders in Safiri.
Your organisation continues to operate its network. Imported records retain their partner affiliation and external identifiers and are intended to be discoverable alongside Safiri's own agents.
This page specifies version 1 of the partner feed. Safiri's background importer will be implemented separately. The import behaviour below describes that planned integration; this page does not introduce an available Safiri import endpoint.
How the integration works
- Provide Safiri with your HTTPS endpoint URL and a bearer token through the agreed private integration channel.
- When Safiri initiates an import, Safiri will fetch the complete response.
- New agents will be onboarded automatically from the supplied business, office and account-holder information. Safiri accepts the partner's vetting; agents do not need to repeat the website application and approval process.
- Later imports will add new agents, skip unchanged agents and update changed partner-provided information while retaining Safiri's identifiers.
The feed must follow the field types and required structure on this page. Safiri accepts the partner's vetting without repeating the approval process. Tax details, a TIN or VAT certificate, and the account holder's national ID or passport document are still required, along with complete office information.
Endpoint
The endpoint path is chosen by you. This is an example:
GET https://partner.example/integrations/safiri/agents
Authorization: Bearer <partner-issued-token>
Accept: application/json
The token is issued by your organisation and authorises Safiri to read your feed. It is separate from the tokens used to call Safiri's booking APIs.
curl --request GET \
'https://partner.example/integrations/safiri/agents' \
--header 'Authorization: Bearer REPLACE_WITH_PARTNER_TOKEN' \
--header 'Accept: application/json'
Return 200 OK with Content-Type: application/json and one complete JSON
response. There is no pagination, cursor, page size or incremental-feed
requirement. A response taking several minutes is acceptable for the planned
background import. Coordinate the expected maximum duration and server/proxy
timeouts with Safiri when setting up the integration.
Return every agent on each successful request, including previously imported
agents and any agents whose status has changed. Do not return a partial list as
a successful response. If the feed cannot be generated, return an appropriate
non-success HTTP status so the fetch can be retried. Use 401 or 403 for
authentication/access failures and 5xx for temporary server failures.
An empty agents array is valid when your feed genuinely contains no agents; it
does not remove records already imported into Safiri.
Complete response example
Each item represents one agent business. Put its branches or parcel locations
inside offices; do not repeat the business as a new agent for every branch.
All values below are illustrative. The example includes the required tax and
identity documents and office details, plus optional settlement information,
storage information and supporting documents. The account holder's profile
photo is optional.
{
"schemaVersion": "1",
"agents": [
{
"externalAgentId": "PARTNER-AGENT-001",
"externalBusinessId": "PARTNER-BUSINESS-100",
"status": "active",
"updatedAt": "2026-09-27T09:00:00Z",
"currency": "TZS",
"businessInformation": {
"businessName": "Example Retail Limited",
"tradingName": "Example Supermarket",
"businessAddressName": "Plot 12, Example Road",
"businessAddressCity": "Dar es Salaam",
"businessAddressCountry": "Tanzania",
"businessAddressLatitude": -6.77,
"businessAddressLongitude": 39.24,
"contacts": [
{
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000001"
}
]
},
"personalDetails": {
"externalUserId": "PARTNER-USER-500",
"fullName": "Amina Example",
"email": "amina@example.com",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002",
"idType": "National ID",
"idNo": "EXAMPLE-ID-NUMBER",
"gender": "Female",
"ageRange": "30-39"
},
"stakeholders": [
{
"externalStakeholderId": "PARTNER-STAKEHOLDER-001",
"fullName": "Amina Example",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002"
}
],
"taxDetails": {
"tinNumber": "EXAMPLE-TIN",
"vatNo": "EXAMPLE-VAT"
},
"accountInformation": {
"accountHolderName": "Example Retail Limited",
"accountNumber": "EXAMPLE-ACCOUNT-NUMBER",
"swiftOrBIC": "EXAMPLE-BIC",
"accountAddressName": "Plot 12, Example Road",
"accountAddressCity": "Dar es Salaam",
"accountAddressCountry": "Tanzania",
"accountAddressLatitude": -6.77,
"accountAddressLongitude": 39.24
},
"mobileMoneyInformation": {
"name": "m-pesa",
"accountHolderName": "Amina Example",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002"
},
"documents": {
"businessLicense": "https://partner.example/documents/business-license.pdf",
"certifiedIncorporationOrReg": "https://partner.example/documents/registration.pdf",
"tinOrVatCertificate": "https://partner.example/documents/tax-certificate.pdf",
"premiseTenancy": "https://partner.example/documents/tenancy.pdf",
"nationalIdOrPassport": "https://partner.example/documents/identity.pdf",
"profilePhoto": "https://partner.example/documents/profile.jpg"
},
"digitalServices": {
"travel": {
"busTickets": false,
"flightTickets": false,
"trainTickets": false,
"ferryTickets": false
},
"delivery": {
"parcelPickupAndDropOff": true
},
"rental": {
"carPickupAndDropOff": false,
"rentalBookings": false
}
},
"offices": [
{
"externalOfficeId": "PARTNER-OFFICE-001",
"name": "Example Supermarket — Mikocheni",
"description": "Parcel counter beside the main entrance.",
"country": "Tanzania",
"city": "Dar es Salaam",
"locality": "Mikocheni",
"subLocality": "Mikocheni B",
"latitude": -6.77,
"longitude": 39.24,
"contact": [
{
"externalContactId": "PARTNER-CONTACT-001",
"fullName": "Amina Example",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002"
}
],
"customerCare": [
{
"externalContactId": "PARTNER-CONTACT-002",
"fullName": "Example Supermarket Support",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000003"
}
],
"openingHours": {
"MONDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"TUESDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"WEDNESDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"THURSDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"FRIDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"SATURDAY": {
"openingTime": "09:00",
"closingTime": "18:00",
"isClosed": false
},
"SUNDAY": {
"openingTime": "00:00",
"closingTime": "00:00",
"isClosed": true
}
},
"storageSpace": {
"storageType": "Dedicated indoor storage room",
"totalArea": 200,
"totalAreaUnit": "square feet",
"ceilingHeight": 3,
"ceilingHeightUnit": "meters",
"storageCapacity": {
"small": true,
"medium": true,
"large": true,
"extraLarge": false
},
"securityFeatures": {
"cctv": true,
"alarm": false,
"accessControl": true
},
"storageCondition": {
"temperatureControlled": false,
"weatherProof": true
}
},
"images": [
"https://partner.example/images/office-001-front.jpg",
"https://partner.example/images/office-001-storage.jpg"
]
}
],
"partnerVerification": {
"status": "verified",
"verifiedAt": "2026-09-01T10:00:00Z",
"reference": "PARTNER-VERIFICATION-001"
}
}
]
}
Minimum valid response example
This example contains the required information for one business, its initial account holder and one office, including tax details, the TIN or VAT certificate, the national ID or passport document, and the office's description, locality, sub-locality, opening hours and images. Additional optional information can be supplied on a later pull using the same external IDs.
{
"schemaVersion": "1",
"agents": [
{
"externalAgentId": "PARTNER-AGENT-001",
"status": "active",
"updatedAt": "2026-09-27T09:00:00Z",
"currency": "TZS",
"businessInformation": {
"businessName": "Example Retail Limited",
"businessAddressName": "Plot 12, Example Road",
"businessAddressCity": "Dar es Salaam",
"businessAddressCountry": "Tanzania",
"businessAddressLatitude": -6.77,
"businessAddressLongitude": 39.24,
"contacts": [
{
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000001"
}
]
},
"personalDetails": {
"externalUserId": "PARTNER-USER-500",
"fullName": "Amina Example",
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002"
},
"taxDetails": {
"tinNumber": "EXAMPLE-TIN"
},
"documents": {
"tinOrVatCertificate": "https://partner.example/documents/tax-certificate.pdf",
"nationalIdOrPassport": "https://partner.example/documents/identity.pdf"
},
"digitalServices": {
"travel": {
"busTickets": false,
"flightTickets": false,
"trainTickets": false,
"ferryTickets": false
},
"delivery": {
"parcelPickupAndDropOff": true
},
"rental": {
"carPickupAndDropOff": false,
"rentalBookings": false
}
},
"offices": [
{
"externalOfficeId": "PARTNER-OFFICE-001",
"name": "Example Supermarket — Mikocheni",
"description": "Parcel counter beside the main entrance.",
"country": "Tanzania",
"city": "Dar es Salaam",
"locality": "Mikocheni",
"subLocality": "Mikocheni B",
"latitude": -6.77,
"longitude": 39.24,
"contact": [
{
"countryCodeName": "TZ",
"countryCode": "255",
"phoneNumber": "712000002"
}
],
"openingHours": {
"MONDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"TUESDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"WEDNESDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"THURSDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"FRIDAY": {
"openingTime": "08:00",
"closingTime": "20:00",
"isClosed": false
},
"SATURDAY": {
"openingTime": "09:00",
"closingTime": "18:00",
"isClosed": false
},
"SUNDAY": {
"openingTime": "00:00",
"closingTime": "00:00",
"isClosed": true
}
},
"images": [
"https://partner.example/images/office-001-front.jpg"
]
}
]
}
]
}
documents.profilePhoto is optional and is omitted from this minimum example.
If available, include a profile photo URL as shown in the complete example.
This is separate from the office images array, which must contain at least one
image.
Field reference
Required means required whenever the containing object is supplied. An
optional section may be omitted entirely; if supplied, its required members must
be present. Send actual JSON booleans and numbers, not their string equivalents.
Omit unavailable optional information rather than sending null or placeholder
values. The EXAMPLE-... values above illustrate the shape only.
Response envelope
| Field | Type | Required | Description |
|---|---|---|---|
schemaVersion | string | Yes | Exactly "1". |
agents | array of agent objects | Yes | The complete feed. May be empty. Each externalAgentId occurs once. |
Agent
| Field | Type | Required | Description |
|---|---|---|---|
externalAgentId | string | Yes | Your stable identifier for this agent business. Unique within your partner feed. |
externalBusinessId | string | No | An additional business/merchant reference from your system. It is not the import matching key. |
status | string | Yes | active or inactive. An inactive agent is retained but is not intended to be offered for new parcel bookings. |
updatedAt | string | Yes | UTC timestamp of the last change to this agent or any nested supplied information, including offices. |
currency | string | Yes | The business currency; see the supported values below. It does not set or change an existing user's wallet currency. |
businessInformation | object | Yes | Business identity, address and contacts. |
personalDetails | object | Yes | The initial account holder authorised to represent this business. |
stakeholders | array of objects | No | Other business stakeholders. Listing a stakeholder does not create an account or grant access. |
taxDetails | object | Yes | Tax identification details. tinNumber is required; vatNo is optional when applicable. |
accountInformation | object | No | Bank settlement details, when applicable to the partner's settlement arrangement. |
mobileMoneyInformation | object | No | Mobile-money settlement details, when applicable. |
documents | object | Yes | Must include tinOrVatCertificate and nationalIdOrPassport. Other document fields are optional. |
digitalServices | object | Yes | Explicit service selections, including parcel pickup/drop-off. |
offices | array of objects | Yes | At least one physical location. Each externalOfficeId occurs once within the agent. |
partnerVerification | object | No | Optional record of the partner's completed verification. |
Supported currency values are TZS, ZMW, MWK, KES, UGX,
XAF, CDF, RWF, SLE and USD. These are the current Safiri
business currency codes. Agree support with Safiri before supplying another code.
Business information
| Field | Type | Required | Description |
|---|---|---|---|
businessName | string | Yes | Registered or recognised business name. |
tradingName | string | No | Customer-facing trading name. On initial creation, defaults to businessName when omitted. |
businessAddressName | string | Yes | Business address, such as street, plot or premises description. |
businessAddressCity | string | Yes | City or town. |
businessAddressCountry | string | Yes | Country name, for example Tanzania. |
businessAddressLatitude | number | Yes | Latitude in decimal degrees. |
businessAddressLongitude | number | Yes | Longitude in decimal degrees. |
contacts | array of phone objects | Yes | At least one business contact. Each item contains the three phone fields below. |
Phone formatting
These fields are used in business contacts, personal details, stakeholders, mobile-money details and office contacts.
| Field | Type | Required | Description |
|---|---|---|---|
countryCodeName | string | Yes | Uppercase two-letter country identifier, for example TZ, KE or GB. |
countryCode | string | Yes | International calling code, 1–5 digits, without +; for example "255". |
phoneNumber | string | Yes | National phone number, 8–13 digits, without the calling code, spaces, punctuation or domestic trunk prefix. |
For example, +255 712 000 002 becomes countryCode: "255" and
phoneNumber: "712000002". Keep these values as strings.
Account holder and personal details
| Field | Type | Required | Description |
|---|---|---|---|
externalUserId | string | Yes | Stable identifier for the person in your system. Reuse it when the same person represents multiple businesses. |
fullName | string | Yes | Account holder's full name, at least two characters. |
countryCodeName, countryCode, phoneNumber | strings | Yes | Account holder's phone details, using the phone rules above. |
email | string | No | Valid email address, when available. |
idType | string | No | Identity document type, for example National ID or Passport. |
idNo | string | No | Identity document number. Supply idType and idNo together if providing identity details. |
gender | string | No | Optional personal information collected during partner onboarding. |
ageRange | string | No | Optional age band, for example 30-39. |
A matching contact phone number by itself is not an instruction to transfer an existing
Safiri account or its permissions. Changes of account holder must use the new
person's own externalUserId; do not reuse another person's identifier.
Stakeholders
Each supplied stakeholder contains:
| Field | Type | Required | Description |
|---|---|---|---|
externalStakeholderId | string | Yes | Stable stakeholder reference within the agent business. |
fullName | string | Yes | Stakeholder's full name, at least two characters. |
countryCodeName, countryCode, phoneNumber | strings | Yes | Stakeholder's phone details. |
Tax details
| Field | Type | Required | Description |
|---|---|---|---|
tinNumber | string | Yes | Tax identification number. Required for every agent. |
vatNo | string | No | VAT registration number, if applicable. |
Bank account information
Bank details and mobile-money details are independent optional sections. Provide one or both when settlement is made directly to the agent and those details are applicable. They may be omitted for settlement handled centrally by the partner. Supplying these sections does not itself enable payouts.
| Field | Type | Required | Description |
|---|---|---|---|
accountHolderName | string | Yes | Name on the account. |
accountNumber | string | Yes | Account number; retain leading zeros. |
swiftOrBIC | string | Yes | Bank's SWIFT/BIC identifier. |
accountAddressName | string | Yes | Address associated with the account. |
accountAddressCity | string | Yes | Address city or town. |
accountAddressCountry | string | Yes | Country name. |
accountAddressLatitude | number | Yes | Address latitude in decimal degrees. |
accountAddressLongitude | number | Yes | Address longitude in decimal degrees. |
Mobile-money information
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Mobile-money provider; use a supported literal below. |
accountHolderName | string | Yes | Name registered to the mobile-money account. |
countryCodeName, countryCode, phoneNumber | strings | Yes | Mobile-money account phone details. |
Supported provider values are t-pesa, m-pesa, tigo-pesa,
airtel-money, halo-pesa, ezy-pesa, zamtel, mtn, telkom,
equitel, utl and orange-money. Use these API literals even where a
provider's customer-facing brand name differs.
Documents
Every agent must supply tinOrVatCertificate and nationalIdOrPassport.
The other document fields, including profilePhoto, are optional. Supply HTTPS
links that Safiri can retrieve under the agreed document-access arrangement.
The links do not need to be publicly accessible; arrange access separately from
feed authentication.
| Field | Type | Required | Description |
|---|---|---|---|
businessLicense | string | No | Business licence document URL. |
certifiedIncorporationOrReg | string | No | Incorporation or business registration document URL. |
tinOrVatCertificate | string | Yes | TIN or VAT certificate URL. |
premiseTenancy | string | No | Evidence of tenancy or occupancy URL. |
nationalIdOrPassport | string | Yes | Account holder's national ID or passport document URL. |
profilePhoto | string | No | Optional account holder's profile photo URL; may be omitted. Office images are required separately. |
Digital services
Supply all three service groups and their required booleans. Use false for
services the business does not provide. In this version, offices inherit the
business's selections; office-specific service overrides are not part of the feed.
| Field | Type | Required | Description |
|---|---|---|---|
travel.busTickets | boolean | Yes | Bus ticket services. |
travel.flightTickets | boolean | Yes | Flight ticket services. |
travel.trainTickets | boolean | Yes | Train ticket services. |
travel.ferryTickets | boolean | Yes | Ferry ticket services. |
delivery.parcelPickupAndDropOff | boolean | Yes | Whether the agent provides parcel collection and drop-off. Use true for an agent offered for these services. |
delivery.storageOnly | boolean | No | Whether parcel storage without delivery is offered. This does not replace the required pickup/drop-off selection. |
rental.carPickupAndDropOff | boolean | Yes | Rental-car collection and drop-off. |
rental.rentalBookings | boolean | Yes | Rental booking services. |
Service selections describe the partner's business. They do not grant Safiri account permissions or configure commissions.
Offices
Each office represents a physical location belonging to the agent business.
For a business with multiple branches, include multiple offices with different,
stable externalOfficeId values under the same externalAgentId.
| Field | Type | Required | Description |
|---|---|---|---|
externalOfficeId | string | Yes | Stable office identifier within the agent business. |
name | string | Yes | Customer-facing location name. |
description | string | Yes | Street address, landmarks and instructions for finding the parcel counter. |
country | string | Yes | Country name. |
city | string | Yes | City or town. |
locality | string | No | District, suburb or locality. |
subLocality | string | No | More specific neighbourhood or area. |
latitude | number | Yes | Office latitude in decimal degrees. |
longitude | number | Yes | Office longitude in decimal degrees. |
contact | array of contact objects | Yes | At least one office contact. The field name is singular: contact. |
customerCare | array of contact objects | No | Additional customer-support contacts. |
openingHours | object | Yes | Weekly operating hours for all seven days, using the structure below. |
storageSpace | object | No | Parcel storage and facilities information. |
images | array of strings | No | HTTPS image URLs showing the premises, entrance or storage area. |
Office contact and customerCare entries share this structure:
| Field | Type | Required | Description |
|---|---|---|---|
externalContactId | string | No | Stable contact reference from your system, if available. |
fullName | string | No | Contact person's name or support-team label. |
countryCodeName, countryCode, phoneNumber | strings | Yes | Contact's phone details. |
Opening hours
Every office must supply openingHours with all seven uppercase day keys:
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
and SUNDAY. Times are in the office's local time.
Each day contains:
| Field | Type | Required | Description |
|---|---|---|---|
openingTime | string | Yes | 24-hour HH:mm time, from 00:00 to 23:59. |
closingTime | string | Yes | 24-hour HH:mm time. |
isClosed | boolean | Yes | Whether the office is closed that day. |
For a closed day, set isClosed: true and both times to "00:00".
For an open day, an earlier closing time means closing on the following day;
equal opening and closing times mean a 24-hour opening period.
Storage and facilities
| Field | Type | Required | Description |
|---|---|---|---|
storageType | string | Yes | Storage description, for example Dedicated indoor storage room. |
totalArea | number | Yes | Positive storage area, expressed in totalAreaUnit. |
totalAreaUnit | string | Yes | Current unit literals: square feet, meters, feet. For area, meters and feet denote square metres and square feet respectively. |
ceilingHeight | number | Yes | Positive ceiling height. |
ceilingHeightUnit | string | Yes | meters or feet. |
storageCapacity.small | boolean | Yes | Whether small parcels can be stored. |
storageCapacity.medium | boolean | Yes | Whether medium parcels can be stored. |
storageCapacity.large | boolean | Yes | Whether large parcels can be stored. |
storageCapacity.extraLarge | boolean | Yes | Whether extra-large parcels can be stored. |
securityFeatures.cctv | boolean | Yes | CCTV is available. |
securityFeatures.alarm | boolean | Yes | An alarm system is available. |
securityFeatures.accessControl | boolean | Yes | Storage access is controlled. |
storageCondition.temperatureControlled | boolean | Yes | Temperature-controlled storage is available. |
storageCondition.weatherProof | boolean | Yes | Storage is protected from weather. |
These capacity flags describe available facilities; they do not define parcel dimensions or override Safiri's parcel booking limits.
Partner verification
Partner vetting is accepted for automatic onboarding. This optional section records that vetting; it is not a request for a second Safiri application review.
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | Exactly verified. The partner has completed its checks. |
verifiedAt | string | Yes | UTC timestamp when verification was completed. |
reference | string | No | Your verification or onboarding reference. |
The required tax and identity documents must be supplied whether or not this
optional verification record is included. The trusted-partner arrangement
applies to the feed. Agent operating status and
partnerVerification.status are separate: a verified business may later become
inactive.
Shared value rules
- External identifiers are non-empty, case-sensitive strings from your system. Do not send Safiri UUIDs or regenerate identifiers on each request.
- All required text fields must contain a value. Identity numbers, account numbers, tax identifiers and phone details remain strings.
- Latitude must be a finite JSON number between
-90and90; longitude must be between-180and180. Zero is a valid coordinate, but do not use0, 0as a placeholder for an unknown location. updatedAtandverifiedAtuse ISO 8601 UTC timestamps, for example2026-09-27T09:00:00Z. Fractional seconds are allowed.updatedAtrecords a data change, not the time the feed was fetched. Advance it when supplied business, account-holder, service or office information changes.
Repeat imports and updates
Safiri will identify an imported agent using the configured partner plus
externalAgentId. Two partners may use the same external ID without referring
to the same Safiri agent. The partner is determined by the configured connection,
not by a field that needs to be repeated in every agent object.
| Situation | Intended import result |
|---|---|
A new externalAgentId is supplied | Create the local business, offices and associated account membership from the partner data. |
| An existing agent's supplied data is unchanged | Skip business/account/office changes and retain existing records. |
| An existing agent has changed supplied fields | Update those partner-managed fields while retaining the Safiri identifiers. |
| Only JSON formatting, object-key order or the fetch time changes | Do not recreate the agent. A timestamp alone is not a changed business detail. |
| An agent gains another office | Create that office under the existing business using its new externalOfficeId. |
| An optional field or section is omitted | Preserve any previously imported value. |
| An agent or office is absent from a later response | Do not delete it or infer closure from its absence. |
Agent status changes to inactive | Retain its records and history; stop offering the agent for new parcel bookings. |
Continue returning complete agent records on every pull, including all required fields. Within a supplied optional section, its required fields still apply. Safiri will update changed supplied information; unchanged fields and omitted optional values will be retained.
Offices are matched by externalOfficeId within the existing agent business.
Their order in the array does not identify them. Keep the same ID when an office
changes its name, address, phone or operating hours.
For other supplied arrays, such as business contacts, office contacts,
stakeholders and images, send the complete current non-empty list for that
field. A supplied list updates that field's value; it does not delete related
Safiri businesses or user accounts. Omit unavailable optional lists.
Clearing fields and deleting records are outside version 1: do not use null,
empty strings or empty arrays as clearing instructions.
Examples across successive pulls
| Pull | Partner data | Intended outcome |
|---|---|---|
| First | PARTNER-AGENT-001 with PARTNER-OFFICE-001 | Create one business and its first office; provision or resolve the account holder and membership. |
| Second | Same agent, office and supplied values | Skip; no duplicate business, office or user. |
| Third | Same IDs; change businessInformation.businessAddressName and an office contact's phoneNumber; advance updatedAt | Update the supplied address and contact data, retaining the same business and office IDs. The account holder's phone is separate and is not changed by an office contact update. |
| Fourth | Same agent; include both PARTNER-OFFICE-001 and a new PARTNER-OFFICE-002 | Retain the existing business and add its second office. |
| Fifth | Add PARTNER-AGENT-002 alongside the unchanged first agent | Create the second agent; skip the unchanged first agent. |
Safiri-managed information
Safiri manages account setup. Your external IDs remain stable partner references. Use the feed contract on this page; it is separate from Safiri's website signup process.
Partner updates maintain imported business and location information. They do not overwrite Safiri passwords, verification credentials, account permissions, wallet balances or currencies, commissions, booking history or operational records. Stakeholders and office contacts are contact information and do not automatically receive user accounts. Changing the account-holder reference does not rename or transfer another person's account.
Safiri will control when imports are triggered and process them in the background. Partners only need to expose this feed; no Safiri import trigger URL is available as part of this documentation release.
Partner readiness checklist
- The HTTPS endpoint accepts the agreed bearer token and returns the full
schemaVersion: "1"response. - Each agent contains the required business, account-holder, tax, document, service and office information. Every office includes a description, locality, sub-locality, opening hours for all seven days and at least one image. Optional supplied sections follow their field definitions.
- Agent, user and office identifiers stay stable across repeated requests.
- Unchanged records keep their data timestamps; changed nested details advance
the enclosing agent's
updatedAt. - The endpoint can return the entire list within the duration agreed for the integration, including when that takes several minutes.
- Safiri has the endpoint URL, feed credentials and any separate access details needed for supplied document or image links.