ADT stack with a dynamic array (revision 1)
It looks very nice, code is clean and readable, not much else to change, I think...



This is more of a personal preference, not an universal recommendation: One of the things I like about C is having fine control over memory allocations, thus making it a very good choice for systems with limited memory or very rudimentary memory allocators. Because of that, I like to avoid allocating memory whenever possible, so I would not allocate each stack instance on the heap with malloc. Rather, let the user decide where to place it, be on the program stack, as a global or heap-allocated. To do that change, you'd just have to remove that allocation from create_stack and one free from delete_stack, taking a pointer to an external object in create: 

bool create_stack(stack* mystack, size_t capacity);


That might seem like a little thing, but forcing the user to dynamically allocate a stack object when it doesn't have to is suboptimal and can be a problem on systems that don't rely on virtual memory and have fragmentation issues.



I strongly recommend that you use booleans instead of error codes when a function has only two possible outcomes, success or failure. There's no universal agreement on the meaning of error codes, e.g. some return 0 on success, some return 1, some return -1 on error, and so on. This can be a major source of confusion. Use the bool type from &lt;stdbool.h&gt; whenever it makes sense.



Avoid repeating types in your malloc calls. E.g.:


item_t *elements_ptr = malloc(capacity*sizeof(item_t));



Can be refactored to:

item_t *elements_ptr = malloc(capacity * sizeof(*elements_ptr));


Notice that you can use the variable name in the sizeof expression, in this case dereferenced, since we want the size of the type itself, not the size of a pointer. Makes your life easier if you change the name of the type you are allocating; one less place to be updated.



Make sure to print errors to stderr. That's the traditional error output and allows users to filter errors from normal program output. Just replace the printf call in handle_error by fprintf(stderr).



Two last tips:

You might want to allow the users of your stack to provide their own error handler. You can achieve that with function pointers.

All functions receive pointers to stack, which could be passed in as null by error or due to some memory allocation failure. You can assert that they are not null to trap errors early and ease the debugging efforts.