{"openapi":"3.1.0","info":{"title":"Action AR API","version":"1.1.0","description":"Partner API for managed location-based collectibles and hosted mobile AR."},"servers":[{"url":"https://www.action-tokens.com/api/ar/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Server-side partner API key."}},"schemas":{"ExperienceInput":{"type":"object","required":["title","mediaUrl","mediaType"],"properties":{"externalId":{"type":"string"},"title":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":2000},"mediaUrl":{"type":"string","format":"uri"},"mediaType":{"enum":["image","video","model"]},"thumbnailUrl":{"type":"string","format":"uri"},"ctaLabel":{"type":"string"},"ctaUrl":{"type":"string","format":"uri"},"metadata":{"type":"object","additionalProperties":true}}},"ExperiencePatch":{"type":"object","properties":{"externalId":{"type":"string","nullable":true},"title":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":2000},"mediaUrl":{"type":"string","format":"uri"},"mediaType":{"enum":["image","video","model"]},"thumbnailUrl":{"type":"string","format":"uri","nullable":true},"ctaLabel":{"type":"string","nullable":true},"ctaUrl":{"type":"string","format":"uri","nullable":true},"metadata":{"type":"object","additionalProperties":true},"isActive":{"type":"boolean"}}},"PinInput":{"type":"object","required":["experienceId","latitude","longitude"],"properties":{"experienceId":{"type":"string","format":"uuid"},"externalId":{"type":"string","description":"If a pin with this externalId exists, POST upserts it instead of creating a duplicate."},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number"},"title":{"type":"string","maxLength":120},"caption":{"type":"string","maxLength":500},"metadata":{"type":"object","additionalProperties":true,"description":"Partner-owned JSON (brand_id, media_id, created_by, is_user_drop, …). Returned on nearby and collections."},"collectionRadiusM":{"type":"integer","minimum":10,"maximum":50000,"default":100},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"maxCollections":{"type":"integer","minimum":1}}},"PinPatch":{"type":"object","properties":{"experienceId":{"type":"string","format":"uuid"},"externalId":{"type":"string","nullable":true},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number","nullable":true},"title":{"type":"string","nullable":true},"caption":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":true},"collectionRadiusM":{"type":"integer","minimum":10,"maximum":50000},"startsAt":{"type":"string","format":"date-time","nullable":true},"endsAt":{"type":"string","format":"date-time","nullable":true},"maxCollections":{"type":"integer","minimum":1,"nullable":true},"isActive":{"type":"boolean"}}},"CollectionInput":{"type":"object","required":["pinId","externalUserId","latitude","longitude"],"properties":{"pinId":{"type":"string","format":"uuid"},"externalUserId":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"}}},"LaunchInput":{"type":"object","required":["experienceId","externalUserId"],"properties":{"experienceId":{"type":"string","format":"uuid"},"externalUserId":{"type":"string"}}},"BountyInput":{"type":"object","required":["title","rewardAmount"],"properties":{"title":{"type":"string","maxLength":200},"summary":{"type":"string","maxLength":500},"description":{"type":"string","maxLength":5000},"bountyType":{"type":"string","default":"general"},"rewardAmount":{"type":"number","minimum":0},"rewardToken":{"type":"string","default":"$ACTION"},"rewardCurrency":{"type":"string","default":"ACTION"},"rewardPer":{"type":"string","default":"submission"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"radiusM":{"type":"number","default":50},"address":{"type":"string"},"proofRequired":{"enum":["photo","action_cam","none"],"default":"photo"},"instructions":{"type":"string"},"deliveryMethod":{"type":"string"},"maxClaims":{"type":"integer","minimum":1,"default":5},"expiresAt":{"type":"string","format":"date-time"},"requiresTransactionLink":{"type":"boolean","default":false},"requiresPayoutWallet":{"type":"boolean","default":true},"requiresActionCam":{"type":"boolean","default":false}}}},"parameters":{"listFilters":[{"name":"externalId","in":"query","schema":{"type":"string"}},{"name":"isActive","in":"query","schema":{"type":"boolean"}},{"name":"metadata","in":"query","schema":{"type":"string"},"description":"JSON object matched with jsonb contains, e.g. {\"brand_id\":\"abc\"}"},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}]}},"paths":{"/health":{"get":{"summary":"Verify credentials and capabilities","responses":{"200":{"description":"Healthy"},"401":{"description":"Invalid key"}}}},"/experiences":{"get":{"summary":"List experiences","parameters":[{"name":"externalId","in":"query","schema":{"type":"string"}},{"name":"isActive","in":"query","schema":{"type":"boolean"}},{"name":"metadata","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Experience list with nextCursor"}}},"post":{"summary":"Create or upsert an experience by externalId","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExperienceInput"}}}},"responses":{"200":{"description":"Upserted"},"201":{"description":"Created"}}}},"/experiences/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Experience UUID or externalId"}],"get":{"summary":"Get an experience","responses":{"200":{"description":"Experience"},"404":{"description":"Not found"}}},"patch":{"summary":"Update title, media, or metadata","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExperiencePatch"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}}},"/pins":{"get":{"summary":"List pins","parameters":[{"name":"externalId","in":"query","schema":{"type":"string"}},{"name":"isActive","in":"query","schema":{"type":"boolean"}},{"name":"bbox","in":"query","schema":{"type":"string"},"description":"minLng,minLat,maxLng,maxLat"},{"name":"metadata","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Pin list with nextCursor"}}},"post":{"summary":"Place a pin. Re-POSTing the same externalId moves/updates that pin.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinInput"}}}},"responses":{"200":{"description":"Upserted"},"201":{"description":"Created"}}}},"/pins/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Pin UUID or externalId"}],"get":{"summary":"Get a pin","responses":{"200":{"description":"Pin"},"404":{"description":"Not found"}}},"patch":{"summary":"Move or update a pin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinPatch"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found"}}},"delete":{"summary":"Remove a pin. Deactivates it if collections already exist.","responses":{"200":{"description":"Deleted or deactivated"},"404":{"description":"Not found"}}}},"/pins/nearby":{"get":{"summary":"Find nearby active pins, including media_url and pin metadata","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number"}},{"name":"lng","in":"query","required":true,"schema":{"type":"number"}},{"name":"radius","in":"query","schema":{"type":"number","maximum":100000}}],"responses":{"200":{"description":"Pins ordered by distance"}}}},"/collections":{"get":{"summary":"List collections. Omit externalUserId for the partner-wide admin list.","parameters":[{"name":"externalUserId","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Collection list with pin coords and collected_lat/lng"}}},"post":{"summary":"Collect a pin after server-side range validation (radius + partner GPS tolerance, default 15m)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionInput"}}}},"responses":{"201":{"description":"Collected"},"403":{"description":"Out of range"},"409":{"description":"Sold out"}}}},"/launch":{"post":{"summary":"Optional 15-minute hosted AR launch URL. Partners may use their own AR viewer with media_url from nearby instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchInput"}}}},"responses":{"200":{"description":"Launch URL"},"403":{"description":"Experience not collected"}}}},"/bounties":{"get":{"summary":"List bounties this partner created","responses":{"200":{"description":"Bounty list"}}},"post":{"summary":"Create a bounty on the shared map","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BountyInput"}}}},"responses":{"201":{"description":"Created"}}}},"/bounties/nearby":{"get":{"summary":"Find nearby active bounties on the community map","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number"}},{"name":"lng","in":"query","required":true,"schema":{"type":"number"}},{"name":"radius","in":"query","schema":{"type":"number","maximum":100000}},{"name":"mine","in":"query","schema":{"enum":["true","false"]}}],"responses":{"200":{"description":"Bounties ordered by distance"}}}}}}