PinPoint API Spec
This local backend exposes the current OpenAPI contract at the root path for quick browser inspection. Raw YAML is also available at /openapi.yaml.
openapi: '3.1.0'
info:
title: PinPoint API
version: '1.0.0'
description: Universal customer delivery identity platform API
servers:
- url: https://recipients.api.oproute.com
description: Production
security:
- CognitoRecipient: []
components:
securitySchemes:
CognitoRecipient:
type: http
scheme: bearer
bearerFormat: JWT
description: Cognito JWT from pinpoint-recipients user pool
CarrierApiKey:
type: apiKey
in: header
name: x-api-key
description: SHA-256-hashed carrier API key
DriverJwt:
type: http
scheme: bearer
bearerFormat: JWT
description: Oproute Cognito JWT (Driver group)
PlatformAdminJwt:
type: http
scheme: bearer
bearerFormat: JWT
description: Platform admin JWT for carrier management
LiveSessionJwt:
type: http
scheme: bearer
bearerFormat: JWT
description: Ephemeral live-session token for customer or driver
schemas:
RecipientProfile:
type: object
properties:
userId: {type: string}
displayName: {type: string, nullable: true}
phone: {type: string, nullable: true}
email: {type: string, nullable: true}
preferredLanguage: {type: string, nullable: true}
pushToken: {type: string, nullable: true}
createdAt: {type: string, format: date-time}
lastActiveAt: {type: string, format: date-time, nullable: true}
RecipientDeletionResponse:
type: object
properties:
success: {type: boolean}
deletionScheduledAt: {type: string, format: date-time}
RecipientExportResponse:
type: object
properties:
success: {type: boolean}
exportRequestId: {type: string}
queuedAt: {type: string, format: date-time}
status: {type: string, enum: [queued]}
deliveryChannel: {type: string, enum: [email]}
NotificationPreferences:
type: object
properties:
deliveryScheduled: {type: boolean}
oneHourBefore: {type: boolean}
liveTracking: {type: boolean}
delivered: {type: boolean}
failed: {type: boolean}
addressReview: {type: boolean}
dataExport: {type: boolean}
NotificationPreferencesUpdateRequest:
type: object
properties:
deliveryScheduled: {type: boolean}
oneHourBefore: {type: boolean}
liveTracking: {type: boolean}
delivered: {type: boolean}
failed: {type: boolean}
addressReview: {type: boolean}
dataExport: {type: boolean}
NotificationHistoryItem:
type: object
properties:
notificationId: {type: string}
trigger:
type: string
enum:
[
delivery_scheduled,
one_hour_before,
live_tracking,
delivered,
failed,
address_review,
data_export,
]
title: {type: string}
body: {type: string}
createdAt: {type: string, format: date-time}
readAt: {type: string, format: date-time, nullable: true}
NotificationListResponse:
type: object
properties:
notifications:
type: array
items: {$ref: '#/components/schemas/NotificationHistoryItem'}
PushTokenRequest:
type: object
required: [pushToken]
properties:
pushToken: {type: string}
PushTokenResponse:
type: object
properties:
success: {type: boolean}
pushToken: {type: string}
CarrierRegisterRequest:
type: object
required: [carrierName]
properties:
carrierId: {type: string}
carrierName: {type: string}
carrierLogoUrl: {type: string, format: uri}
webhookUrl: {type: string, format: uri}
CarrierProfile:
type: object
properties:
carrierId: {type: string}
carrierName: {type: string}
carrierLogoUrl: {type: string, format: uri, nullable: true}
webhookUrl: {type: string, format: uri, nullable: true}
createdAt: {type: string, format: date-time}
updatedAt: {type: string, format: date-time}
apiKeyCount: {type: integer}
CarrierUpdateRequest:
type: object
properties:
carrierName: {type: string}
carrierLogoUrl: {type: string, format: uri}
CarrierApiKeyCreateResponse:
type: object
properties:
keyId: {type: string}
apiKey: {type: string}
createdAt: {type: string, format: date-time}
CarrierApiKeyDeleteResponse:
type: object
properties:
success: {type: boolean}
keyId: {type: string}
CarrierWebhookUpdateRequest:
type: object
required: [webhookUrl]
properties:
webhookUrl: {type: string, format: uri}
CarrierInviteListItem:
type: object
properties:
tokenId: {type: string}
shipmentId: {type: string}
status: {type: string, enum: [pending, claimed, expired]}
createdAt: {type: string, format: date-time}
expiresAt: {type: string, format: date-time}
openedAt: {type: string, format: date-time, nullable: true}
claimedAt: {type: string, format: date-time, nullable: true}
CarrierInviteListResponse:
type: object
properties:
invites:
type: array
items: {$ref: '#/components/schemas/CarrierInviteListItem'}
CarrierAnalyticsResponse:
type: object
properties:
sent: {type: integer}
opened: {type: integer}
claimed: {type: integer}
completed: {type: integer}
Address:
type: object
required: [addressId, label, streetAddress, coordinateTier]
properties:
addressId: {type: string}
label: {type: string}
streetAddress: {type: string}
city: {type: string}
postcode: {type: string}
country: {type: string}
geocodedLat: {type: number}
geocodedLng: {type: number}
precisionPinLat: {type: number, nullable: true}
precisionPinLng: {type: number, nullable: true}
coordinateTier: {type: integer, minimum: 1, maximum: 5}
geocodeConfidence: {type: number, minimum: 0, maximum: 1}
geocodeProvider: {type: string, nullable: true}
addressHash: {type: string}
what3words: {type: string, nullable: true}
plusCode: {type: string, nullable: true}
deliveryNotes: {type: string, nullable: true}
parkingInstructions: {type: string, nullable: true}
accessCode:
{
type: string,
nullable: true,
description: 'Masked in recipient responses. Returned to drivers only with read:access_code consent.',
}
neighbourName: {type: string, nullable: true}
neighbourAddress: {type: string, nullable: true}
neighbourUnit: {type: string, nullable: true}
neighbourAvailable: {type: boolean}
preferredWindow:
{type: string, enum: [morning, afternoon, evening, any]}
isDefault: {type: boolean}
activeIntelligenceId: {type: string, nullable: true}
entrancePhotos:
type: array
maxItems: 3
items: {$ref: '#/components/schemas/AddressEntrancePhoto'}
createdAt: {type: string, format: date-time}
updatedAt: {type: string, format: date-time}
AddressEntrancePhoto:
type: object
required: [photoId, objectKey, contentType, status, createdAt]
properties:
photoId: {type: string}
objectKey: {type: string}
contentType: {type: string, enum: [image/jpeg, image/png, image/webp]}
fileName: {type: string, nullable: true}
status: {type: string, enum: [pending, ready]}
createdAt: {type: string, format: date-time}
uploadedAt: {type: string, format: date-time, nullable: true}
viewUrl: {type: string, format: uri, nullable: true}
AddressEntrancePhotoUploadRequest:
type: object
required: [contentType]
properties:
contentType: {type: string, enum: [image/jpeg, image/png, image/webp]}
fileName: {type: string}
AddressEntrancePhotoUploadResponse:
type: object
required: [expiresAt, photo, uploadHeaders, uploadMethod, uploadUrl]
properties:
expiresAt: {type: string, format: date-time}
photo: {$ref: '#/components/schemas/AddressEntrancePhoto'}
uploadHeaders:
type: object
required: [content-type]
properties:
content-type: {type: string}
uploadMethod: {type: string, enum: [PUT]}
uploadUrl: {type: string, format: uri}
AddressUpsertRequest:
type: object
required: [label, streetAddress, coordinateTier]
properties:
addressId: {type: string}
label: {type: string}
streetAddress: {type: string}
city: {type: string}
postcode: {type: string}
country: {type: string}
geocodedLat: {type: number}
geocodedLng: {type: number}
precisionPinLat: {type: number, nullable: true}
precisionPinLng: {type: number, nullable: true}
coordinateTier: {type: integer, minimum: 1, maximum: 5}
geocodeConfidence: {type: number, minimum: 0, maximum: 1}
what3words: {type: string, nullable: true}
plusCode: {type: string, nullable: true}
deliveryNotes: {type: string, nullable: true}
parkingInstructions: {type: string, nullable: true}
accessCode: {type: string, nullable: true}
neighbourName: {type: string, nullable: true}
neighbourAddress: {type: string, nullable: true}
neighbourUnit: {type: string, nullable: true}
neighbourAvailable: {type: boolean}
preferredWindow:
{type: string, enum: [morning, afternoon, evening, any]}
isDefault: {type: boolean}
AddressListResponse:
type: object
properties:
addresses:
type: array
items: {$ref: '#/components/schemas/Address'}
AddressIntelligence:
type: object
properties:
addressHash: {type: string}
correctedLat: {type: number, nullable: true}
correctedLng: {type: number, nullable: true}
correctedParkingInstructions: {type: string, nullable: true}
correctedDeliveryNotes: {type: string, nullable: true}
feedbackCount: {type: integer}
positiveCount: {type: integer}
negativeCount: {type: integer}
confidenceAdjustment: {type: number}
aiGeneratedInstruction: {type: string, nullable: true}
lastUpdated: {type: string, format: date-time}
reviewedByDispatcher: {type: boolean}
AddressFeedbackRequest:
type: object
required: [shipmentId, addressHash, feedbackType]
properties:
shipmentId: {type: string}
addressHash: {type: string}
feedbackType:
type: string
enum:
[
correct,
wrong_entrance,
parking_wrong,
building_number_diff,
access_changed,
other,
]
notes: {type: string, nullable: true}
actualLat: {type: number, nullable: true}
actualLng: {type: number, nullable: true}
AddressFeedbackResponse:
type: object
properties:
success: {type: boolean}
addressHash: {type: string}
feedbackCount: {type: integer}
AddressOwnerNotifyResponse:
type: object
properties:
success: {type: boolean}
addressHash: {type: string}
notifiedCount: {type: integer}
VerificationIssueRequest:
type: object
required: [shipmentId]
properties:
shipmentId: {type: string}
VerificationIssueResponse:
type: object
properties:
verificationId: {type: string}
code: {type: string}
qrPayload: {type: string}
expiresAt: {type: string, format: date-time}
oneTime: {type: boolean}
VerificationVerifyRequest:
type: object
properties:
presentedCode: {type: string}
scannedJws: {type: string}
lat: {type: number}
lng: {type: number}
VerificationVerifyResponse:
type: object
properties:
valid: {type: boolean}
consumedAt: {type: string, format: date-time}
ConsentRecord:
type: object
properties:
carrierId: {type: string}
carrierName: {type: string}
carrierLogoUrl: {type: string, nullable: true}
scope: {type: array, items: {type: string}}
grantedAt: {type: string, format: date-time}
expiresAt: {type: string, format: date-time, nullable: true}
revokedAt: {type: string, format: date-time, nullable: true}
grantMethod: {type: string, enum: [invite, manual]}
auditTrail:
type: array
items:
type: object
properties:
action: {type: string, enum: [granted, updated, revoked]}
consentPresentation:
{type: string, enum: [default_bundle, manual]}
ip: {type: string, nullable: true}
scope: {type: array, items: {type: string}}
timestamp: {type: string, format: date-time}
ConsentListResponse:
type: object
properties:
consents:
type: array
items: {$ref: '#/components/schemas/ConsentRecord'}
ConsentUpdateRequest:
type: object
required: [scope]
properties:
scope: {type: array, items: {type: string}}
ConsentWithdrawAllResponse:
type: object
properties:
success: {type: boolean}
revokedCount: {type: integer}
CarrierRecipientConsentResponse:
type: object
properties:
active: {type: boolean}
carrierId: {type: string}
consentScopes: {type: array, items: {type: string}}
revokedAt: {type: string, format: date-time, nullable: true}
userId: {type: string}
DriverContextResponse:
type: object
required: [shipmentId, recipientProfileFound, consentValid]
properties:
shipmentId: {type: string}
recipientProfileFound: {type: boolean}
consentValid: {type: boolean}
contextRevision: {type: string}
address:
type: object
nullable: true
properties:
formattedAddress: {type: string}
deliveryLat: {type: number}
deliveryLng: {type: number}
coordinateTier: {type: integer}
coordinateTierLabel: {type: string}
geocodeConfidence: {type: number}
what3words: {type: string, nullable: true}
plusCode: {type: string, nullable: true}
deliveryInstructions:
type: object
nullable: true
properties:
notes: {type: string, nullable: true}
parkingInstructions: {type: string, nullable: true}
accessCode: {type: string, nullable: true}
preferredWindow: {type: string, nullable: true}
neighbourFallback:
type: object
nullable: true
properties:
available: {type: boolean}
name: {type: string, nullable: true}
address: {type: string, nullable: true}
unit: {type: string, nullable: true}
additionalNote: {type: string, nullable: true}
addressIntelligence:
type: object
nullable: true
properties:
hasCorrections: {type: boolean}
correctionNote: {type: string, nullable: true}
correctedLat: {type: number, nullable: true}
correctedLng: {type: number, nullable: true}
confidence: {type: number}
liveLocationAvailable: {type: boolean}
liveSessionId: {type: string, nullable: true}
entrancePhotos:
type: array
items:
type: object
required: [photoId, uploadedAt, viewUrl]
properties:
photoId: {type: string}
uploadedAt: {type: string, format: date-time}
viewUrl: {type: string, format: uri}
meta:
type: object
properties:
profileLastUpdated:
{type: string, format: date-time, nullable: true}
consentGrantedAt: {type: string, format: date-time, nullable: true}
consentScopes: {type: array, items: {type: string}}
DeliveryFeedItem:
type: object
properties:
deliveryId: {type: string}
carrierId: {type: string}
carrierName: {type: string}
carrierLogoUrl: {type: string, nullable: true}
trackingNumber: {type: string, nullable: true}
status:
{
type: string,
enum:
[
scheduled,
in_transit,
out_for_delivery,
delivered,
attempted,
returned,
],
}
statusHistory:
type: array
items:
type: object
properties:
status:
{
type: string,
enum:
[
scheduled,
in_transit,
out_for_delivery,
delivered,
attempted,
returned,
],
}
timestamp: {type: string, format: date-time}
note: {type: string, nullable: true}
expectedDate: {type: string, nullable: true}
deliveredAt: {type: string, format: date-time, nullable: true}
addressId: {type: string, nullable: true}
pinpointShipmentId: {type: string}
lastUpdated: {type: string, format: date-time}
DeliveryFeedListResponse:
type: object
properties:
deliveries:
type: array
items: {$ref: '#/components/schemas/DeliveryFeedItem'}
InviteCreateRequest:
type: object
required: [idempotencyKey, shipmentId, recipientEmail, carrierBrand]
properties:
idempotencyKey: {type: string}
shipmentId: {type: string}
recipientEmail: {type: string, format: email}
carrierBrand: {type: string}
expectedDeliveryDate: {type: string, format: date}
deliveryChannel: {type: string, enum: [email], default: email}
defaultAddressId: {type: string}
InviteCreateResponse:
type: object
properties:
tokenId: {type: string}
deepLink: {type: string, format: uri}
expiresAt: {type: string, format: date-time}
status: {type: string, enum: [pending, claimed, expired]}
InvitePublicLookupResponse:
type: object
properties:
tokenId: {type: string}
status: {type: string, enum: [pending, claimed, expired]}
carrierName: {type: string}
carrierLogoUrl: {type: string, nullable: true}
shipmentReference: {type: string}
expectedDeliveryDate: {type: string, nullable: true}
InviteClaimResponse:
type: object
properties:
success: {type: boolean}
consentGranted: {type: boolean}
consentScopes: {type: array, items: {type: string}}
InviteStatusResponse:
type: object
properties:
tokenId: {type: string}
status: {type: string, enum: [pending, claimed, expired]}
expiresAt: {type: string, format: date-time}
claimedAt: {type: string, format: date-time, nullable: true}
LiveSessionCreateRequest:
type: object
required: [shipmentId]
properties:
shipmentId: {type: string}
driverName: {type: string}
stopsAhead: {type: integer}
triggerChannel: {type: string, enum: [push, silent], default: push}
LiveSessionCreateResponse:
type: object
properties:
sessionId: {type: string}
customerToken: {type: string}
driverToken: {type: string}
wsEndpoint: {type: string, format: uri}
expiresAt: {type: string, format: date-time}
customerNotified: {type: boolean}
LiveSessionStatusResponse:
type: object
properties:
sessionId: {type: string}
shipmentId: {type: string}
recipientUserId: {type: string}
carrierId: {type: string}
status: {type: string, enum: [active, ended]}
endReason:
{
type: string,
enum: [delivered, timeout, customer_ended, driver_ended, error],
nullable: true,
}
createdAt: {type: string, format: date-time}
expiresAt: {type: string, format: date-time}
endedAt: {type: string, format: date-time, nullable: true}
driverName: {type: string, nullable: true}
stopsAhead: {type: integer, nullable: true}
triggerChannel: {type: string, enum: [push, silent]}
customerNotified: {type: boolean}
customerTokenHash: {type: string}
driverTokenHash: {type: string}
messages:
type: array
items: {$ref: '#/components/schemas/QuickReplyMessage'}
LiveSessionEndResponse:
type: object
properties:
success: {type: boolean}
sessionId: {type: string}
reason:
{
type: string,
enum: [delivered, timeout, customer_ended, driver_ended, error],
}
QuickReplyRequest:
type: object
required: [replyCode]
properties:
replyCode:
{
type: string,
enum:
[
ON_MY_WAY,
FIVE_MIN,
USE_SIDE_DOOR,
LEAVE_SAFE,
IM_HOME,
ARRIVED,
],
}
QuickReplyMessage:
type: object
properties:
messageId: {type: string}
sessionId: {type: string}
from: {type: string, enum: [customer, driver]}
replyCode:
{
type: string,
enum:
[
ON_MY_WAY,
FIVE_MIN,
USE_SIDE_DOOR,
LEAVE_SAFE,
IM_HOME,
ARRIVED,
],
}
ts: {type: string, format: date-time}
QuickReplyMessageListResponse:
type: object
properties:
messages:
type: array
items: {$ref: '#/components/schemas/QuickReplyMessage'}
GeocodeRequest:
type: object
required: [address]
properties:
address: {type: string}
countryCode: {type: string, minLength: 2, maxLength: 2}
ReverseGeocodeRequest:
type: object
required: [lat, lng]
properties:
lat: {type: number}
lng: {type: number}
GeocodeResponse:
type: object
properties:
formattedAddress: {type: string}
lat: {type: number}
lng: {type: number}
confidence: {type: number}
coordinateTier: {type: integer}
needsManualConfirmation: {type: boolean}
agreement: {type: string, enum: [high, medium, low, single]}
addressHash: {type: string}
intelligence: {type: object, properties: {available: {type: boolean}}}
providers:
type: object
additionalProperties:
type: object
properties:
lat: {type: number}
lng: {type: number}
confidence: {type: number}
PlaceSearchResponse:
type: object
properties:
results:
type: array
items:
type: object
properties:
formattedAddress: {type: string}
lat: {type: number}
lng: {type: number}
addressHash: {type: string}
CarrierEventRequest:
type: object
required: [eventType, shipmentId, status, timestamp]
properties:
eventId: {type: string}
eventType:
{
type: string,
enum:
[
DELIVERY_CREATED,
STATUS_UPDATED,
DELIVERY_COMPLETED,
DELIVERY_FAILED,
],
}
shipmentId: {type: string}
recipientPhone: {type: string}
recipientEmail: {type: string, format: email}
trackingNumber: {type: string}
status:
{
type: string,
enum:
[
scheduled,
in_transit,
out_for_delivery,
delivered,
attempted,
returned,
],
}
statusNote: {type: string}
expectedDate: {type: string, format: date}
timestamp: {type: string, format: date-time}
CarrierEventResponse:
type: object
properties:
eventAccepted: {type: boolean}
shipmentId: {type: string}
deliveryId: {type: string}
paths:
/v1/invite:
post:
operationId: createInvite
security: [{CarrierApiKey: []}]
summary: Generate an invite token for a shipment recipient
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InviteCreateRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/InviteCreateResponse'}
/v1/invite/{token}:
get:
operationId: getInvite
security: []
summary: Validate invite token and return carrier context
parameters:
- name: token
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/InvitePublicLookupResponse'}
'404':
description: Token not found or expired
/v1/invite/{token}/claim:
post:
operationId: claimInvite
security: [{CognitoRecipient: []}]
summary: Claim invite token and grant default consent
parameters:
- name: token
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/InviteClaimResponse'}
/v1/invite/{token}/status:
get:
operationId: getInviteStatus
security: [{CarrierApiKey: []}]
summary: Check whether an invite token is pending, claimed, or expired
parameters:
- name: token
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/InviteStatusResponse'}
/v1/recipient/me:
get:
operationId: getRecipient
summary: Get own recipient profile
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/RecipientProfile'}
put:
operationId: updateRecipient
summary: Update own profile
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
displayName: {type: string}
preferredLanguage: {type: string}
pushToken: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/RecipientProfile'}
delete:
operationId: deleteRecipient
summary: Initiate account deletion
responses:
'202':
content:
application/json:
schema: {$ref: '#/components/schemas/RecipientDeletionResponse'}
/v1/recipient/me/export:
post:
operationId: requestRecipientExport
summary: Queue a GDPR data export for the authenticated recipient
responses:
'202':
content:
application/json:
schema: {$ref: '#/components/schemas/RecipientExportResponse'}
/v1/recipient/me/notifications:
get:
operationId: listRecipientNotifications
summary: List notification history for the authenticated recipient
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/NotificationListResponse'}
/v1/recipient/me/notification-preferences:
put:
operationId: updateRecipientNotificationPreferences
summary: Update recipient notification preferences
requestBody:
required: true
content:
application/json:
schema:
{
$ref: '#/components/schemas/NotificationPreferencesUpdateRequest',
}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/NotificationPreferences'}
/v1/recipient/me/push-token:
post:
operationId: registerRecipientPushToken
summary: Register or update the recipient push token
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/PushTokenRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/PushTokenResponse'}
/v1/recipient/me/addresses:
get:
operationId: listAddresses
summary: List saved delivery addresses
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/AddressListResponse'}
post:
operationId: createAddress
summary: Add a new delivery address
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AddressUpsertRequest'}
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
/v1/recipient/me/addresses/{addressId}:
get:
operationId: getAddress
summary: Get a saved delivery address
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
put:
operationId: updateAddress
summary: Update a saved delivery address
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AddressUpsertRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
delete:
operationId: deleteAddress
summary: Delete a saved delivery address
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema:
type: object
properties:
success: {type: boolean}
/v1/recipient/me/addresses/{addressId}/default:
post:
operationId: setDefaultAddress
summary: Set a saved delivery address as default
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
/v1/recipient/me/addresses/{addressId}/intelligence:
get:
operationId: getAddressIntelligence
summary: Get address intelligence summary
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/AddressIntelligence'}
/v1/recipient/me/addresses/{addressId}/entrance-photos/upload-url:
post:
operationId: createAddressEntrancePhotoUploadUrl
summary: Create a presigned upload URL for an entrance photo
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema:
{$ref: '#/components/schemas/AddressEntrancePhotoUploadRequest'}
responses:
'200':
content:
application/json:
schema:
{
$ref: '#/components/schemas/AddressEntrancePhotoUploadResponse',
}
/v1/recipient/me/addresses/{addressId}/entrance-photos/{photoId}/complete:
post:
operationId: completeAddressEntrancePhotoUpload
summary: Mark a previously uploaded entrance photo as ready for driver use
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
- name: photoId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
/v1/recipient/me/addresses/{addressId}/entrance-photos/{photoId}:
delete:
operationId: deleteAddressEntrancePhoto
summary: Remove an entrance photo from a saved address
parameters:
- name: addressId
in: path
required: true
schema: {type: string}
- name: photoId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/Address'}
/v1/recipient/me/consents:
get:
operationId: listConsents
summary: List recipient consents
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentListResponse'}
/v1/recipient/me/consents/{carrierId}:
get:
operationId: getConsent
summary: Get a single recipient consent
parameters:
- name: carrierId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentRecord'}
put:
operationId: updateConsent
summary: Update scopes for a recipient consent
parameters:
- name: carrierId
in: path
required: true
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentUpdateRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentRecord'}
delete:
operationId: revokeConsent
summary: Revoke a recipient consent
parameters:
- name: carrierId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentRecord'}
/v1/recipient/me/consents/withdraw-all:
post:
operationId: withdrawAllConsents
summary: Revoke all recipient consents
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/ConsentWithdrawAllResponse'}
/v1/carrier/register:
post:
operationId: registerCarrier
security: [{PlatformAdminJwt: []}]
summary: Register a carrier for PinPoint API access
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierRegisterRequest'}
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierProfile'}
/v1/carrier/me:
get:
operationId: getCarrierProfile
security: [{CarrierApiKey: []}]
summary: Get the authenticated carrier profile
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierProfile'}
put:
operationId: updateCarrierProfile
security: [{CarrierApiKey: []}]
summary: Update the authenticated carrier profile
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierUpdateRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierProfile'}
/v1/carrier/me/api-keys:
post:
operationId: createCarrierApiKey
security: [{CarrierApiKey: []}]
summary: Generate a new carrier API key
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierApiKeyCreateResponse'}
/v1/carrier/me/api-keys/{keyId}:
delete:
operationId: revokeCarrierApiKey
security: [{CarrierApiKey: []}]
summary: Revoke a carrier API key
parameters:
- name: keyId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierApiKeyDeleteResponse'}
/v1/carrier/me/webhook:
put:
operationId: updateCarrierWebhook
security: [{CarrierApiKey: []}]
summary: Update the carrier webhook URL
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierWebhookUpdateRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierProfile'}
/v1/carrier/me/invites:
get:
operationId: listCarrierInvites
security: [{CarrierApiKey: []}]
summary: List invites sent by the authenticated carrier
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierInviteListResponse'}
/v1/carrier/me/analytics:
get:
operationId: getCarrierAnalytics
security: [{CarrierApiKey: []}]
summary: Get invite funnel analytics for the authenticated carrier
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierAnalyticsResponse'}
/v1/carrier/me/recipients/{userId}/consent:
get:
operationId: getCarrierRecipientConsent
security: [{CarrierApiKey: []}]
summary: Get consent status for a recipient under the current carrier
parameters:
- name: userId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema:
{$ref: '#/components/schemas/CarrierRecipientConsentResponse'}
/v1/recipient/me/deliveries:
get:
operationId: listDeliveries
summary: List recipient deliveries
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/DeliveryFeedListResponse'}
/v1/recipient/me/deliveries/{deliveryId}:
get:
operationId: getDelivery
summary: Get delivery detail
parameters:
- name: deliveryId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/DeliveryFeedItem'}
/v1/driver-context/{shipmentId}:
get:
operationId: getDriverContext
security: [{CarrierApiKey: []}, {DriverJwt: []}]
summary: Get full driver context package for a shipment
parameters:
- name: shipmentId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/DriverContextResponse'}
/v1/driver-context/by-recipient/{userId}:
get:
operationId: getDriverContextByRecipient
security: [{CarrierApiKey: []}]
summary: Get driver context using the recipient default address
parameters:
- name: userId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/DriverContextResponse'}
/v1/live-session:
post:
operationId: createLiveSession
security: [{CarrierApiKey: []}]
summary: Create a live location session
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/LiveSessionCreateRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/LiveSessionCreateResponse'}
/v1/live-session/{sessionId}:
get:
operationId: getLiveSession
security: [{CarrierApiKey: []}, {LiveSessionJwt: []}]
summary: Get live session status
parameters:
- name: sessionId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/LiveSessionStatusResponse'}
delete:
operationId: endLiveSession
security: [{CarrierApiKey: []}]
summary: End a live session
parameters:
- name: sessionId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/LiveSessionEndResponse'}
/v1/live-session/by-shipment/{shipmentId}:
get:
operationId: getLiveSessionByShipment
security: [{CarrierApiKey: []}]
summary: Get active or ended live session by shipment
parameters:
- name: shipmentId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/LiveSessionStatusResponse'}
/v1/live-session/{sessionId}/messages:
get:
operationId: listLiveSessionMessages
security: [{LiveSessionJwt: []}]
summary: List quick replies for a live session
parameters:
- name: sessionId
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema:
{$ref: '#/components/schemas/QuickReplyMessageListResponse'}
post:
operationId: createLiveSessionMessage
security: [{LiveSessionJwt: []}]
summary: Send a quick reply for a live session
parameters:
- name: sessionId
in: path
required: true
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/QuickReplyRequest'}
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/QuickReplyMessage'}
/v1/geocode:
post:
operationId: geocode
security: [{CognitoRecipient: []}, {CarrierApiKey: []}]
summary: Geocode an address using the local deterministic provider for development
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/GeocodeRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/GeocodeResponse'}
/v1/geocode/reverse:
post:
operationId: reverseGeocode
security: [{CognitoRecipient: []}]
summary: Reverse geocode a latitude and longitude
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ReverseGeocodeRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/GeocodeResponse'}
/v1/places/search:
get:
operationId: searchPlaces
security: [{CognitoRecipient: []}]
summary: Search places for address entry assistance
parameters:
- name: q
in: query
required: false
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/PlaceSearchResponse'}
/v1/what3words/{words}:
get:
operationId: resolveWhat3Words
security: [{CognitoRecipient: []}]
summary: Resolve a What3Words string to coordinates
parameters:
- name: words
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/GeocodeResponse'}
/v1/pluscode/{code}:
get:
operationId: resolvePlusCode
security: [{CognitoRecipient: []}]
summary: Resolve a Plus Code to coordinates
parameters:
- name: code
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/GeocodeResponse'}
/v1/address-feedback:
post:
operationId: submitAddressFeedback
security: [{DriverJwt: []}]
summary: Submit delivery outcome feedback for an address
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AddressFeedbackRequest'}
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/AddressFeedbackResponse'}
/v1/address-intelligence/{hash}:
get:
operationId: getAddressIntelligenceByHash
security: [{CarrierApiKey: []}, {DriverJwt: []}]
summary: Get intelligence for a normalized address hash
parameters:
- name: hash
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/AddressIntelligence'}
/v1/address-intelligence/{hash}/notify-owner:
post:
operationId: notifyAddressOwner
security: [{CarrierApiKey: []}]
summary: Notify the address owner that review is needed
parameters:
- name: hash
in: path
required: true
schema: {type: string}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/AddressOwnerNotifyResponse'}
/v1/verification:
post:
operationId: issueVerification
security: [{CarrierApiKey: []}]
summary: Issue a one-time handover verification token
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/VerificationIssueRequest'}
responses:
'201':
content:
application/json:
schema: {$ref: '#/components/schemas/VerificationIssueResponse'}
/v1/verification/{verificationId}/verify:
post:
operationId: verifyVerification
security: [{DriverJwt: []}]
summary: Verify a presented PIN or scanned QR handover token
parameters:
- name: verificationId
in: path
required: true
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/VerificationVerifyRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/VerificationVerifyResponse'}
/v1/carrier-events:
post:
operationId: pushCarrierEvent
security: [{CarrierApiKey: []}]
summary: Push delivery status update to the recipient feed
parameters:
- name: x-pinpoint-signature
in: header
required: true
description: HMAC-SHA256 signature of the raw request body
schema: {type: string}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierEventRequest'}
responses:
'200':
content:
application/json:
schema: {$ref: '#/components/schemas/CarrierEventResponse'}