I have a print operation to perform for my customer documents. I need the other standard operations to be performed as well, like add,update, delete. so, I have following:

  • For creating new customer:
    URI = /customer/{id}, type = POST, Methodname = CreateCustomer()
  • For updating:
    URI: /customer/{id}, type = PUT, method = UpdateCstomer()
  • For Delete customer:
    URI = /customer/{id}, type = DELETE, Methodname = DeleteCustomer()
  • For View:
    URI: /customer/{id}, type = GET, method = GetCustomer()

Now, if I need to print a document for that customer, I need a print function. My URI may look like this: /customer/{id}, type = POST , method = PrintCustomer(). But I have used that URI and POST type for CreateCustomer. I wanted the URI to look like this: /customer/Print/{id}, type = POST , method = PrintCustomer().

But I cannot have "Print" verb in my URI. Whats the best way to do this? I thought about /customer/document/{id} as the URI... but I will run into the same issue. I would have the CRUD operations on the "document". So, again I run out of what I would used for "print". Please advise.

  • 2
    Printing is usually a client-side operation, so I'm curious - how is your setup such that it requires you to send a command to a REST server? – Shauna Jan 4 '13 at 17:27
  • 2
    @Shauna Not necessarily, the URI may be a request to the server for a print-friendly version of the resource (ie a different view). – Evan Plaice Jan 4 '13 at 20:07
  • 1
    @EvanPlaice - Fair enough, though that still leaves the act of printing to the client (which, even after fetching a server-side print-friendly version, would then decide what device to print to and send the print command itself, even if that command goes to a print server). A request to get a print-friendly version of a resource would then logically be...well...GET. – Shauna Jan 7 '13 at 14:10
  • @Shauna Triggering a print job from a HTTP request alone would be impossible due to browser security. A request for a print-friendly version is just a GET request but you still need a way to specify that the browser should render the printable version. You could specify a different URL but that would violate the principles of REST because you're not actually requesting a different resource, just a different transform of the same resource. Hence the reason for specifying the transform via a query-parameter and/or content-type. – Evan Plaice Nov 9 '15 at 21:39
  • I don't have enough rep to post as an answer, but I find it interesting that tyk.io/rest-never-crud argues that POST /customers/123/print is a valid thing to do. – jlh Nov 6 '19 at 7:13

POST doesn't mean "create", it means "process". You can create a new resource by posting a suitable request to an existing resource (i.e. post to /customers to create a new customer). But you can also use POST to fill in all of the other actions which don't correspond to a neat CRUD paradigm.

In the case of printing, you should consider the act of printing as a resource itself. You're asking the system to create a "print job" for you. This means you can have a prints/ resource which acts as the container for all prints requested. When you want to print something you POST a document to this resource which contains all the information about the print-out you want to create, identifying the resources you want to print with links to them.

As a JSON document, it could look like this:

   contents: ["http://site/customers/12345"],
   paper-size: "A4",
   duplex: "true"

Obviously, you need to customise this to be relevant to what you want to do. The key thing is that you're identifying other resources to print by specifying their URL.

In response to the request, you could simply return a 200 OK or a 204 No-Content and treat it as a fire-and-forget process. However, if you wanted to enhance it, you could return 201 Created and specify the URL of the newly created print job, e.g. /prints/12345.

A user could then perform a GET on the resource to see the status of their print job (pending, in-progress, etc), or could request the job be cancelled by issuing a DELETE.

Once you rephrase the problem in terms of resource, the RESTful design should come naturally and give you opportunity to expand and enhance in ways you may not have immediately considered.

| improve this answer | |
  • 2
    POST usually means create/insert, whereas put usually means update save/update. That's how it's defined in REST even if it isn't how it's usually used in HTML. – Evan Plaice Jan 4 '13 at 20:01
  • 2
    @EvanPlaice the HTTP spec names PUT as the create/update verb (it uses a create+update model instead of the more familiar create + retrieve + update) and POST is the "data processing" verb, as well as the "append" verb. Roy Fielding in his blog described POST as the verb to use when you don't want to standardize the operation. POST takes on "create" semantics when you consider it appending a new item to a collections of items. In this case, Tragedian hit the nail on the head using POST for processing or adding a print job. – Rob Dec 31 '14 at 1:06
  • @RobY OK, that makes sense. As an example, PUT could be used to represent a SPROC designed to enter data into a database. Whereas, a POST could make up the intermediate steps and mutations required to collect/prepare that data. The design of the POST operation could change or be replaced as the design evolves but the PUT operations represent the model which (ideally) shouldn't change. I'd update my answer but this one already does a great job of explaining the difference. – Evan Plaice Jan 5 '15 at 5:43

I done this before. To print a document I just return a pdf version of a resource. The client only need to send a GET request for the resource with Accept header application/pdf.

This also avoid creating new URI for temporary resource like print job. Using HTTP header is also part of REST and it keeps the URI clean.

| improve this answer | |

Just add a parameter to the current URI's GET

It's pretty typical to use a URI's for multiple actions.

If you're talking about the same resource but a different action, you'd define it as a parameter.


Then where you define your GET method you detect the presence of the print parameter and handle it differently.

REST is defined in the following way:

  • POST - Create a record, asset, or resource
  • PUT - Update, a record, asset, or resource
  • DELETE - Remove a, record, asset, or resource

GET, on the other hand, is meant to be used in multiple ways because there are typically a lot of different forms that a resource may be retrieved. That's also why GET requests are represented as a query string. If you were working with a database resource you'd literally be retrieving a view via a query but REST is intentionally abstracted to a higher level because it's designed to handle with many different types of resources.

The REST specification is pretty forward thinking, even though API's are only recently starting to use it heavily.

If you're interested in learning more about REST protocols I highly suggest you read "Haters Gonna Hate HATEOAS".


@Shauna pointed out an interesting hole in my reasoning. There's no true right way and many forms are considered acceptable. I thought about it some more and since your intended use is to transform the data into a different representation, it makes sense to define the transform as a new MIME-Type.

For example, you could represent the URI as:


Where you could set the response Content-Type to text/html+print. That way you'd also have the option to define more transforms in the future.

For example:

// for application/json

// for application/atom+xml

Either way, all forms are acceptable. The implementation you decide depends more on personal preference, and the capabilities of your server.

Aside: Let me clarify since there seems to be some confusion. The 'print' query-parameter and/or content-type is used to specify how the resource is transformed. Not how to trigger a physical print job. For security reasons, hardware-level access is always left to the user/client/browser.

| improve this answer | |
  • To add - As an alternative to using the query string (?print=true), you can also use URI parameters (ie - /customer/{id}/printable). Which one you use will largely depend on the standard your system (CMS, framework, code in general) is set up to handle. Both are considered valid and acceptable. – Shauna Jan 7 '13 at 14:21
  • @Shauna Technically, the best approach would be to employ a MIME-type specific to printing with the URI '/customer/{id}+print' and a response MIME-Type of text/html+print. The advantage of such an approach being, you can create transforms for many MIME-types (ex text/html, text/x-markdown, application/json, etc) for the same URI. The disadvantage of the solution you present is, you'd need to create an additional URI (and define another route) for every different MIME-Type. It kinda defeats the purpose of using REST. – Evan Plaice Jan 7 '13 at 21:59
  • (cont) I would argue that URI-hacks are an anti-pattern introduced primarily by the ROR community but that doesn't mean they aren't useful. With the arrival of better low-level HTTPd servers it's just becoming easier to implement REST in a manner that fully leverages its potential. Things have come a long way since the days where Apache and routing everything through index.html was the only option. – Evan Plaice Jan 7 '13 at 22:13
  • 2
    GET shouldn't make state changes or have side effects. Consider that GET is idempotent, meaning that middleware may retry the request if it didn't see it go through. In this case, each retry would result in a new, freshly printed copy of the document. ;) – Rob Dec 31 '14 at 1:11
  • @RobY I was assuming that the 'print' action wasn't going to handle process of physically printing the document as that would be better served by the browser and print driver. Rather, the media/print output would return a 'print friendly' representation of the document. Therefore, idempotency is maintained. Good point tho, sending print jobs across the internet in a stateless manner would be a bad time. – Evan Plaice Jan 5 '15 at 5:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.