Write API

Alert: We are sun-setting access to the V3 APIs (Read, Schema, Facets, Submit). Learn more.


For developers making real-time writes to Factual, we provide a full featured API that allows for:

There are copious examples below to help you get started. We cannot currently guarantee that changes through the API will always propagate, but we will do our best. When your app is ready to be published, we’d love to hear from you. A quick look at your app and the data it submits may enable us to increase the expediency with which your data is made visible.

Please note – the API is intended for the use of our developer partners. If you are a SEO Agency/business listings management company and want to submit data to Factual, please contact us to apply to our Trusted Data Contributor program.

Code Examples

The examples below are shown using Factual’s Ruby driver.

The examples below are not comprehensive. For a full list of writeable fields, refer to the schema for the appropriate dataset.

Important: When you make contributions using the submit API, please be sure to store the commit_id in the JSON response returned from your submission request. Without the commit ID, we will not be able to trace the whereabouts of \
your data for any potential support request.

Here is an example response:

  factual_id: "03c26917-5d66-4de9-96bc-b13066173c65",
  new_entity: false,
  commit_id: "H4sIAAAAAAAAAA3BuxUCIAwAwIl4Sch_BAdwABLAys7C8fUOiBQ-38fr_QTknpbkQ7fZkH1ypFWPIkYzcm5TIAhE6ZayOTPC56paqJFVEXd6gyfqppZDs1WSeYlsyttbb7Ia4B8BCSrOUERlh1Y6y1RukPeaWX4s2cmO7avUPzvtmZWpAAAA"


Add or Update a new business
# configure driver: (will not be repeated in subsequent examples)
require 'factual'
factual = Factual.new("YOUR_KEY", "YOUR_SECRET")

# place details:
new_values = { :name => "Factual Book Club",
               :address => "11111 santa monica blvd",
               :address_extended => "suite 250",
               :locality => "Los Angeles",
               :region => "CA",
               :postcode => "90025",
               :latitude => 34.048193,
               :longitude => -118.445185,
	       :tel => "555-555-5555",
               :category_ids => [26, 130], # Community and Government > Education & Bookstores
	       :hours => "Mon 9:00am-5:30pm Tue-Fri 9:00am-2:00pm, 3:30pm-9:00pm Sat 11:00pm-1:30am Sun closed"

# do the submit:
factual.submit("us-sandbox", "my_apps_user").values(new_values).write


  • Always submit ALL of the business details you have, even if you are attempting to update a single field.
  • Do NOT include any existing Factual ID of the business you are attempting to update. If you are working with an existing business, simply add the entire record, as shown above. Factual will attempt to properly match the record to any pre-existing records. If this results in a duplicate, You can separately submit a flag request if the older record needs to be removed, as shown in the examples below.
  • The hours of operation in the example above show a single set of hours for Monday, two separate hours of operation (with a break in between) for Tuesday through Friday, hours that extend beyond midnight for Saturday, and closed for business Sunday. Time should be in 12 hour format, with ‘am’ or ‘pm’ indicators. Days should be three letter abbreviations (Mon, Tue, Wed, Thu, Fri, Sat, Sun).
  • International telephone numbers can be in any locally common format.

Clear incorrect data without submitting a correction
clear = factual.clear("us-sandbox", "my_apps_user", "01b4f392-c8da-4425-b817-4f8940151280")
clear = clear.fields(:latitude, :longitude) # erase the current lat/lng

Add a Crosswalk record
# update an existing row by it's Factual Id:
# Note that this call submits to the crosswalk table, not places-us or us-sandbox
crosswalk = factual.submit("crosswalk", "my_apps_user", "01b4f392-c8da-4425-b817-4f8940151280")
crosswalk = crosswalk.reference("https://twitter.com/factual") # this is the crosswalk reference being added.

Note: only crosswalk references for supported namespaces are accepted.

Flag a relocated business so that only the current location will show in search results
# this is the Factual ID of the old location (which should be redirected).
flag = factual.flag("us-sandbox", "my_apps_user", "01b4f392-c8da-4425-b817-4f8940151280", :relocated)

# this is the Factual ID of the new location
flag = flag.preferred("4e4a14fe-988c-4f03-a8e7-0efc806d0a7f")

Flag a duplicate business (same name, same addresse) for removal
# this first Factual ID is the one being requested for removal
flag = factual.flag("us-sandbox", "my_apps_user", "01b4f392-c8da-4425-b817-4f8940151280", :duplicate)

# the preferred Factual ID is the duplicate that will persist
flag = flag.preferred("4e4a14fe-988c-4f03-a8e7-0efc806d0a7f")

Flag a closed business for removal
flag = factual.flag("us-sandbox", "my_apps_user", "01b4f392-c8da-4425-b817-4f8940151280", :closed)
flag = flag.comment("I tried to go there yesterday.")

API Docs

Comprehensive documentation on all of the write APIs can be found here:


How long before new places appear in Factual?

Data written through the API should appear within minutes, provided that you are searching for the data using a comprehensive existence threshold. There may be some factors that prevent this from being the case. For example:

  • A submission does not meet the minimum validation for inclusion: it must either contain a valid postal address or lat/lng
  • Businesses with spammy names (incorporating deals or SEO-specific tags into the name, etc.) are often flagged and suppressed
  • You are submitting (on behalf of a third party) a business that we have strong evidence is no longer an ongoing concern. E.g., you are telling us about a business that many other developers or other sources have told us is closed.
Where can I test the API?

Factual provides an API sandbox for testing the API:

  • The sandbox is accessed programmatically at the API endpoint: http://api.v3.factual.com/t/us-sandbox.
  • The sandbox only supports US data for testing.
  • The sandbox cleans/validates data using the same algorithms as the production place data. As such, any test data must have a valid US Postal address.