{"openapi":"3.1.0","info":{"title":"Food Integrity Project API: v1 compatibility","version":"1.5-fipos","summary":"Connect's catalog, certificate and community APIs, and the Salesforce TA API v1.5, answered by FIP-OS.","description":"These are the APIs partners and technical administrators call today, answered by FIP-OS exactly as they answer now, so you can switch hosts first and move to v2 at your own pace. Both work on the same records.\n\n- **Catalog v1, certificates v1, community:** change the host from `connect.nongmoproject.org` to this one. Nothing else.\n- **TA API v1.5:** change your login host to this one; `instance_url` then points here. Staff set up your key's sign-in first.\n\nEach operation says what FIP-OS changed and the v2 call to move to. The full guide: https://fip-os-api.vercel.app/docs/guides/moving-from-v1."},"servers":[{"url":"https://fip-os-api.vercel.app","description":"FIP-OS"}],"tags":[{"name":"Catalog v1","description":"Connect's Verified Products API. Without a token you see only listed products, 60 calls an hour; with a FIP-OS token (catalog.read), 20,000 an hour and the token-only fields. Move to `/v2/catalog/*`."},{"name":"Certificates v1","description":"Connect's certificate (COV) API. Each request becomes a lasting link to today's certificate, ready at once. Also at the old `/api/1.1/wf/get_summary_cov`, `get_custom_cov_summary` and `get_cov_pdf`. Move to `POST /v2/certificates/pdf`."},{"name":"Community","description":"Connect's community API: \"please verify this\" requests and a barcode's demand. TAs see the demand for their products in `GET /v2/demand`."},{"name":"TA API v1.5","description":"The Salesforce TA API, at this host: the same paths, TA-ID header, bare-array bodies and `{status, objList}` answers. Writes are checked as v2's are, and go to Salesforce the same way. Move resource by resource to v2 (see each operation)."}],"security":[{},{"bearerAuth":[]}],"paths":{"/api/v1/catalog/products":{"get":{"tags":["Catalog v1"],"operationId":"v1ListProducts","summary":"Search verified products","description":"Connect's product search: 20 a page (up to 100), sorted by product ID. A `q` of 6 to 14 digits is an exact barcode; otherwise it matches words in the product name, a package code or the brand. **Changed:** without a token, listed products only; each line adds `status`, `certificate_number`, `valid_to` and `listed`. **v2:** `GET /v2/catalog/products`.","parameters":[{"name":"q","in":"query","description":"Words, or a barcode (6 to 14 digits, exact)","schema":{"type":"string"},"example":"granola"},{"name":"type","in":"query","description":"A program","schema":{"type":"string","enum":["nongmo","nonupf","both"]}},{"name":"status","in":"query","description":"With a token: verified, hold, withdrawn or all (default all). Without one, always verified","schema":{"type":"string","enum":["verified","hold","withdrawn","all"]}},{"name":"category","in":"query","description":"A category code (repeat for more)","schema":{"type":"array","items":{"type":"string"}},"explode":true},{"name":"how_sold","in":"query","description":"A how-sold category code (repeat for more)","schema":{"type":"array","items":{"type":"string"}},"explode":true},{"name":"cert_group","in":"query","description":"A certificate group","schema":{"type":"string"}},{"name":"single_ingredient","in":"query","description":"true for single-ingredient products only","schema":{"type":"string","enum":["true"]}},{"name":"new_since","in":"query","description":"First verified on or after (YYYY-MM-DD)","schema":{"type":"string","format":"date"}},{"name":"brand_id","in":"query","description":"A brand ID","schema":{"type":"string"}},{"name":"context","in":"query","description":"scan when a person scanned a barcode (counts toward demand); anything else is a refresh","schema":{"type":"string","enum":["scan","refresh"]}},{"name":"page","in":"query","description":"Page, from 1","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","description":"1 to 100","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":[{"product_id":"2-12345-00001","product_name":"Example Oat Crackers","brand_id":"123456","brand_name":"Example Brand","brand_logo_url":"https://api.foodintegrityproject.org/brand-logos/123456","verification_types":["nongmo"],"categories":["Crackers"],"package_codes":[{"code":"012345678905","type":"upc_a"}],"status":"verified","certificate_number":"C-654321-2026","valid_to":"2027-02-28","listed":true}],"meta":{"total":58825,"page":1,"per_page":20,"authenticated":false}}}}},"429":{"description":"Over the hourly limit (X-RateLimit-* headers)","content":{"application/json":{"example":{"error":"Rate limit exceeded"}}}}}}},"/api/v1/catalog/products/{product_id}":{"get":{"tags":["Catalog v1"],"operationId":"v1GetProduct","summary":"Get a product","description":"One product by its TA product ID, with `brand_url`. **Changed:** without a token, listed products only. **v2:** `GET /v2/catalog/products/{id}`.","parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string"},"example":"2-12345-00001"}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"product_id":"2-12345-00001","product_name":"Example Oat Crackers","brand_id":"123456","brand_name":"Example Brand","brand_logo_url":"https://api.foodintegrityproject.org/brand-logos/123456","verification_types":["nongmo"],"categories":["Crackers"],"package_codes":[{"code":"012345678905","type":"upc_a"}],"status":"verified","certificate_number":"C-654321-2026","valid_to":"2027-02-28","listed":true,"brand_url":"https://example.com","ingredients":null,"original_verification_date":"2019-03-15","single_ingredient":false,"other_certifications":["Organic"],"package_info":[{"code":"012345678905","type":"upc_a","size":8,"unit":"Ounces","package_type":"Box","channel":"Retail","normalized_code":"00012345678905"}]}}}}},"404":{"description":"Not found","content":{"application/json":{"example":{"error":"Product not found"}}}}}}},"/api/v1/catalog/brands":{"get":{"tags":["Catalog v1"],"operationId":"v1ListBrands","summary":"Search brands","description":"Brands with products in the catalog, sorted by name, with `brand_sf_id` as Connect gave it. **v2:** `GET /v2/catalog/brands`.","parameters":[{"name":"q","in":"query","description":"Words in the brand name","schema":{"type":"string"}},{"name":"type","in":"query","description":"A program","schema":{"type":"string","enum":["nongmo","nonupf"]}},{"name":"page","in":"query","description":"Page","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","description":"1 to 100","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":[{"brand_sf_id":"a0X000000000001AAA","brand_id":"123456","brand_name":"Example Brand","brand_url":"https://example.com","brand_logo_url":"https://api.foodintegrityproject.org/brand-logos/123456","verification_types":["nongmo"],"product_count":12}],"meta":{"total":4120,"page":1,"per_page":20,"authenticated":false}}}}}}}},"/api/v1/catalog/brands/{brand_id}":{"get":{"tags":["Catalog v1"],"operationId":"v1GetBrand","summary":"Get a brand and its products","description":"A brand with a page of its products. **v2:** `GET /v2/catalog/brands/{number}` and `GET /v2/catalog/products?brand_number=`.","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"string"},"example":"123456"},{"name":"type","in":"query","description":"A program","schema":{"type":"string","enum":["nongmo","nonupf"]}},{"name":"status","in":"query","description":"With a token","schema":{"type":"string","enum":["verified","hold","withdrawn","all"]}},{"name":"page","in":"query","description":"Page","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","description":"1 to 100","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"brand_id":"123456","brand_name":"Example Brand","brand_url":"https://example.com","brand_logo_url":null,"products":[{"product_id":"2-12345-00001","product_name":"Example Oat Crackers","verification_types":["nongmo"],"categories":["Crackers"],"package_codes":[{"code":"012345678905","type":"upc_a"}],"status":"verified","certificate_number":"C-654321-2026","valid_to":"2027-02-28","listed":true}]},"meta":{"total":12,"page":1,"per_page":20,"authenticated":false}}}}},"404":{"description":"No such brand, or `Brand has no verified products`","content":{"application/json":{"example":{"error":"Brand not found"}}}}}}},"/api/v1/catalog/categories":{"get":{"tags":["Catalog v1"],"operationId":"v1ListCategories","summary":"List categories","description":"Categories by certificate group. **v2:** `GET /v2/catalog/categories`.","responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":[{"certificate_group":"Grocery and beverages","categories":[{"id":"a0C000000000001AAA","name":"Crackers","code":"SNACK-03"}]}]}}}}}}},"/api/cov/generate":{"get":{"tags":["Certificates v1"],"operationId":"v1GenerateCov","summary":"Make a certificate","description":"A certificate for a product (`p` and `a`), a certificate number (`c` and `a`), a brand (`b`, optionally with `a`) or a participant (`a`). Ready at once: `pdf_url` always gives today's certificate for the request. `callback_url` gets `{cov_id, status, pdf_url}` and `callback_email` an email with the link. **Changed:** `key` isn't required until notice is given. **v2:** `POST /v2/certificates/pdf`.","security":[{}],"parameters":[{"name":"t","in":"query","description":"Your TA's public number (FoodChain ID 1, NSF 2, Where Food Comes From 3, SCS 5)","schema":{"type":"string"},"required":true,"example":"2"},{"name":"key","in":"query","description":"Your key (not checked until notice)","schema":{"type":"string"}},{"name":"a","in":"query","description":"Participant ID","schema":{"type":"string"},"example":"27123"},{"name":"b","in":"query","description":"Brand ID","schema":{"type":"string"}},{"name":"p","in":"query","description":"TA product ID","schema":{"type":"string"},"example":"2-12345-00001"},{"name":"c","in":"query","description":"Certificate number","schema":{"type":"string"}},{"name":"type","in":"query","description":"Program","schema":{"type":"string","enum":["nongmo","nonupf"],"default":"nongmo"}},{"name":"title","in":"query","description":"A summary's title","schema":{"type":"string"}},{"name":"callback_url","in":"query","description":"Told when it's ready","schema":{"type":"string","format":"uri"}},{"name":"callback_email","in":"query","description":"Emailed when it's ready","schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":"success","cov_id":"01a1c2d3-0000-7000-8000-000000000999","cov_type":"product","products":[{"product_name":"Example Oat Crackers","product_id":"2-12345-00001","brand":"Example Brand","participant_name":"Example Foods Inc.","participant_id":"27123","certificate_no":"C-654321-2026","scope":"Goods for human or pet ingestion or topical application","issued":"Mar 1, 2026","expiration":"Feb 28, 2027","verification_type":"nongmo","risk_status":"standard","single_ingredient":false}],"pdf_url":"https://app.foodintegrityproject.org/cov/Q7Z2K9M4PX","message":"COV generated","engine":"local"}}}},"400":{"description":"A parameter is missing","content":{"application/json":{"example":{"status":"error","message":"Missing required parameter: a, b, p, or c"}}}},"401":{"description":"Unknown TA","content":{"application/json":{"example":{"status":"error","message":"Invalid TA credentials"}}}},"404":{"description":"Nothing to certify","content":{"application/json":{"example":{"status":"error","message":"No verified product found"}}}}}}},"/api/cov/generate-custom":{"get":{"tags":["Certificates v1"],"operationId":"v1GenerateCustomCov","summary":"Make a certificate for a list of products","description":"Up to 500 products by TA product ID (repeat `p`, or `p[]`), under a title. **v2:** `POST /v2/certificates/pdf` with `kind: custom`.","security":[{}],"parameters":[{"name":"t","in":"query","description":"Your TA's public number","schema":{"type":"string"},"required":true,"example":"2"},{"name":"key","in":"query","description":"Your key (not checked until notice)","schema":{"type":"string"}},{"name":"p","in":"query","description":"TA product IDs","schema":{"type":"array","items":{"type":"string"}},"required":true,"explode":true,"example":["2-12345-00001","2-12345-00002"]},{"name":"title","in":"query","description":"The list's title","schema":{"type":"string"},"required":true,"example":"Spring order"},{"name":"type","in":"query","description":"Program","schema":{"type":"string","enum":["nongmo","nonupf"]}},{"name":"callback_url","in":"query","description":"Told when it's ready","schema":{"type":"string"}},{"name":"callback_email","in":"query","description":"Emailed when it's ready","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":"success","cov_id":"01a1c2d3-0000-7000-8000-000000000998","cov_type":"custom","title":"Spring order","products":[{"product_name":"Example Oat Crackers","product_id":"2-12345-00001","brand":"Example Brand","participant_name":"Example Foods Inc.","participant_id":"27123","certificate_no":"C-654321-2026","scope":"Goods for human or pet ingestion or topical application","issued":"Mar 1, 2026","expiration":"Feb 28, 2027","verification_type":"nongmo","risk_status":"standard","single_ingredient":false}],"pdf_url":"https://app.foodintegrityproject.org/cov/R8A3L0N5QY","message":"Custom COV generated","engine":"local"}}}},"400":{"description":"Missing or too many products","content":{"application/json":{"example":{"status":"error","message":"Missing required parameters: p (product IDs) and title"}}}}}}},"/api/cov/retrieve":{"get":{"tags":["Certificates v1"],"operationId":"v1RetrieveCov","summary":"Get a certificate","description":"A certificate by its `cov_id`, including ones Connect made. **v2:** `GET /v2/certificates/pdf/{job}`.","security":[{}],"parameters":[{"name":"id","in":"query","description":"The cov_id","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":"complete","cov_id":"01a1c2d3-0000-7000-8000-000000000999","pdf_url":"https://app.foodintegrityproject.org/cov/Q7Z2K9M4PX"}}}},"404":{"description":"Unknown id","content":{"application/json":{"example":{"status":"error","message":"COV not found"}}}}}}},"/api/cov/generate-zip":{"get":{"tags":["Certificates v1"],"operationId":"v1GenerateCovZip","summary":"Download each product's certificate as a ZIP","description":"A participant's (`a`) or brand's (`b`) products, each certificate a PDF in the ZIP.","security":[{}],"parameters":[{"name":"t","in":"query","description":"Your TA's public number","schema":{"type":"string"},"required":true,"example":"2"},{"name":"a","in":"query","description":"Participant ID","schema":{"type":"string"}},{"name":"b","in":"query","description":"Brand ID","schema":{"type":"string"}},{"name":"type","in":"query","description":"Program","schema":{"type":"string","enum":["nongmo","nonupf"]}}],"responses":{"200":{"description":"The ZIP","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"A parameter is missing","content":{"application/json":{"example":{"error":"Missing parameter: a or b"}}}},"404":{"description":"Nothing to certify","content":{"application/json":{"example":{"error":"No verified products found"}}}}}}},"/api/v1/community/requests":{"post":{"tags":["Community"],"operationId":"v1CommunityRequest","summary":"Ask for a product to be verified","description":"From the public or a partner app: name at least a brand, product, barcode or store. 5,000 an hour per address.","security":[{}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brand_name":{"type":"string"},"brand_id":{"type":"string"},"product_name":{"type":"string"},"product_id":{"type":"string"},"upc":{"type":"string"},"store_name":{"type":"string"},"location":{"type":"string"},"email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"opt_in":{"type":"boolean"},"verification_types":{"type":"array","items":{"type":"string","enum":["nongmo","nonupf"]}},"partner_id":{"type":"string"}}},"example":{"upc":"012345678905","product_name":"Example Oat Crackers","store_name":"Example Market","verification_types":["nongmo"]}}}},"responses":{"201":{"description":"Recorded","content":{"application/json":{"example":{"id":"01a1c2d3-0000-7000-8000-000000000555","created_at":"2026-11-12T18:00:00Z"}}}},"400":{"description":"Missing what it's about","content":{"application/json":{"example":{"error":"At least one of brand_name, brand_id, product_name, product_id, upc, or store_name is required."}}}}}}},"/api/v1/community/activity":{"get":{"tags":["Community"],"operationId":"v1CommunityActivity","summary":"A barcode's demand","description":"How many scans (scan-app look-ups, once per app per 2-second burst) and requests name a barcode. 2,000 an hour per address.","security":[{}],"parameters":[{"name":"upc","in":"query","description":"The barcode","schema":{"type":"string"},"required":true,"example":"012345678905"}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"upc":"012345678905","scans":14,"last_scanned_at":"2026-11-10T17:38:11Z","requests":3,"last_requested_at":"2026-11-02T16:00:00Z"}}}},"400":{"description":"No barcode","content":{"application/json":{"example":{"error":"Query parameter 'upc' is required."}}}}}}},"/services/oauth2/token":{"post":{"tags":["TA API v1.5"],"operationId":"v15Token","summary":"Sign in (JWT bearer)","description":"Salesforce's JWT bearer flow, as you sign in today: an RS256 assertion with `iss` your consumer key, `sub` your API username and `aud` `https://login.salesforce.com` (or this host), signed with your certificate's key. Staff record the consumer key and username on your TA's key, with the certificate's public key. Use `access_token` as the bearer token; `instance_url` is this host.","security":[],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","assertion"],"properties":{"grant_type":{"type":"string","enum":["urn:ietf:params:oauth:grant-type:jwt-bearer"]},"assertion":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"access_token":"fipos_at_…","scope":"api","instance_url":"https://fip-os-api.vercel.app","id":"https://fip-os-api.vercel.app/id/01a1c2d3-…","token_type":"Bearer","issued_at":"1794438000000"}}}},"400":{"description":"Not a valid assertion for a key set up this way","content":{"application/json":{"example":{"error":"invalid_grant","error_description":"invalid assertion"}}}}}}},"/services/apexrest/nongmoservices/product":{"get":{"tags":["TA API v1.5"],"operationId":"v15GetProduct","summary":"Get a product (existence check)","description":"Your product by TA product ID, with its packages, categories and latest verification per program. Not yours or not found: 400 `No product found for ta_product_id: …`, as before. **v2:** `GET /v2/products/{id}` (404 when not found).","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}},{"name":"ta_product_id","in":"query","description":"TA product ID","schema":{"type":"string"},"required":true,"example":"2-12345-00001"}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001","product_name":"Example Oat Crackers","trade_name":"Example Oat Crackers","participant_id":"27123","other_certifications":[],"categories":[{"code":"SNACK-03"}],"packages":[{"package_id":"PKG-0098765","package_code":"012345678905","code_type":"UPC-A","package_category":"Retail","status":"Active"}],"most_recent_verification":{"verification_id":"V-0123456","status":"Verified","valid_from":"2026-03-01","valid_to":"2027-02-28","brand_id":"123456","verification_type":"NonGMO","facilities":[{"facility_id":"NSF-FAC-1234","facility_status":"Active"}]}}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"post":{"tags":["TA API v1.5"],"operationId":"v15CreateProducts","summary":"Add products","description":"A bare array of products. A TA product ID already yours updates it. **v2:** `PUT /v2/products/{ta_product_id}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"ta_product_id":"2-12345-00001","product_name":"Example Oat Crackers","participant_id":"27123","is_single_ingredient":false,"categories":[{"code":"SNACK-03"}]}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"patch":{"tags":["TA API v1.5"],"operationId":"v15UpdateProducts","summary":"Change products","description":"A bare array. Removing a category (`action: delete`) is done in v2 (`remove_categories`). **v2:** `PATCH /v2/products/{id}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"ta_product_id":"2-12345-00001","trade_name":"Oat Crackers, Sea Salt"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/verification":{"post":{"tags":["TA API v1.5"],"operationId":"v15CreateVerifications","summary":"Add verifications","description":"A bare array of new cycles; the answer fills each `verification_id` (the V- number). **v2:** `POST /v2/products/{id}/verifications`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"ta_product_id":"2-12345-00001","participant_id":"27123","brand_id":"123456","status":"Verified","verification_type":"nongmo","valid_from":"2026-11-01","valid_to":"2027-10-31","verification_completed":"2026-11-01"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001","verification_id":"V-0123457","status":"Verified"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"patch":{"tags":["TA API v1.5"],"operationId":"v15UpdateVerifications","summary":"Change verifications","description":"Details, and a status: On Hold, Verified (release), Withdrawn (with `withdrawal_date` and `withdrawal_reason`; the listing ends 180 days later), Terminated, Transferred or Canceled. **Changed:** statuses are checked, and your TA's verifications only. **v2:** `PATCH /v2/verifications/{ref}` and the actions (`/hold`, `/withdraw`…).","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"verification_id":"V-0123456","status":"On Hold","on_hold_date":"2026-11-12"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"verification_id":"V-0123456","status":"On Hold","on_hold_date":"2026-11-12"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/package":{"post":{"tags":["TA API v1.5"],"operationId":"v15CreatePackages","summary":"Add packages","description":"A bare array; the answer fills each `package_id`. **v2:** `POST /v2/products/{id}/packages`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"ta_product_id":"2-12345-00001","brand_id":"123456","package_code":"012345678905","code_type":"UPC-A","package_type":"Box","size":8,"unit":"Ounces","package_category":"Retail"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001","package_id":"PKG-0098765","package_code":"012345678905"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"patch":{"tags":["TA API v1.5"],"operationId":"v15UpdatePackages","summary":"Change or remove packages","description":"By `package_id`; `status: Removed` removes it. **v2:** `PATCH` or `DELETE /v2/packages/{id}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"package_id":"PKG-0098765","status":"Removed"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"package_id":"PKG-0098765","status":"Removed"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/facility":{"post":{"tags":["TA API v1.5"],"operationId":"v15AddFacilities","summary":"Add facilities to verifications","description":"A bare array. A `facility_id` FIP-OS doesn't know yet is registered from the row's `facility_name` and address (matched first by name and postal code). Use `last_inspected_date` or `last_inspected`. **v2:** `POST /v2/facilities` and `PUT /v2/verifications/{ref}/facilities/{facility_id}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"verification_id":"V-0123456","facility_id":"NSF-FAC-1234","is_owned":false,"was_inspected":true,"last_inspected_date":"2026-10-20"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"verification_id":"V-0123456","facility_id":"NSF-FAC-1234","is_owned":false,"was_inspected":true}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"patch":{"tags":["TA API v1.5"],"operationId":"v15UpdateFacilities","summary":"Change a facility's status on verifications","description":"`status: Removed` takes it off. **v2:** `DELETE /v2/verifications/{ref}/facilities/{facility_id}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"verification_id":"V-0123456","facility_id":"NSF-FAC-1234","status":"Removed"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"verification_id":"V-0123456","facility_id":"NSF-FAC-1234","status":"Removed"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/client":{"post":{"tags":["TA API v1.5"],"operationId":"v15CreateClients","summary":"Send client applications","description":"A bare array; the answer fills each `client_id`. **v2:** `POST /v2/clients`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"company_name":"Example Foods Inc.","address":{"street_address":"1 Example Way","city":"Bellingham","state":"WA","postal_code":"98225","country":"US"},"nongmo_enrolled":true,"contacts":[{"role":"primary","first_name":"Sam","last_name":"Example","email":"sam@example.com"}]}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"company_name":"Example Foods Inc.","client_id":"C-012345"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}},"patch":{"tags":["TA API v1.5"],"operationId":"v15UpdateClients","summary":"Change clients","description":"Address, contacts, company name, programs; `status: Withdrawn` withdraws (other statuses are decided by staff). **v2:** `PATCH /v2/clients/{id}`, `/withdraw`, `/contacts/{role}`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"client_id":"C-012345","status":"Withdrawn","withdraw_date":"2026-11-12"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"client_id":"C-012345","status":"Withdrawn"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/brand":{"post":{"tags":["TA API v1.5"],"operationId":"v15CreateBrands","summary":"Add brands to clients","description":"A bare array; an existing brand with that name and owner is reused. A brand owned by another company is added by staff for now. **v2:** `POST /v2/brands`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}},"example":[{"client_id":"C-012345","brand_name":"Example Brand"}]}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"client_id":"C-012345","brand_name":"Example Brand","brand_id":"123457"}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/certificate":{"get":{"tags":["TA API v1.5"],"operationId":"v15GetCertificates","summary":"Certificates","description":"By TA product ID, participant, brand or certificate number (any combination; NonGMO unless `verification_type` or a certificate number is given). **Changed:** one participant without an agreement no longer fails the answer: each line says `license_agreement_signed`, and `certificate_link` is a real link. Still across TAs until notice. **v2:** `GET /v2/certificates`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":false,"description":"Your TA's private ID. Optional on /certificate, as in v1.5.","schema":{"type":"string"}},{"name":"ta_product_id","in":"query","description":"TA product ID","schema":{"type":"string"}},{"name":"participant_id","in":"query","description":"Participant ID","schema":{"type":"string"}},{"name":"brand_id","in":"query","description":"Brand ID","schema":{"type":"string"}},{"name":"certificate_number","in":"query","description":"Certificate number","schema":{"type":"string"},"example":"C-654321-2026"},{"name":"verification_type","in":"query","description":"nongmo or nonupf","schema":{"type":"string","enum":["nongmo","nonupf"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"ta_product_id":"2-12345-00001","product_name":"Example Oat Crackers","participant_id":"27123","participant_name":"Example Foods Inc.","brand_id":"123456","brand_name":"Example Brand","certificate_number":"C-654321-2026","status":"Verified","verification_id":"V-0123456","valid_from":"2026-03-01","valid_to":"2027-02-28","verifier":"NSF","do_not_publish":false,"license_agreement_signed":true,"certificate_link":"https://app.foodintegrityproject.org/verify/2-12345-00001","verification_type":"nongmo","most_recent_verification":true}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/application":{"get":{"tags":["TA API v1.5"],"operationId":"v15GetApplications","summary":"Approved client applications","description":"Your TA's approved clients submitted (and optionally approved) since a date. **v2:** `GET /v2/clients?status=approved&updated_since=`.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}},{"name":"date_submitted","in":"query","description":"yyyy-MM-dd","schema":{"type":"string","format":"date"},"required":true,"example":"2026-10-01"},{"name":"date_approved","in":"query","description":"yyyy-MM-dd","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"pvp_id":"C-012345","participant_id":"27123","company_name":"Example Foods Inc.","date_submitted":"2026-10-03","date_approved":"2026-10-20","license_agreement_signed":true,"brands":[{"brand_id":"123456","brand_name":"Example Brand"}]}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}},"/services/apexrest/nongmoservices/prospect":{"get":{"tags":["TA API v1.5"],"operationId":"v15GetProspects","summary":"Shared prospects","description":"Prospects shared with TAs, created after a date (default yesterday). Still across TAs until notice. **v2:** `GET /v2/opportunities?updated_since=`, or the `opportunity.shared` webhook.","security":[{"salesforceSession":[]}],"parameters":[{"name":"TA-ID","in":"header","required":true,"description":"Your TA's private ID, as with Salesforce today.","schema":{"type":"string"}},{"name":"createdAfter","in":"query","description":"yyyy-MM-dd","schema":{"type":"string","format":"date"},"example":"2026-11-01"}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":["success"],"objList":[{"account_name":"Example Snacks LLC","prospect_id":"P-00123","website":"https://example.com","product_description":"Three flavors of kettle chips","interested_nongmo":true,"interested_nonupf":false,"created_date":"2026-11-03","contacts":[{"First_Name":"Alex","Last_Name":"Example","email":"alex@example.com"}]}]}}}},"400":{"description":"`status` says error: the second entry is the message, and rows that failed carry `error`","content":{"application/json":{"example":{"status":["error","No product found for ta_product_id: 2-12345-00001"]}}}},"401":{"description":"No valid session: Salesforce's `[{\"message\": \"Session expired or invalid\", \"errorCode\": \"INVALID_SESSION_ID\"}]`, or the plain text `Unauthorized` when TA-ID doesn't match your key"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A FIP-OS token with catalog.read (your explorer token, a personal token or a key's). Optional: without one the catalog answers as for the public."},"salesforceSession":{"type":"http","scheme":"bearer","description":"The access_token from POST /services/oauth2/token (your TA's key). An admin can paste a key's token from Keys and tokens (Use in the explorer)."}}}}